View Javadoc

1   package com.atlassian.cache;
2   
3   import org.hamcrest.Matchers;
4   import org.junit.Test;
5   
6   import java.util.concurrent.TimeUnit;
7   import java.util.concurrent.atomic.AtomicInteger;
8   
9   import static junit.framework.Assert.fail;
10  import static org.hamcrest.Matchers.hasSize;
11  import static org.hamcrest.core.IsEqual.equalTo;
12  import static org.hamcrest.core.IsInstanceOf.instanceOf;
13  import static org.junit.Assert.assertThat;
14  
15  /**
16   * Test the Lazy Cache
17   *
18   * @since 2.0
19   */
20  public abstract class AbstractCacheLazyTest
21  {
22  
23      protected CacheFactory factory;
24  
25      @Test
26      public void testGetName() throws Exception
27      {
28          Cache<String, Long> cache = makeUnexpiringCache();
29  
30          assertThat(((ManagedCache) cache).getName(), equalTo("mycache"));
31      }
32  
33      @Test
34      public void testFactoryGeneratedName() throws Exception
35      {
36          Cache<String,Long> cache = factory.getCache(Object.class, "mycache");
37  
38          assertThat(((ManagedCache) cache).getName(), equalTo("java.lang.Object.mycache"));
39      }
40  
41      @Test
42      public void testGetKeys() throws Exception
43      {
44          Cache<String, Long> cache = makeUnexpiringCache();
45          // Add some entries using the builder
46          cache.get("1");
47          cache.get("2");
48          cache.get("3");
49          cache.get("4");
50          assertThat(cache.get("1"), equalTo(1L));
51          assertThat(cache.get("2"), equalTo(2L));
52          assertThat(cache.get("3"), equalTo(3L));
53          assertThat(cache.get("4"), equalTo(4L));
54          assertSize(cache, 4);
55      }
56  
57      @Test
58      public void testConstructExpiringCache() throws Exception
59      {
60          Cache<String, Long> cache = makeExpiringCache();
61          // Add some entries using the builder
62          cache.get("1");
63          cache.get("2");
64          cache.get("3");
65          cache.get("4");
66          assertThat(cache.get("1"), equalTo(1L));
67          assertThat(cache.get("2"), equalTo(2L));
68          assertThat(cache.get("3"), equalTo(3L));
69          assertThat(cache.get("4"), equalTo(4L));
70          assertSize(cache, 4);
71      }
72  
73      @Test
74      public void testPut() throws Exception
75      {
76          Cache<String, Long> cache = makeUnexpiringCache();
77          // Add some entries using the builder
78          cache.put("1", 11L);
79          cache.put("2", 12L);
80          cache.put("3", 13L);
81          cache.put("4", 14L);
82          assertThat(cache.get("1"), equalTo(11L));
83          assertThat(cache.get("2"), equalTo(12L));
84          assertThat(cache.get("3"), equalTo(13L));
85          assertThat(cache.get("4"), equalTo(14L));
86          assertSize(cache, (4));
87      }
88  
89      @Test
90      public void testGet() throws Exception
91      {
92          Cache<String, Long> cache = makeUnexpiringCache();
93          // Add some entries using the builder
94          cache.put("1", 11L);
95          cache.put("2", 12L);
96          cache.put("3", 13L);
97          cache.put("4", 14L);
98          assertThat(cache.get("1"), equalTo(11L));
99          assertThat(cache.get("2"), equalTo(12L));
100         assertThat(cache.get("3"), equalTo(13L));
101         assertThat(cache.get("4"), equalTo(14L));
102         assertThat(cache.get("5"), equalTo(5L));
103         assertThat(cache.get("6"), equalTo(6L));
104         assertThat(cache.get("7"), equalTo(7L));
105         assertSize(cache, (7));
106     }
107 
108     @Test
109     public void testRemove() throws Exception
110     {
111         Cache<String, Long> cache = makeUnexpiringCache();
112         // Add some entries using the builder
113         cache.put("1", 11L);
114         cache.put("2", 12L);
115         cache.put("3", 13L);
116         cache.put("4", 14L);
117         assertThat(cache.get("1"), equalTo(11L));
118         assertThat(cache.get("2"), equalTo(12L));
119         assertThat(cache.get("3"), equalTo(13L));
120         assertThat(cache.get("4"), equalTo(14L));
121         assertSize(cache, (4));
122 
123         cache.remove("1");
124         cache.remove("2");
125         cache.remove("3");
126         assertSize(cache, (1));
127 
128         // Removed values should be recomputed
129         assertThat(cache.get("1"), equalTo(1L));
130         assertThat(cache.get("2"), equalTo(2L));
131         assertThat(cache.get("3"), equalTo(3L));
132         assertThat(cache.get("4"), equalTo(14L));
133         assertSize(cache, (4));
134     }
135 
136     @Test
137     public void testRemoveTwice() throws Exception
138     {
139         Cache<String, Long> cache = makeUnexpiringCache();
140 
141         // Add some entries using the builder
142         cache.put("1", 11L);
143         cache.put("2", 12L);
144         cache.put("3", 13L);
145         cache.put("4", 14L);
146         assertThat(cache.get("1"), equalTo(11L));
147         assertThat(cache.get("2"), equalTo(12L));
148         assertThat(cache.get("3"), equalTo(13L));
149         assertThat(cache.get("4"), equalTo(14L));
150         assertSize(cache, (4));
151 
152         cache.remove("1");
153         // Remove again should be a no-op
154         cache.remove("1");
155         assertSize(cache, (3));
156 
157         // Removed values should be recomputed
158         assertThat(cache.get("1"), equalTo(1L));
159         assertThat(cache.get("2"), equalTo(12L));
160         assertThat(cache.get("3"), equalTo(13L));
161         assertThat(cache.get("4"), equalTo(14L));
162         assertSize(cache, (4));
163     }
164 
165     @Test
166     public void testRemoveAll() throws Exception
167     {
168         Cache<String, Long> cache = makeUnexpiringCache();
169         // Add some entries using the builder
170         cache.put("1", 11L);
171         cache.put("2", 12L);
172         cache.put("3", 13L);
173         cache.put("4", 14L);
174         assertThat(cache.get("1"), equalTo(11L));
175         assertThat(cache.get("2"), equalTo(12L));
176         assertThat(cache.get("3"), equalTo(13L));
177         assertThat(cache.get("4"), equalTo(14L));
178         assertSize(cache, (4));
179 
180         cache.removeAll();
181         assertEmpty(cache);
182 
183         // Removed values should be recomputed
184         assertThat(cache.get("1"), equalTo(1L));
185         assertThat(cache.get("2"), equalTo(2L));
186         assertThat(cache.get("3"), equalTo(3L));
187         assertThat(cache.get("4"), equalTo(4L));
188         assertSize(cache, (4));
189     }
190 
191     @Test
192     public void testClear() throws Exception
193     {
194         Cache<String, Long> cache = makeUnexpiringCache();
195         // Add some entries using the builder
196         cache.put("1", 11L);
197         cache.put("2", 12L);
198         cache.put("3", 13L);
199         cache.put("4", 14L);
200         assertThat(cache.get("1"), equalTo(11L));
201         assertThat(cache.get("2"), equalTo(12L));
202         assertThat(cache.get("3"), equalTo(13L));
203         assertThat(cache.get("4"), equalTo(14L));
204         assertSize(cache, (4));
205 
206         ((ManagedCache) cache).clear();
207         assertEmpty(cache);
208 
209         // Removed values should be recomputed
210         assertThat(cache.get("1"), equalTo(1L));
211         assertThat(cache.get("2"), equalTo(2L));
212         assertThat(cache.get("3"), equalTo(3L));
213         assertThat(cache.get("4"), equalTo(4L));
214         assertSize(cache, (4));
215     }
216 
217     @Test
218     public void testNullHandling() throws Exception
219     {
220         Cache<String, Long> cache = makeNullReturningCache();
221 
222         // Add some entries using the builder
223         assertThat(cache.get("1"), equalTo(1L));
224         assertThat(cache.get("2"), equalTo(2L));
225         assertThat(cache.get("3"), equalTo(3L));
226         try
227         {
228             Long v = cache.get("George");
229             fail("Should throw CacheException when the loader computes a null");
230         }
231         catch (CacheException ex)
232         {
233             // OK
234         }
235         try
236         {
237             Long v = cache.get(null);
238             fail("Should throw CacheException when the Key is a null");
239         }
240         catch (CacheException ex)
241         {
242             // OK
243         }
244         assertSize(cache, (3));
245     }
246 
247     @Test
248     public void testMaxEntries() throws Exception
249     {
250         final AtomicInteger loadCounter = new AtomicInteger();
251         Cache<String, Long> cache = makeSizeLimitedCache(3, loadCounter);
252 
253         // Add some entries using the builder
254         assertThat(cache.get("1"), equalTo(1L));
255         assertThat(cache.get("1"), equalTo(1L));
256         assertThat(cache.get("2"), equalTo(2L));
257         assertThat(cache.get("3"), equalTo(3L));
258         assertThat("loadCounter", loadCounter.get(), equalTo(3));
259         assertSize(cache, (3));
260         assertThat(cache.get("3"), equalTo(3L));
261         assertThat(cache.get("3"), equalTo(3L));
262         assertThat("loadCounter", loadCounter.get(), equalTo(3));
263         assertSize(cache, (3));
264         assertThat(cache.get("4"), equalTo(4L));
265         assertThat("loadCounter", loadCounter.get(), equalTo(4));
266         assertSize(cache, (3));
267     }
268 
269     @Test
270     public void testExceptionHandling() throws Exception
271     {
272         Cache<String, Long> cache = makeExceptionalCache();
273 
274         // Add some entries using the builder
275         assertThat(cache.get("1"), equalTo(1L));
276         assertThat(cache.get("2"), equalTo(2L));
277         assertThat(cache.get("3"), equalTo(3L));
278         try
279         {
280             Long v = cache.get("George");
281             fail("Should throw CacheException when the loader throws an exception");
282         }
283         catch (CacheException ex)
284         {
285             assertThat("This exception should wrap the original Exception", ex.getCause(), instanceOf(NumberFormatException.class));
286         }
287         try
288         {
289             Long v = cache.get(null);
290             fail("Should throw CacheException when the Key is a null");
291         }
292         catch (CacheException ex)
293         {
294             assertThat("This exception should wrap the original Exception", ex.getCause(), instanceOf(NullPointerException.class));
295         }
296         assertSize(cache, (3));
297     }
298 
299     private Cache<String, Long> makeUnexpiringCache()
300     {
301         // Build a Cache using the builder
302         CacheLoader<String, Long> loader = new CacheLoader<String, Long>()
303         {
304             @Override
305             public Long load(final String key)
306             {
307                 try
308                 {
309                     return Long.valueOf(key);
310                 }
311                 catch (NumberFormatException e)
312                 {
313                     return -21L;
314                 }
315             }
316         };
317         final Cache<String, Long> cache = factory.getCache("mycache", loader);
318         assertEmpty(cache);
319         return cache;
320     }
321 
322     private Cache<String, Long> makeSizeLimitedCache(final int maxEntries, final AtomicInteger loadCounter)
323     {
324         // Build a Cache using the builder
325         CacheLoader<String, Long> loader = new CacheLoader<String, Long>()
326         {
327             @Override
328             public Long load(final String key)
329             {
330                 loadCounter.incrementAndGet();
331                 return Long.valueOf(key);
332             }
333         };
334         CacheSettings settings = new CacheSettingsBuilder().maxEntries(maxEntries).build();
335         final Cache<String, Long> cache = factory.getCache("mycache", loader, settings);
336         assertEmpty(cache);
337         return cache;
338     }
339 
340     private Cache<String, Long> makeExpiringCache()
341     {
342         // Build a Cache using the builder
343         CacheLoader<String, Long> loader = new CacheLoader<String, Long>()
344         {
345             @Override
346             public Long load(final String key)
347             {
348                 try
349                 {
350                     return Long.valueOf(key);
351                 }
352                 catch (NumberFormatException e)
353                 {
354                     return -21L;
355                 }
356             }
357         };
358         CacheSettings settings = new CacheSettingsBuilder().expireAfterAccess(10, TimeUnit.MILLISECONDS).build();
359         final Cache<String, Long> cache = factory.getCache("mycache", loader, settings);
360         assertEmpty(cache);
361         return cache;
362     }
363 
364     private Cache<String,Long> makeNullReturningCache()
365     {
366         // Build a Cache using the builder
367         CacheLoader<String, Long> loader = new CacheLoader<String, Long>()
368         {
369             @Override
370             public Long load(final String key)
371             {
372                 try
373                 {
374                     return Long.valueOf(key);
375                 }
376                 catch (NumberFormatException e)
377                 {
378                     return null;
379                 }
380             }
381         };
382         final Cache<String, Long> cache = factory.getCache("mycache", loader);
383         assertEmpty(cache);
384         return cache;
385     }
386 
387     private Cache<String,Long> makeExceptionalCache()
388     {
389         // Build a Cache using the builder
390         CacheLoader<String, Long> loader = new CacheLoader<String, Long>()
391         {
392             @Override
393             public Long load(final String key)
394             {
395                 return Long.valueOf(key);
396             }
397         };
398         final Cache<String, Long> cache = factory.getCache("mycache", loader);
399         assertEmpty(cache);
400         return cache;
401     }
402 
403 
404 
405     // Hiding broken type inferences
406 
407     private static <K,V> void assertEmpty(Cache<K,V> cache)
408     {
409         assertThat(cache.getKeys(), Matchers.<K>empty());
410     }
411 
412     private static <K,V> void assertSize(Cache<K,V> cache, final int expectedSize)
413     {
414         assertThat(cache.getKeys(), hasSize(expectedSize));
415     }
416 }