1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.fulcrum.cache;
21
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertSame;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27 import static org.junit.jupiter.api.Assertions.fail;
28
29 import java.util.ConcurrentModificationException;
30 import java.util.Date;
31 import java.util.List;
32
33 import org.apache.avalon.framework.component.ComponentException;
34 import org.apache.fulcrum.cache.impl.DefaultGlobalCacheService;
35 import org.apache.fulcrum.testcontainer.BaseUnit5Test;
36 import org.apache.logging.log4j.LogManager;
37 import org.apache.logging.log4j.Logger;
38 import org.junit.jupiter.api.AfterEach;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Tag;
41 import org.junit.jupiter.api.Test;
42
43
44
45
46
47
48
49
50
51 public class CacheTest extends BaseUnit5Test
52 {
53
54 protected GlobalCacheService globalCache = null;
55
56 protected static final String cacheKey = "CacheKey";
57
58 protected static final String cacheKey_2 = "CacheKey_2";
59
60 protected static final Logger log = LogManager.getLogger( CacheTest.class );
61
62 static {
63 String logSystem = System.getProperty("jcs.logSystem", null);
64 if (logSystem == null) {
65 System.setProperty("jcs.logSystem", "log4j2" );
66 log.info( "Setting jcs.logSystem to: log4j2");
67 logSystem = System.getProperty("jcs.logSystem", null);
68 }
69 log.warn( "What is the value of the jcs.logSystem: "+ logSystem);
70
71 }
72
73
74
75
76
77
78 protected String getCacheRoleName()
79 {
80 return GlobalCacheService.ROLE;
81 }
82
83 @BeforeEach
84 protected void setUp() throws Exception
85 {
86 System.out.println( "Testing service: "+ getClass().getName() + "for "+ getCacheRoleName());
87
88 try
89 {
90 globalCache = (GlobalCacheService) this
91 .lookup(getCacheRoleName());
92 }
93 catch (ComponentException e)
94 {
95 e.printStackTrace();
96 fail(e.getMessage());
97 }
98
99 }
100
101 @AfterEach
102 protected void cleanup() {
103 this.globalCache.removeObject(cacheKey);
104 }
105
106
107
108
109
110
111 @Test
112 public void testSimpleAddGetCacheObject() throws Exception
113 {
114 String testString = "This is a test";
115 Object retrievedObject = null;
116 CachedObject<String> cacheObject1 = null;
117
118 cacheObject1 = new CachedObject<String>(testString);
119 assertNotNull(cacheObject1, "Failed to create a cachable object 1" );
120
121 this.globalCache.addObject(cacheKey, cacheObject1);
122
123 retrievedObject = this.globalCache.getObject(cacheKey);
124 assertNotNull( retrievedObject, "Did not retrieve a cached object 1");
125 assertSame(
126 retrievedObject, cacheObject1,
127 "Did not retrieve a correct, expected cached object 1");
128
129 this.globalCache.removeObject(cacheKey);
130
131 retrievedObject = null;
132 cacheObject1 = null;
133 try
134 {
135 retrievedObject = this.globalCache.getObject(cacheKey);
136 assertNull(
137 retrievedObject,
138 "Retrieved the deleted cached object 1 and did not get expected ObjectExpiredException"
139 );
140 assertNotNull(
141 retrievedObject,
142 "Did not get expected ObjectExpiredException retrieving a deleted object"
143 );
144 }
145 catch (ObjectExpiredException e)
146 {
147 assertNull(
148 retrievedObject,
149 "Retrieved the deleted cached object 1, but caught expected ObjectExpiredException exception"
150 );
151 }
152
153 this.globalCache.removeObject(cacheKey);
154 }
155
156
157
158
159
160
161 @Test
162 public void test2ObjectAddGetCachedObject() throws Exception
163 {
164 String testString = "This is a test";
165 Object retrievedObject = null;
166 CachedObject<String> cacheObject1 = null;
167 CachedObject<String> cacheObject2 = null;
168
169 cacheObject1 = new CachedObject<String>(testString);
170 assertNotNull(cacheObject1, "Failed to create a cachable object 1" );
171 this.globalCache.addObject(cacheKey, cacheObject1);
172 retrievedObject = this.globalCache.getObject(cacheKey);
173 assertNotNull( retrievedObject, "Did not retrieve a cached object 1");
174 assertEquals(cacheObject1,
175 retrievedObject, "Did not retrieve correct cached object");
176
177 cacheObject2 = new CachedObject<String>(testString);
178 assertNotNull(cacheObject2, "Failed to create a cachable object 2");
179 this.globalCache.addObject(cacheKey_2, cacheObject2);
180 retrievedObject = this.globalCache.getObject(cacheKey_2);
181 assertNotNull(retrievedObject, "Did not retrieve a cached object 2");
182 assertEquals( cacheObject2,
183 retrievedObject,
184 "Did not retrieve correct cached object 2");
185
186 retrievedObject = this.globalCache.getObject(cacheKey);
187 assertNotNull(
188 retrievedObject,
189 "Did not retrieve a cached object 1. Attempt #2");
190 assertEquals(
191 cacheObject1, retrievedObject,
192 "Did not retrieve correct cached object 1. Attempt #2");
193
194 retrievedObject = this.globalCache.getObject(cacheKey);
195 assertNotNull(
196 retrievedObject,
197 "Did not retrieve a cached object 1. Attempt #3");
198 assertEquals(
199 cacheObject1, retrievedObject,
200 "Did not retrieve correct cached object 1. Attempt #3");
201
202 retrievedObject = this.globalCache.getObject(cacheKey_2);
203 assertNotNull(
204 retrievedObject,
205 "Did not retrieve a cached object 2. Attempt #2");
206 assertEquals(
207 cacheObject2, retrievedObject,
208 "Did not retrieve correct cached object 2 Attempt #2");
209
210 this.globalCache.removeObject(cacheKey);
211 this.globalCache.removeObject(cacheKey_2);
212 }
213
214
215
216
217
218
219
220 @Test
221 public void testObjectExpiration() throws Exception
222 {
223 String testString = "This is a test";
224 Object retrievedObject = null;
225 CachedObject<String> cacheObject = null;
226
227 cacheObject = new CachedObject<String>(testString, 1000);
228 assertNotNull(cacheObject, "Failed to create a cachable object");
229 long addTime = System.currentTimeMillis();
230 this.globalCache.addObject(cacheKey, cacheObject);
231
232 try
233 {
234 retrievedObject = this.globalCache.getObject(cacheKey);
235 assertNotNull( retrievedObject, "Did not retrieve a cached object");
236 assertEquals(
237 cacheObject, retrievedObject,
238 "Did not retrieve correct cached object");
239 }
240 catch (ObjectExpiredException e)
241 {
242 assertTrue(false, "Object expired early ( "
243 + (System.currentTimeMillis() - addTime) + " millis)");
244 }
245
246 Thread.sleep(1500);
247
248 try
249 {
250 retrievedObject = null;
251 retrievedObject = this.globalCache.getObject(cacheKey);
252 assertNull(retrievedObject,
253 "Retrieved the expired cached object and did not get expected ObjectExpiredException"
254 );
255 assertNotNull(retrievedObject,
256 "Did not get expected ObjectExpiredException retrieving an expired object"
257 );
258 }
259 catch (ObjectExpiredException e)
260 {
261 assertNull(retrievedObject,
262 "Retrieved the expired cached object, but caught expected ObjectExpiredException exception"
263 );
264 }
265
266 this.globalCache.removeObject(cacheKey);
267 }
268
269
270
271
272
273
274
275
276 @Test
277 public void testCacheFlush() throws Exception
278 {
279 String testString = "This is a test";
280 CachedObject<String> cacheObject = null;
281
282 cacheObject = new CachedObject<String>(testString, (getCacheRefresh() * 5) + 1);
283 assertNotNull( cacheObject, "Failed to create a cachable object");
284 this.globalCache.addObject(cacheKey, cacheObject);
285
286 Thread.sleep(getCacheRefresh() + 1);
287 assertTrue( (0 < this.globalCache
288 .getNumberOfObjects()),
289 "No object in cache before flush");
290
291 this.globalCache.flushCache();
292
293
294 Thread.sleep((getCacheRefresh() * 2) + 1);
295 assertEquals( 0, this.globalCache.getNumberOfObjects(),
296 "After refresh");
297
298 this.globalCache.removeObject(cacheKey);
299 }
300
301
302
303
304
305
306 @Test
307 public void testObjectCount() throws Exception
308 {
309 assertNotNull(this.globalCache, "Could not retrieve cache service.");
310
311 long cacheRefresh = getCacheRefresh();
312
313
314 long expireTime = cacheRefresh + cacheRefresh / 2;
315 log.info( "set expireTime in ms: {}", expireTime );
316
317 CachedObject<String> cacheObject = new CachedObject<String>("This is a test",
318 expireTime);
319 assertNotNull( cacheObject, "Failed to create a cachable object");
320
321 this.globalCache.addObject(cacheKey, cacheObject);
322 assertEquals( 1, this.globalCache
323 .getNumberOfObjects(),
324 "After adding 1 Object");
325
326
327 Thread.sleep(cacheRefresh + cacheRefresh / 3);
328 assertEquals( 1, this.globalCache
329 .getNumberOfObjects(),
330 "After one refresh");
331
332
333 Thread.sleep((cacheRefresh * 2) + cacheRefresh / 3);
334
335 assertEquals(0, this.globalCache
336 .getNumberOfObjects(),
337 "After three refreshes");
338 }
339
340
341
342
343
344
345
346
347
348
349 @Tag("LongRunning")
350 @Test
351 public void testRefreshableObject() throws Exception
352 {
353 CachedObject<RefreshableObject> retrievedObject = null;
354 RefreshableCachedObject<RefreshableObject> cacheObject = null;
355
356 cacheObject = new RefreshableCachedObject<RefreshableObject>(new RefreshableObject(),
357 getTestExpireTime());
358 assertNotNull( cacheObject, "Failed to create a cachable object");
359 long addTime = System.currentTimeMillis();
360 log.info( "Adding refreshable object to cache: {}", cacheObject );
361 this.globalCache.addObject(cacheKey, cacheObject);
362
363 try
364 {
365 retrievedObject = this.globalCache.getObject(cacheKey);
366 assertNotNull(retrievedObject, "Did not retrieve a cached object");
367 assertEquals(
368 cacheObject, retrievedObject,
369 "Did not retrieve correct cached object");
370 }
371 catch (ObjectExpiredException e)
372 {
373 assertTrue(false, "Object expired early ( "
374 + (System.currentTimeMillis() - addTime) + " millis)"
375 );
376 }
377
378 Thread.sleep(getTestExpireTime() + 1000);
379
380 try
381 {
382 retrievedObject = null;
383 retrievedObject = this.globalCache.getObject(cacheKey);
384 assertNotNull(
385 retrievedObject, "Did not retrieve a cached object, after sleep");
386 assertNotNull(
387 ((RefreshableCachedObject<?>) retrievedObject).getContents(),
388 "Cached object has no contents, after sleep.");
389 assertTrue(
390
391 (((RefreshableCachedObject<RefreshableObject>) retrievedObject)
392 .getContents().getRefreshCount() > 0),
393 "Object did not refresh.");
394 }
395 catch (ObjectExpiredException e)
396 {
397 assertTrue(false, "Received unexpected ObjectExpiredException exception "
398 + "when retrieving refreshable object after ( "
399 + (System.currentTimeMillis() - addTime) + " millis)"
400 );
401 }
402
403
404 for (int i = 0; i < 100; i++)
405 {
406 Thread.sleep(1000);
407
408 try
409 {
410 retrievedObject = null;
411 retrievedObject = this.globalCache.getObject(cacheKey);
412 assertNotNull(retrievedObject,
413 "Did not retrieve a cached object, after sleep");
414 assertNotNull(
415 ((RefreshableCachedObject<?>) retrievedObject)
416 .getContents(),
417 "Cached object has no contents, after sleep.");
418 assertTrue(
419
420 (((RefreshableCachedObject<RefreshableObject>) retrievedObject)
421 .getContents().getRefreshCount() > 0),
422 "Object did not refresh.");
423 }
424 catch (ObjectExpiredException e)
425 {
426 assertTrue(false,
427 "Received unexpected ObjectExpiredException exception "
428 + "when retrieving refreshable object after ( "
429 + (System.currentTimeMillis() - addTime)
430 + " millis)");
431 }
432 }
433
434 this.globalCache.removeObject(cacheKey);
435 }
436
437
438
439
440
441
442
443
444
445 @Tag("LongRunning")
446 @Test
447 public void testRefreshableTimeToLive() throws Exception
448 {
449 CachedObject<RefreshableObject> retrievedObject = null;
450 RefreshableCachedObject<RefreshableObject> cacheObject = null;
451
452 cacheObject = new RefreshableCachedObject<RefreshableObject>(new RefreshableObject(),
453 getTestExpireTime());
454 assertNotNull(cacheObject, "Failed to create a cachable object");
455 cacheObject.setTTL(getTestExpireTime());
456
457 assertEquals(getTestExpireTime(), cacheObject
458 .getTTL(),
459 "Returned TimeToLive");
460
461 log.info( "Adding refreshable object to cache: {}", cacheObject );
462 this.globalCache.addObject(cacheKey, cacheObject);
463 long addTime = System.currentTimeMillis();
464
465 try
466 {
467 retrievedObject = this.globalCache.getObject(cacheKey);
468 assertNotNull(retrievedObject, "Did not retrieve a cached object");
469 assertEquals(
470 cacheObject, retrievedObject,
471 "Did not retrieve correct cached object");
472 }
473 catch (ObjectExpiredException e)
474 {
475 fail("Object expired early ( "
476 + (System.currentTimeMillis() - addTime) + " millis)");
477 }
478
479 long timeout = getTestExpireTime() - 0000;
480 Thread.sleep(timeout);
481
482 try
483 {
484 retrievedObject = null;
485 retrievedObject = this.globalCache.getObject(cacheKey);
486 assertNotNull(retrievedObject,
487 "Did not retrieve a cached object, after sleep");
488 assertNotNull(
489 ((RefreshableCachedObject<?>) retrievedObject).getContents(),
490 "Cached object has no contents, after sleep.");
491
492
493
494
495
496
497
498 }
499 catch (ObjectExpiredException e)
500 {
501 assertTrue(false, "Received unexpected ObjectExpiredException exception "
502 + "when retrieving refreshable object after ( "
503 + (System.currentTimeMillis() - addTime) + " millis)");
504 }
505
506 Thread.sleep(getTestExpireTime() + 5000);
507
508 try
509 {
510 retrievedObject = null;
511 retrievedObject = this.globalCache.getObject(cacheKey);
512 assertNull(retrievedObject, "Retrieved a cached object, after exceeding TimeToLive"
513 );
514 }
515 catch (ObjectExpiredException e)
516 {
517 assertNull(retrievedObject,
518 "Retrieved the expired cached object, but caught expected ObjectExpiredException exception");
519 }
520
521 this.globalCache.removeObject(cacheKey);
522 }
523
524
525
526
527
528 @Test
529 public void testCacheGetKeyList()
530 {
531 this.globalCache.flushCache();
532 this.globalCache.addObject("date1", new CachedObject<Date>(new Date()));
533 this.globalCache.addObject("date2", new CachedObject<Date>(new Date()));
534 this.globalCache.addObject("date3", new CachedObject<Date>(new Date()));
535 assertTrue(
536 (this.globalCache.getKeys() != null),
537 "Did not get key list back.");
538 List<String> keys = this.globalCache.getKeys();
539 for (String key : keys)
540 {
541 assertTrue(
542 (key instanceof String),
543 "Key was not an instance of String.");
544 }
545
546 }
547
548
549
550
551 @Test
552 public void testCacheGetCachedObjects()
553 {
554 this.globalCache.flushCache();
555 this.globalCache.addObject("date1", new CachedObject<Date>(new Date()));
556 this.globalCache.addObject("date2", new CachedObject<Date>(new Date()));
557 this.globalCache.addObject("date3", new CachedObject<Date>(new Date()));
558 assertTrue((this.globalCache
559 .getCachedObjects() != null),
560 "Did not get object list back.");
561 List<CachedObject<?>> objects = this.globalCache.getCachedObjects();
562 for (CachedObject<?> obj : objects)
563 {
564 assertNotNull(obj, "Object was null.");
565 assertTrue(
566 (obj instanceof CachedObject),
567 "Object was not an instance of CachedObject");
568 }
569
570 }
571
572
573
574
575
576
577
578 @Test
579 public void testCacheModification()
580 {
581 this.globalCache.flushCache();
582 this.globalCache.addObject("date1", new CachedObject<Date>(new Date()));
583 this.globalCache.addObject("date2", new CachedObject<Date>(new Date()));
584 this.globalCache.addObject("date3", new CachedObject<Date>(new Date()));
585 assertTrue(
586 (this.globalCache.getKeys() != null),
587 "Did not get key list back.");
588 List<String> keys = this.globalCache.getKeys();
589 try
590 {
591 for (@SuppressWarnings("unused") String key : keys)
592 {
593 this.globalCache.addObject("date4",
594 new CachedObject<Date>(new Date()));
595 }
596 }
597 catch (ConcurrentModificationException cme)
598 {
599 fail("Caught ConcurrentModificationException adding to cache.");
600 }
601 List<CachedObject<?>> objects = this.globalCache.getCachedObjects();
602 try
603 {
604 for (@SuppressWarnings("unused") CachedObject<?> obj : objects)
605 {
606 this.globalCache.addObject("date4",
607 new CachedObject<Date>(new Date()));
608 }
609 }
610 catch (ConcurrentModificationException cme)
611 {
612 fail("Caught ConcurrentModificationException adding to cache.");
613 }
614 }
615
616
617
618
619
620
621
622 private long getCacheRefresh()
623 {
624 try
625 {
626 DefaultGlobalCacheService cache =
627 (DefaultGlobalCacheService)this.lookup(GlobalCacheService.ROLE);
628 return cache.getCacheCheckFrequency();
629 }
630 catch (ComponentException e)
631 {
632 return 5000;
633 }
634 }
635
636
637
638
639
640
641 private long getTestExpireTime()
642 {
643 return getCacheRefresh() + 1000;
644 }
645
646
647
648
649 class RefreshableObject implements Refreshable
650 {
651 private int refreshCount = 0;
652
653
654
655
656 @Override
657 public void refresh()
658 {
659 this.refreshCount++;
660 }
661
662
663
664
665
666
667 public int getRefreshCount()
668 {
669 return this.refreshCount;
670 }
671 }
672 }