1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.ehcache.constructs.blocking;
18
19 import net.sf.ehcache.Cache;
20 import net.sf.ehcache.CacheManager;
21 import net.sf.ehcache.CacheTest;
22 import net.sf.ehcache.Ehcache;
23 import net.sf.ehcache.Element;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27
28
29
30
31
32
33
34 public class SelfPopulatingCacheTest extends CacheTest {
35 private static final Log LOG = LogFactory.getLog(SelfPopulatingCache.class.getName());
36
37
38
39
40 protected CacheManager manager;
41
42
43
44 protected SelfPopulatingCache selfPopulatingCache;
45
46
47
48 protected Ehcache cache;
49
50
51
52
53 protected volatile int cacheEntryFactoryRequests;
54
55
56
57
58 protected void setUp() throws Exception {
59 super.setUp();
60 manager = new CacheManager();
61 cache = manager.getCache("sampleIdlingExpiringCache");
62 selfPopulatingCache = new SelfPopulatingCache(cache, new CountingCacheEntryFactory("value"));
63 cacheEntryFactoryRequests = 0;
64 }
65
66
67
68
69 protected void tearDown() throws Exception {
70 selfPopulatingCache.removeAll();
71 manager.shutdown();
72 super.tearDown();
73 }
74
75
76
77
78 public void testFetch() throws Exception {
79
80
81 final Element element = selfPopulatingCache.get("key");
82 assertEquals("value", element.getValue());
83 }
84
85
86
87
88 public void testFetchUnknown() throws Exception {
89 final CacheEntryFactory factory = new CountingCacheEntryFactory(null);
90 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
91
92
93 assertNull(cache.get("key"));
94 }
95
96
97
98
99 public void testFetchFail() throws Exception {
100 final Exception exception = new Exception("Failed.");
101 final CacheEntryFactory factory = new CacheEntryFactory() {
102 public Object createEntry(final Object key) throws Exception {
103 throw exception;
104 }
105 };
106 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
107
108
109 try {
110 selfPopulatingCache.get("key");
111 fail();
112 } catch (final Exception e) {
113 Thread.sleep(20);
114
115 assertEquals("Could not fetch object for cache entry \"key\".", e.getMessage());
116 }
117 }
118
119
120
121
122 public void testCreateOnce() throws Exception {
123 final String value = "value";
124 final CountingCacheEntryFactory factory = new CountingCacheEntryFactory(value);
125 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
126
127
128 for (int i = 0; i < 5; i++) {
129 assertSame(value, selfPopulatingCache.get("key").getObjectValue());
130 assertEquals(1, factory.getCount());
131 }
132 }
133
134
135
136
137 public void testRefresh() throws Exception {
138 final String value = "value";
139 final CountingCacheEntryFactory factory = new CountingCacheEntryFactory(value);
140 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
141
142
143 assertSame(value, selfPopulatingCache.get("key").getObjectValue());
144 assertEquals(1, factory.getCount());
145
146
147 selfPopulatingCache.refresh();
148 assertEquals(2, factory.getCount());
149
150
151 assertSame(value, selfPopulatingCache.get("key").getObjectValue());
152 assertEquals(2, factory.getCount());
153
154 }
155
156
157
158
159
160 public void testThreadNaming() throws Exception {
161 final String value = "value";
162 final CountingCacheEntryFactory factory = new CountingCacheEntryFactory(value);
163 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
164
165 String originalThreadName = Thread.currentThread().getName();
166
167
168 selfPopulatingCache.get("key");
169 assertEquals(originalThreadName, Thread.currentThread().getName());
170
171
172 selfPopulatingCache.refresh();
173 assertEquals(originalThreadName, Thread.currentThread().getName());
174
175
176 selfPopulatingCache.get(null);
177 assertEquals(originalThreadName, Thread.currentThread().getName());
178
179
180 }
181
182
183
184
185
186
187
188
189
190
191
192 public void testDiscardLittleUsed() throws Exception {
193 final CacheEntryFactory factory = new CountingCacheEntryFactory("value");
194 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
195
196
197 selfPopulatingCache.get("key1");
198 selfPopulatingCache.get("key2");
199 assertEquals(2, selfPopulatingCache.getSize());
200 selfPopulatingCache.refresh();
201 assertEquals(2, selfPopulatingCache.getSize());
202 Thread.sleep(2020);
203
204
205 assertEquals(2, selfPopulatingCache.getSize());
206
207
208 selfPopulatingCache.removeAll();
209 assertEquals(0, selfPopulatingCache.getSize());
210 }
211
212
213
214
215
216
217
218
219
220
221
222 public void testDiscardLittleUsedSlow() throws Exception {
223 final CacheEntryFactory factory = new CacheEntryFactory() {
224 public Object createEntry(final Object key) throws Exception {
225 Thread.sleep(200);
226 return key;
227 }
228 };
229 selfPopulatingCache = new SelfPopulatingCache(cache, factory);
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 public void testSelfPopulatingBlocksWithTimeoutSetNull() throws InterruptedException {
254 selfPopulatingCache = new SelfPopulatingCache(new Cache("TestCache", 50, false, false, 0, 0), new NullCachePopulator());
255 selfPopulatingCache.setTimeoutMillis(200);
256 manager.addCache(selfPopulatingCache);
257
258 CacheAccessorThread[] cacheAccessorThreads = new CacheAccessorThread[10];
259
260 for (int i = 0; i < cacheAccessorThreads.length; i++) {
261 cacheAccessorThreads[i] = new CacheAccessorThread(selfPopulatingCache, "key1");
262 cacheAccessorThreads[i].start();
263
264
265 try {
266 Thread.sleep(20);
267 } catch (InterruptedException ignored) {
268
269 }
270 }
271
272
273
274 Thread.sleep(1000);
275 Thread lateThread = new CacheAccessorThread(selfPopulatingCache, "key1");
276 lateThread.start();
277 lateThread.join();
278
279 assertEquals("Too many cacheAccessorThreads tried to create selfPopulatingCache entry for key1",
280 2, cacheEntryFactoryRequests);
281 }
282
283
284
285
286
287
288
289 public void testSelfPopulatingBlocksWithoutTimeoutSetNull() throws InterruptedException {
290 selfPopulatingCache = new SelfPopulatingCache(new Cache("TestCache", 50, false, false, 0, 0), new NullCachePopulator());
291
292 manager.addCache(selfPopulatingCache);
293
294 CacheAccessorThread[] cacheAccessorThreads = new CacheAccessorThread[10];
295
296 for (int i = 0; i < cacheAccessorThreads.length; i++) {
297 cacheAccessorThreads[i] = new CacheAccessorThread(selfPopulatingCache, "key1");
298 cacheAccessorThreads[i].start();
299
300
301 try {
302 Thread.sleep(20);
303 } catch (InterruptedException ignored) {
304
305 }
306 }
307
308
309
310 Thread.sleep(12000);
311 Thread lateThread = new CacheAccessorThread(selfPopulatingCache, "key1");
312 lateThread.start();
313 lateThread.join();
314
315 assertEquals("The wrong number of cacheAccessorThreads tried to create selfPopulatingCache entry for key1",
316 11, cacheEntryFactoryRequests);
317 }
318
319
320
321
322
323
324 public void testSelfPopulatingBlocksWithoutTimeoutSetNonNull() throws InterruptedException {
325 selfPopulatingCache = new SelfPopulatingCache(new Cache("TestCache", 50, false, false, 0, 0),
326 new NonNullCachePopulator());
327
328 manager.addCache(selfPopulatingCache);
329
330 CacheAccessorThread[] cacheAccessorThreads = new CacheAccessorThread[10];
331
332 for (int i = 0; i < cacheAccessorThreads.length; i++) {
333 cacheAccessorThreads[i] = new CacheAccessorThread(selfPopulatingCache, "key1");
334 cacheAccessorThreads[i].start();
335
336
337 try {
338 Thread.sleep(20);
339 } catch (InterruptedException ignored) {
340
341 }
342 }
343
344
345
346 Thread.sleep(2000);
347 Thread lateThread = new CacheAccessorThread(selfPopulatingCache, "key1");
348 lateThread.start();
349 lateThread.join();
350
351 assertEquals("The wrong number of cacheAccessorThreads tried to create selfPopulatingCache entry for key1",
352 1, cacheEntryFactoryRequests);
353 }
354
355
356
357
358
359 private final class CacheAccessorThread extends Thread {
360 private Ehcache cache;
361 private String key;
362
363 private CacheAccessorThread(Ehcache cache, String key) {
364 this.cache = cache;
365 this.key = key;
366 }
367
368
369
370
371 public void run() {
372 try {
373 cache.get(key);
374 } catch (Exception e) {
375 LOG.info("Exception: " + e.getMessage());
376 }
377 }
378 }
379
380
381
382
383 private class NullCachePopulator implements CacheEntryFactory {
384
385 public Object createEntry(Object key) throws Exception {
386 cacheEntryFactoryRequests++;
387 Thread.sleep(1000);
388 return null;
389 }
390 }
391
392
393
394
395
396 private class NonNullCachePopulator implements CacheEntryFactory {
397
398 public Object createEntry(Object key) throws Exception {
399 cacheEntryFactoryRequests++;
400 Thread.sleep(1000);
401 return "value";
402 }
403 }
404 }
405
406