(no commit message)
authorErik Brakkee <erik@brakkee.org>
Tue, 22 Jun 2010 19:36:09 +0000 (19:36 +0000)
committerErik Brakkee <erik@brakkee.org>
Tue, 22 Jun 2010 19:36:09 +0000 (19:36 +0000)
support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java

index 955a71148512c47010e4f042dc318703f6629559..02d151cbd9126c75708d1c3c33d8583d6ac3970a 100644 (file)
  * 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 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<Integer, Integer> 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<Integer, Integer>() {
-            public Integer getObject(Integer aObjectKey) {
+        computation = mock(CachedObject.Computation.class);
+        when(computation.getObject(anyInt())).thenAnswer(new Answer<Integer>() {
+            public Integer answer(
+                org.mockito.invocation.InvocationOnMock invocation)
+                throws Throwable {
                 ncomputations++;
-
-                return compute(aObjectKey);
-            };
-        };
+                return compute((Integer) invocation.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<Integer, Integer> cached = createCached(new ForeverCache<Integer, Integer>());
         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,67 @@ public class CachedObjectTest extends TestCase {
         CachedObject<Integer, Integer> cached = createCached(new ZeroCache<Integer, Integer>());
         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<Integer,Integer> cached = createCached(new ZeroCache<Integer, Integer>());
+        reset(computation);
+        when(computation.getObject(anyInt())).thenReturn(1).thenAnswer(
+            new Answer<Integer>() {
+                @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<Integer,Integer> cached = createCached(new ZeroCache<Integer, Integer>());
+        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<Integer,Integer> cached = createCached(new ZeroCache<Integer, Integer>());
+        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());
     }
 }