X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=support%2Fgeneral%2Fsrc%2Ftest%2Fjava%2Forg%2Fwamblee%2Fcache%2FCachedObjectTest.java;h=da7d8d47bcf6e4b9301475400f07d2e4e52fe147;hb=26805fc0810098c4bd8009a35c8719478e74153e;hp=70d1b7af9733a6cc52769404d04b525f28f4131c;hpb=81fe8784a2182e25f92a7591ec5b0fba00afb828;p=utils diff --git a/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java b/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java index 70d1b7af..da7d8d47 100644 --- a/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java +++ b/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,165 +12,236 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.cache; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + import java.io.IOException; import junit.framework.TestCase; import net.sf.ehcache.CacheException; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.wamblee.io.TestResource; import org.wamblee.test.TimingUtils; /** - * Cached object test. - * + * Cached object test. + * * @author Erik Brakkee */ public class CachedObjectTest extends TestCase { - - /** - * - */ private static final String EHCACHE_CONFIG = "ehcache.xml"; + private static final int OBJECT_KEY = 10; + private CachedObject.Computation computation; + private int ncomputations; - private static final int OBJECT_KEY = 10; - - private CachedObject.Computation computation; - private int ncomputations; - - /* (non-Javadoc) + private synchronized void incrementComputations() { + ncomputations++; + } + + private synchronized int getComputationCount() { + return ncomputations; + } + + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); - computation = new CachedObject.Computation() { - public Integer getObject(Integer aObjectKey) { + computation = mock(CachedObject.Computation.class); + when(computation.getObject(anyInt())).thenAnswer(new Answer() { + public Integer answer( + org.mockito.invocation.InvocationOnMock aInvocation) + throws Throwable { ncomputations++; - return compute(aObjectKey); - }; - }; - ncomputations = 0; + return compute((Integer) aInvocation.getArguments()[0]); + } + }); + ncomputations = 0; } - - private int compute(int aValue) { + + private int compute(int aValue) { return aValue + 10; } - - private CachedObject createCached(Cache aCache) { - return new CachedObject(aCache, OBJECT_KEY, computation); + + private CachedObject createCached( + Cache aCache) { + return new CachedObject(aCache, OBJECT_KEY, + computation); } /** - * Verifies that upon first use, the cached object uses the computation to - * retrieve the object. - * + * Verifies that upon first use, the cached object uses the computation to + * retrieve the object. + * */ - public void testComputation() { - CachedObject cached = createCached(new ZeroCache()); + public void testComputation() { + CachedObject cached = createCached(new ZeroCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, ncomputations); } - - public void testInvalidateCache() { - CachedObject cached = createCached(new ForeverCache()); + + public void testInvalidateCache() { + CachedObject cached = createCached(new ForeverCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); assertEquals(1, ncomputations); - cached.invalidate(); + cached.invalidate(); value = cached.get(); assertEquals(compute(OBJECT_KEY), value); assertEquals(2, ncomputations); } - + public void testBehaviorEhCache() throws CacheException, IOException { - Cache cache = new EhCache(new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "test"); + Cache cache = new EhCache( + new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "test"); CachedObject cached = createCached(cache); - - assertTrue( cache == cached.getCache()); + + assertTrue(cache == cached.getCache()); + int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - // The value must still be cached. - value = cached.get(); + assertEquals(1, getComputationCount()); + // The value must still be cached. + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - - // Cache expiry. - TimingUtils.sleep(6000); - value = cached.get(); + assertEquals(1, getComputationCount()); + + // Cache expiry. + TimingUtils.sleep(6000); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); - + assertEquals(2, getComputationCount()); + // Should still be cached now. - value = cached.get(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); - + assertEquals(2, getComputationCount()); + // explicit invalidation. - cached.invalidate(); - value = cached.get(); + cached.invalidate(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(3, ncomputations); - + assertEquals(3, getComputationCount()); } - + public void testBehaviorEhCacheDefault() throws CacheException, IOException { - Cache cache = new EhCache(new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "undefined"); + Cache cache = new EhCache( + new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), + "undefined"); CachedObject cached = createCached(cache); - - assertTrue( cache == cached.getCache()); + + assertTrue(cache == cached.getCache()); + int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - // The value must still be cached. - value = cached.get(); + assertEquals(1, getComputationCount()); + // The value must still be cached. + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - - // Cache expiry. - TimingUtils.sleep(6000); - value = cached.get(); + assertEquals(1, getComputationCount()); + + // Cache expiry. + TimingUtils.sleep(6000); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); - + assertEquals(2, getComputationCount()); + // Should still be cached now. - value = cached.get(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); - + assertEquals(2, getComputationCount()); } - - - public void testBehaviorForeverCache() { - CachedObject cached = createCached(new ForeverCache()); + + public void testBehaviorForeverCache() { + CachedObject cached = createCached(new ForeverCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - for (int ncomp = 2; ncomp <= 100; ncomp++) { - value = cached.get(); + assertEquals(1, getComputationCount()); + + for (int ncomp = 2; ncomp <= 100; ncomp++) { + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, getComputationCount()); } } - - public void testBehaviorZeroCache() { - CachedObject cached = createCached(new ZeroCache()); + + public void testBehaviorZeroCache() { + CachedObject cached = createCached(new ZeroCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - for (int ncomp = 2; ncomp <= 100; ncomp++) { - value = cached.get(); + assertEquals(1, getComputationCount()); + + for (int ncomp = 2; ncomp <= 100; ncomp++) { + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(ncomp, ncomputations); + assertEquals(ncomp, getComputationCount()); } - cached.invalidate(); - value = cached.get(); + + cached.invalidate(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(101, ncomputations); + assertEquals(101, getComputationCount()); + } + + public void testPreviousValueWhileComputationBeingDone() throws Exception { + final CachedObject cached = createCached(new ZeroCache()); + reset(computation); + when(computation.getObject(anyInt())).thenReturn(1).thenAnswer( + new Answer() { + @Override + public Integer answer(InvocationOnMock aInvocation) + throws Throwable { + TimingUtils.sleep(1000); + return 2; + } + }).thenReturn(3); + + assertEquals(1, cached.get().intValue()); + Thread recompute = new Thread(new Runnable() { + + @Override + public void run() { + // will sleep for 1 second. + assertEquals(2, cached.get().intValue()); + } + }); + recompute.start(); + // Now asking the value should not recompute but should return the old + // value. + TimingUtils.sleep(500); + assertEquals(1, cached.get().intValue()); + recompute.join(); + } + + public void testNullValueWhenComputationReturnsNull() throws Exception { + final CachedObject cached = createCached(new ZeroCache()); + reset(computation); + when(computation.getObject(anyInt())).thenReturn(1).thenReturn(null) + .thenReturn(2); + + assertEquals(1, cached.get().intValue()); + assertNull(cached.get()); + assertEquals(2, cached.get().intValue()); + } + + public void testPreviousValueWhenComputationThrowsException() + throws Exception { + final CachedObject cached = createCached(new ZeroCache()); + reset(computation); + when(computation.getObject(anyInt())).thenReturn(1).thenThrow( + new RuntimeException()).thenReturn(2); + + assertEquals(1, cached.get().intValue()); + assertEquals(1, cached.get().intValue()); + assertEquals(2, cached.get().intValue()); } }