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=4ed1d2d2aae32ffe965308b6c5fbb259f71d4842;hpb=f4d446b84fa1a38ed83cd157f79fdb8233822145;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 4ed1d2d2..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,12 +1,12 @@ /* - * 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. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,45 +15,55 @@ */ package org.wamblee.cache; -import junit.framework.TestCase; +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; -import java.io.IOException; - - /** * 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; - /* (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) { - ncomputations++; - - return compute(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((Integer) aInvocation.getArguments()[0]); + } + }); ncomputations = 0; } @@ -70,7 +80,7 @@ public class CachedObjectTest extends TestCase { /** * Verifies that upon first use, the cached object uses the computation to * retrieve the object. - * + * */ public void testComputation() { CachedObject cached = createCached(new ZeroCache()); @@ -91,75 +101,76 @@ public class CachedObjectTest extends TestCase { } 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()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - // The value must still be cached. + assertEquals(1, getComputationCount()); + // The value must still be cached. value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, getComputationCount()); - // Cache expiry. + // 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(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); + assertEquals(2, getComputationCount()); // explicit invalidation. 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()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); - // The value must still be cached. + assertEquals(1, getComputationCount()); + // The value must still be cached. value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, getComputationCount()); - // Cache expiry. + // 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(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, ncomputations); + assertEquals(2, getComputationCount()); } public void testBehaviorForeverCache() { CachedObject cached = createCached(new ForeverCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, getComputationCount()); for (int ncomp = 2; ncomp <= 100; ncomp++) { value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + assertEquals(1, getComputationCount()); } } @@ -167,17 +178,70 @@ public class CachedObjectTest extends TestCase { CachedObject cached = createCached(new ZeroCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + 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(); 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()); } }