X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=support%2Fgeneral%2Fsrc%2Ftest%2Fjava%2Forg%2Fwamblee%2Fcache%2FCachedObjectTest.java;h=da7d8d47bcf6e4b9301475400f07d2e4e52fe147;hb=26805fc0810098c4bd8009a35c8719478e74153e;hp=630770019b904e2977fcc610f6acaca390485f25;hpb=539c6d91b7a34e32c6669445d00e9275c337530a;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 63077001..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,16 +15,19 @@ */ 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. * @@ -36,6 +39,14 @@ public class CachedObjectTest extends TestCase { private CachedObject.Computation computation; private int ncomputations; + private synchronized void incrementComputations() { + ncomputations++; + } + + private synchronized int getComputationCount() { + return ncomputations; + } + /* * (non-Javadoc) * @@ -44,13 +55,15 @@ public class CachedObjectTest extends TestCase { @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); - }; - }; + return compute((Integer) aInvocation.getArguments()[0]); + } + }); ncomputations = 0; } @@ -96,28 +109,28 @@ public class CachedObjectTest extends TestCase { int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + 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. 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 { @@ -130,34 +143,34 @@ public class CachedObjectTest extends TestCase { int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, ncomputations); + 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. 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()); } } @@ -165,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()); } }