From a2efaf4dc15aa02f382f5d27a9e9ba4afc25abd6 Mon Sep 17 00:00:00 2001 From: Alex Feinberg Date: Sun, 28 Aug 2011 20:46:31 -0700 Subject: [PATCH] Add a unit test for CachedCallable --- src/java/voldemort/utils/CachedCallable.java | 11 +++- .../voldemort/utils/CachedCallableTest.java | 58 +++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 test/unit/voldemort/utils/CachedCallableTest.java diff --git a/src/java/voldemort/utils/CachedCallable.java b/src/java/voldemort/utils/CachedCallable.java index 94429da7cf..518f08343c 100644 --- a/src/java/voldemort/utils/CachedCallable.java +++ b/src/java/voldemort/utils/CachedCallable.java @@ -11,21 +11,28 @@ public class CachedCallable implements Callable { private final Callable inner; private final long ttlMs; + private final Time time; private final AtomicReference valueRef; private volatile long lastCalledMs; public CachedCallable(Callable inner, long ttlMs) { + this(inner, ttlMs, SystemTime.INSTANCE); + } + + public CachedCallable(Callable inner, + long ttlMs, + Time time) { this.inner = inner; this.ttlMs = ttlMs; + this.time = time; valueRef = new AtomicReference(); } - public T call() throws Exception { T value = valueRef.get(); - long now = System.currentTimeMillis(); + long now = time.getMilliseconds(); if(value == null || now - lastCalledMs > ttlMs) { T newValue = inner.call(); if(valueRef.compareAndSet(value, newValue)) { diff --git a/test/unit/voldemort/utils/CachedCallableTest.java b/test/unit/voldemort/utils/CachedCallableTest.java new file mode 100644 index 0000000000..e2515cde91 --- /dev/null +++ b/test/unit/voldemort/utils/CachedCallableTest.java @@ -0,0 +1,58 @@ +package voldemort.utils; + + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import voldemort.MockTime; + +import java.util.concurrent.Callable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class CachedCallableTest { + + private static final long CACHE_TTL_MS = 1000; + private static final long CALL_RESULT = 0xdeaddeadl; + + @Mock + private Callable inner; + + private CachedCallable cachedCallable; + private MockTime mockTime; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + when(inner.call()).thenReturn(CALL_RESULT); + mockTime = new MockTime(); + cachedCallable = new CachedCallable(inner, + CACHE_TTL_MS, + mockTime); + } + + @Test + public void testCall() throws Exception { + assertEquals((long) cachedCallable.call(), CALL_RESULT); + } + + @Test + public void testCaching() throws Exception { + cachedCallable.call(); + cachedCallable.call(); + verify(inner, times(1)).call(); + } + + @Test + public void testTtl() throws Exception { + cachedCallable.call(); + cachedCallable.call(); + verify(inner, times(1)).call(); + mockTime.addMilliseconds(1001); + when(inner.call()).thenReturn(CALL_RESULT + 1l); + assertEquals((long) cachedCallable.call(), CALL_RESULT + 1l); + verify(inner, times(2)).call(); + } +}