1 /**
2 * Copyright 2003-2006 Greg Luck
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import java.io.Serializable;
23 import java.lang.ref.SoftReference;
24 import java.util.Date;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29
30 /**
31 * Tests for a Cache
32 *
33 * @author Greg Luck, Claus Ibsen
34 * @version $Id: CacheTest.java 141 2006-06-30 01:56:32Z gregluck $
35 */
36 public class CacheTest extends AbstractCacheTest {
37 private static final Log LOG = LogFactory.getLog(CacheTest.class.getName());
38
39
40 /**
41 * teardown
42 */
43 protected void tearDown() throws Exception {
44 super.tearDown();
45 }
46
47 /**
48 * Checks we cannot use a cache after shutdown
49 */
50 public void testUseCacheAfterManagerShutdown() throws CacheException {
51 Cache cache = manager.getCache("sampleCache1");
52 manager.shutdown();
53 Element element = new Element("key", "value");
54 try {
55 cache.getSize();
56 fail();
57 } catch (IllegalStateException e) {
58 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
59 }
60 try {
61 cache.put(element);
62 fail();
63 } catch (IllegalStateException e) {
64 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
65 }
66 try {
67 cache.get("key");
68 fail();
69 } catch (IllegalStateException e) {
70 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
71 }
72 try {
73 cache.getHitCount();
74 fail();
75 } catch (IllegalStateException e) {
76 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
77 }
78 try {
79 cache.getMemoryStoreHitCount();
80 fail();
81 } catch (IllegalStateException e) {
82 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
83 }
84 try {
85 cache.getDiskStoreHitCount();
86 fail();
87 } catch (IllegalStateException e) {
88 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
89 }
90 try {
91 cache.getMissCountExpired();
92 fail();
93 } catch (IllegalStateException e) {
94 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
95 }
96 try {
97 cache.getMissCountNotFound();
98 fail();
99 } catch (IllegalStateException e) {
100 assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
101 }
102 }
103
104 /**
105 * Checks we cannot use a cache outside the manager
106 */
107 public void testUseCacheOutsideManager() throws CacheException {
108
109 Cache cache = new Cache("testCache", 1, true, false, 5, 2);
110 Element element = new Element("key", "value");
111 try {
112 cache.getSize();
113 fail();
114 } catch (IllegalStateException e) {
115 assertEquals("The testCache Cache is not alive.", e.getMessage());
116 }
117 try {
118 cache.put(element);
119 fail();
120 } catch (IllegalStateException e) {
121 assertEquals("The testCache Cache is not alive.", e.getMessage());
122 }
123 try {
124 cache.get("key");
125 fail();
126 } catch (IllegalStateException e) {
127 assertEquals("The testCache Cache is not alive.", e.getMessage());
128 }
129 try {
130 cache.getHitCount();
131 fail();
132 } catch (IllegalStateException e) {
133 assertEquals("The testCache Cache is not alive.", e.getMessage());
134 }
135 try {
136 cache.getMemoryStoreHitCount();
137 fail();
138 } catch (IllegalStateException e) {
139 assertEquals("The testCache Cache is not alive.", e.getMessage());
140 }
141 try {
142 cache.getDiskStoreHitCount();
143 fail();
144 } catch (IllegalStateException e) {
145 assertEquals("The testCache Cache is not alive.", e.getMessage());
146 }
147 try {
148 cache.getMissCountExpired();
149 fail();
150 } catch (IllegalStateException e) {
151 assertEquals("The testCache Cache is not alive.", e.getMessage());
152 }
153 try {
154 cache.getMissCountNotFound();
155 fail();
156 } catch (IllegalStateException e) {
157 assertEquals("The testCache Cache is not alive.", e.getMessage());
158 }
159 }
160
161
162 /**
163 * Test using a cache which has been removed and replaced.
164 */
165 public void testStaleCacheReference() throws CacheException {
166 manager.addCache("test");
167 Cache cache = manager.getCache("test");
168 assertNotNull(cache);
169 cache.put(new Element("key1", "value1"));
170
171 assertEquals("value1", cache.get("key1").getObjectValue());
172 manager.removeCache("test");
173 manager.addCache("test");
174
175 try {
176 cache.get("key1");
177 fail();
178 } catch (IllegalStateException e) {
179 assertEquals("The test Cache is not alive.", e.getMessage());
180 }
181 }
182
183 /**
184 * Tests getting the cache name
185 *
186 * @throws Exception
187 */
188 public void testCacheName() throws Exception {
189 manager.addCache("test");
190 Cache cache = manager.getCache("test");
191 assertEquals("test", cache.getName());
192 assertEquals(Status.STATUS_ALIVE, cache.getStatus());
193 }
194
195
196
197 /**
198 * Tests getting the cache name
199 *
200 * @throws Exception
201 */
202 public void testCacheWithNoIdle() throws Exception {
203 Cache cache = manager.getCache("sampleCacheNoIdle");
204 assertEquals("sampleCacheNoIdle", cache.getName());
205 assertEquals(Status.STATUS_ALIVE, cache.getStatus());
206 assertEquals(0, cache.getTimeToIdleSeconds());
207 }
208
209 /**
210 * Test expiry based on time to live
211 * <cache name="sampleCacheNoIdle"
212 * maxElementsInMemory="1000"
213 * eternal="false"
214 * timeToLiveSeconds="5"
215 * overflowToDisk="false"
216 * />
217 */
218 public void testExpiryBasedOnTimeToLiveWhenNoIdle() throws Exception {
219
220 Cache cache = manager.getCache("sampleCacheNoIdle");
221 cache.put(new Element("key1", "value1"));
222 cache.put(new Element("key2", "value1"));
223 assertNotNull(cache.get("key1"));
224 assertNotNull(cache.get("key2"));
225
226
227 Thread.sleep(2000);
228 assertNotNull(cache.get("key1"));
229 assertNotNull(cache.get("key2"));
230
231
232 Thread.sleep(5001);
233 assertNull(cache.get("key1"));
234 assertNull(cache.get("key2"));
235 }
236
237
238 /**
239 * Test expiry based on time to live. Even though eternal is false, because there are no
240 * expiry or idle times, it is eternal.
241 * <cache name="sampleCacheNotEternalButNoIdleOrExpiry"
242 * maxElementsInMemory="1000"
243 * eternal="false"
244 * overflowToDisk="false"
245 * />
246 */
247 public void testExpirySampleCacheNotEternalButNoIdleOrExpiry() throws Exception {
248
249 Cache cache = manager.getCache("sampleCacheNotEternalButNoIdleOrExpiry");
250 cache.put(new Element("key1", "value1"));
251 cache.put(new Element("key2", "value1"));
252 assertNotNull(cache.get("key1"));
253 assertNotNull(cache.get("key2"));
254
255
256 Thread.sleep(2000);
257 assertNotNull(cache.get("key1"));
258 assertNotNull(cache.get("key2"));
259
260
261 Thread.sleep(5001);
262 assertNotNull(cache.get("key1"));
263 assertNotNull(cache.get("key2"));
264 }
265
266
267 /**
268 * Test overflow to disk = false
269 */
270 public void testNoOverflowToDisk() throws Exception {
271
272 Cache cache = new Cache("test", 1, false, true, 5, 2);
273 manager.addCache(cache);
274 cache.put(new Element("key1", "value1"));
275 cache.put(new Element("key2", "value1"));
276 assertNull(cache.get("key1"));
277 assertNotNull(cache.get("key2"));
278 }
279
280
281 /**
282 * Performance tests for a range of Memory Store - Disk Store combinations.
283 * <p/>
284 * This demonstrates that a memory only store is approximately an order of magnitude
285 * faster than a disk only store.
286 * <p/>
287 * It also shows that double the performance of a Disk Only store can be obtained
288 * with a maximum memory size of only 1. Accordingly a Cache created without a
289 * maximum memory size of less than 1 will issue a warning.
290 * <p/>
291 * Threading changes were made in v1.41 of DiskStore. The before and after numbers are shown.
292 */
293 public void testProportionMemoryAndDiskPerformance() throws Exception {
294 StopWatch stopWatch = new StopWatch();
295 long time = 0;
296
297
298 Cache memoryOnlyCache = new Cache("testMemoryOnly", 5000, false, false, 5, 2);
299 manager.addCache(memoryOnlyCache);
300 time = stopWatch.getElapsedTime();
301 for (int i = 0; i < 5000; i++) {
302 Integer key = new Integer(i);
303 memoryOnlyCache.put(new Element(new Integer(i), "value"));
304 memoryOnlyCache.get(key);
305 }
306 time = stopWatch.getElapsedTime();
307 LOG.info("Time for MemoryStore: " + time);
308 assertTrue("Time to put and get 5000 entries into MemoryStore", time < 300);
309
310
311
312
313 Cache diskOnlyCache = new Cache("testDiskOnly", 0, true, false, 5, 2);
314 manager.addCache(diskOnlyCache);
315 time = stopWatch.getElapsedTime();
316 for (int i = 0; i < 5000; i++) {
317 Integer key = new Integer(i);
318 diskOnlyCache.put(new Element(key, "value"));
319 diskOnlyCache.get(key);
320 }
321 time = stopWatch.getElapsedTime();
322 LOG.info("Time for DiskStore: " + time);
323 assertTrue("Time to put and get 5000 entries into DiskStore was less than 2 sec", time < 2000);
324
325
326
327
328 Cache m1d999Cache = new Cache("m1d999Cache", 1, true, false, 5, 2);
329 manager.addCache(m1d999Cache);
330 time = stopWatch.getElapsedTime();
331 for (int i = 0; i < 5000; i++) {
332 Integer key = new Integer(i);
333 m1d999Cache.put(new Element(key, "value"));
334 m1d999Cache.get(key);
335 }
336 time = stopWatch.getElapsedTime();
337 LOG.info("Time for m1d999Cache: " + time);
338 assertTrue("Time to put and get 5000 entries into m1d999Cache", time < 2000);
339
340
341
342
343 Cache m500d500Cache = new Cache("m500d500Cache", 500, true, false, 5, 2);
344 manager.addCache(m500d500Cache);
345 time = stopWatch.getElapsedTime();
346 for (int i = 0; i < 5000; i++) {
347 Integer key = new Integer(i);
348 m500d500Cache.put(new Element(key, "value"));
349 m500d500Cache.get(key);
350 }
351 time = stopWatch.getElapsedTime();
352 LOG.info("Time for m500d500Cache: " + time);
353 assertTrue("Time to put and get 5000 entries into m500d500Cache", time < 2000);
354
355 }
356
357 /**
358 * Test Caches with persistent stores dispose properly. Tests:
359 * <ol>
360 * <li>No exceptions are thrown on dispose
361 * <li>You cannot re add a cache after it has been disposed and removed
362 * <li>You can create a new cache with the same name
363 * </ol>
364 */
365 public void testCreateAddDisposeAdd() throws CacheException {
366 Cache cache = new Cache("test2", 1, true, true, 0, 0, true, 120);
367 manager.addCache(cache);
368 cache.put(new Element("key1", "value1"));
369 cache.put(new Element("key2", "value1"));
370 int sizeFromGetSize = cache.getSize();
371 int sizeFromKeys = cache.getKeys().size();
372 assertEquals(sizeFromGetSize, sizeFromKeys);
373 assertEquals(2, cache.getSize());
374
375 cache.dispose();
376 manager.removeCache("test2");
377
378
379 try {
380 manager.addCache(cache);
381 fail();
382 } catch (IllegalStateException e) {
383
384 }
385
386
387 Cache cache2 = new Cache("test2", 1, true, true, 0, 0, true, 120);
388 manager.addCache(cache2);
389 Cache cacheFromManager = manager.getCache("test2");
390 assertTrue(cacheFromManager.getStatus().equals(Status.STATUS_ALIVE));
391
392 }
393
394 /**
395 * Test expiry based on time to live
396 */
397 public void testExpiryBasedOnTimeToLive() throws Exception {
398
399 Cache cache = new Cache("test", 1, true, false, 5, 2);
400 manager.addCache(cache);
401 cache.put(new Element("key1", "value1"));
402 cache.put(new Element("key2", "value1"));
403
404
405 assertNotNull(cache.get("key1"));
406 assertNotNull(cache.get("key2"));
407 Thread.sleep(5010);
408 assertNull(cache.get("key1"));
409 assertNull(cache.get("key2"));
410 }
411
412
413 /**
414 * Tests that a cache created from defaults will expire as per
415 * the default expiry policy.
416 *
417 * @throws Exception
418 */
419 public void testExpiryBasedOnTimeToLiveForDefault() throws Exception {
420 String name = "ThisIsACacheWhichIsNotConfiguredAndWillThereforeUseDefaults";
421 Cache cache = null;
422 CacheManager manager = CacheManager.getInstance();
423 cache = manager.getCache(name);
424 if (cache == null) {
425 LOG.warn("Could not find configuration for " + name
426 + ". Configuring using the defaultCache settings.");
427 manager.addCache(name);
428 cache = manager.getCache(name);
429 }
430
431 cache.put(new Element("key1", "value1"));
432 cache.put(new Element("key2", "value1"));
433
434
435 assertNotNull(cache.get("key1"));
436 assertNotNull(cache.get("key2"));
437 Thread.sleep(10010);
438 assertNull(cache.get("key1"));
439 assertNull(cache.get("key2"));
440
441
442 }
443
444
445 /**
446 * Test expiry based on time to live.
447 * <p/>
448 * Elements are put quietly back into the cache after being cloned.
449 * The elements should expire as if the putQuiet had not happened.
450 */
451 public void testExpiryBasedOnTimeToLiveAfterPutQuiet() throws Exception {
452
453 Cache cache = new Cache("test", 1, true, false, 5, 2);
454 manager.addCache(cache);
455 cache.put(new Element("key1", "value1"));
456 cache.put(new Element("key2", "value1"));
457
458 Element element1 = cache.get("key1");
459 Element element2 = cache.get("key2");
460 assertNotNull(element1);
461 assertNotNull(element2);
462
463
464 Thread.sleep(2010);
465
466 cache.putQuiet((Element) element2.clone());
467 cache.putQuiet((Element) element2.clone());
468 Thread.sleep(3010);
469 assertNull(cache.get("key1"));
470 assertNull(cache.get("key2"));
471 }
472
473 /**
474 * Test expiry based on time to live
475 */
476 public void testNoIdleOrExpiryBasedOnTimeToLiveForEternal() throws Exception {
477
478 Cache cache = new Cache("test", 1, true, true, 5, 2);
479 manager.addCache(cache);
480 cache.put(new Element("key1", "value1"));
481 cache.put(new Element("key2", "value1"));
482
483
484 assertNotNull(cache.get("key1"));
485 assertNotNull(cache.get("key2"));
486
487
488 Thread.sleep(2010);
489 assertNotNull(cache.get("key1"));
490 assertNotNull(cache.get("key2"));
491
492
493 Thread.sleep(3010);
494 assertNotNull(cache.get("key1"));
495 assertNotNull(cache.get("key2"));
496 }
497
498 /**
499 * Test expiry based on time to idle.
500 */
501 public void testExpiryBasedOnTimeToIdle() throws Exception {
502
503 Cache cache = new Cache("test", 1, true, false, 5, 2);
504 manager.addCache(cache);
505 cache.put(new Element("key1", "value1"));
506 cache.put(new Element("key2", "value1"));
507
508
509 Element element1 = cache.get("key1");
510 Element element2 = cache.get("key2");
511 assertNotNull(element1);
512 assertNotNull(element2);
513 Thread.sleep(2010);
514 assertNull(cache.get("key1"));
515 assertNull(cache.get("key2"));
516 }
517
518
519 /**
520 * Test expiry based on time to idle.
521 */
522 public void testExpiryBasedOnTimeToIdleAfterPutQuiet() throws Exception {
523
524 Cache cache = new Cache("test", 1, true, false, 5, 3);
525 manager.addCache(cache);
526 cache.put(new Element("key1", "value1"));
527 cache.put(new Element("key2", "value1"));
528
529
530 Element element1 = cache.get("key1");
531 Element element2 = cache.get("key2");
532 assertNotNull(element1);
533 assertNotNull(element2);
534
535
536 Thread.sleep(1010);
537 element1 = cache.getQuiet("key1");
538 element2 = cache.getQuiet("key2");
539 Thread.sleep(2010);
540 assertNull(cache.getQuiet("key1"));
541 assertNull(cache.getQuiet("key2"));
542
543
544 cache.putQuiet((Element) element1.clone());
545 cache.putQuiet((Element) element2.clone());
546 assertNull(cache.get("key1"));
547 element2 = cache.get("key2");
548 assertNull(element2);
549 }
550
551 /**
552 * Test statistics
553 */
554 public void testStatistics() throws Exception {
555
556 Cache cache = new Cache("test", 1, true, false, 5, 2);
557 manager.addCache(cache);
558 cache.put(new Element("key1", "value1"));
559 cache.put(new Element("key2", "value1"));
560
561
562 cache.get("key1");
563 assertEquals(1, cache.getHitCount());
564 assertEquals(1, cache.getDiskStoreHitCount());
565 assertEquals(0, cache.getMemoryStoreHitCount());
566 assertEquals(0, cache.getMissCountExpired());
567 assertEquals(0, cache.getMissCountNotFound());
568
569
570 cache.get("key1");
571 assertEquals(2, cache.getHitCount());
572 assertEquals(1, cache.getDiskStoreHitCount());
573 assertEquals(1, cache.getMemoryStoreHitCount());
574 assertEquals(0, cache.getMissCountExpired());
575 assertEquals(0, cache.getMissCountNotFound());
576
577
578 Thread.sleep(5010);
579
580
581 cache.get("key1");
582 assertEquals(2, cache.getHitCount());
583 assertEquals(1, cache.getDiskStoreHitCount());
584 assertEquals(1, cache.getMemoryStoreHitCount());
585 assertEquals(1, cache.getMissCountExpired());
586 assertEquals(1, cache.getMissCountNotFound());
587 }
588
589 /**
590 * Test element statistics, including get and getQuiet
591 * eternal="false"
592 * timeToIdleSeconds="5"
593 * timeToLiveSeconds="10"
594 * overflowToDisk="true"
595 */
596 public void testElementStatistics() throws Exception {
597
598 Cache cache = new Cache("test", 1, true, false, 5, 2);
599 manager.addCache(cache);
600 cache.put(new Element("key1", "value1"));
601 cache.put(new Element("key2", "value1"));
602
603 Element element1 = cache.get("key1");
604 assertEquals("Should be one", 1, element1.getHitCount());
605 element1 = cache.getQuiet("key1");
606 assertEquals("Should be one", 1, element1.getHitCount());
607 element1 = cache.get("key1");
608 assertEquals("Should be two", 2, element1.getHitCount());
609 }
610
611 /**
612 * Checks that getQuiet works how we expect it to
613 *
614 * @throws Exception
615 */
616 public void testGetQuietAndPutQuiet() throws Exception {
617
618 Cache cache = new Cache("test", 1, true, false, 5, 2);
619 manager.addCache(cache);
620 cache.put(new Element("key1", "value1"));
621 cache.put(new Element("key2", "value1"));
622
623 Element element1 = cache.get("key1");
624 long lastAccessedElement1 = element1.getLastAccessTime();
625 long hitCountElement1 = element1.getHitCount();
626 assertEquals("Should be two", 1, element1.getHitCount());
627
628 element1 = cache.getQuiet("key1");
629 element1 = cache.getQuiet("key1");
630 Element clonedElement1 = (Element) element1.clone();
631 cache.putQuiet(clonedElement1);
632 element1 = cache.getQuiet("key1");
633 assertEquals("last access time should be unchanged",
634 lastAccessedElement1, element1.getLastAccessTime());
635 assertEquals("hit count should be unchanged",
636 hitCountElement1, element1.getHitCount());
637 element1 = cache.get("key1");
638 assertEquals("Should be two", 2, element1.getHitCount());
639 }
640
641 /**
642 * Test size with put and remove.
643 * <p/>
644 * It checks that size makes sense, and also that getKeys.size() matches getSize()
645 */
646 public void testSizeWithPutAndRemove() throws Exception {
647
648 Cache cache = new Cache("test2", 1, true, true, 0, 0);
649 manager.addCache(cache);
650 cache.put(new Element("key1", "value1"));
651 cache.put(new Element("key2", "value1"));
652 int sizeFromGetSize = cache.getSize();
653 int sizeFromKeys = cache.getKeys().size();
654 assertEquals(sizeFromGetSize, sizeFromKeys);
655 assertEquals(2, cache.getSize());
656 cache.put(new Element("key1", "value1"));
657 cache.put(new Element("key1", "value1"));
658
659
660 assertEquals(cache.getSize(), cache.getKeys().size());
661 assertEquals(2, cache.getSize());
662
663 cache.remove("key1");
664 assertEquals(cache.getSize(), cache.getKeys().size());
665 assertEquals(1, cache.getSize());
666 cache.remove("key2");
667 assertEquals(cache.getSize(), cache.getKeys().size());
668 assertEquals(0, cache.getSize());
669
670
671 cache.put(new Element("nullValue1", null));
672 cache.put(new Element("nullValue2", null));
673
674 assertEquals(1, cache.getSize());
675 Element nullValueElement = cache.get("nullValue2");
676 assertNull(nullValueElement.getValue());
677 assertNull(nullValueElement.getObjectValue());
678
679 }
680
681 /**
682 * Test getKeys after expiry
683 * <p/>
684 * Makes sure that if an element is expired, its key should also be expired
685 */
686 public void testGetKeysAfterExpiry() throws Exception {
687
688 Cache cache = new Cache("test2", 1, true, false, 1, 0);
689 manager.addCache(cache);
690 cache.put(new Element("key1", "value1"));
691 cache.put(new Element("key2", "value1"));
692
693 assertEquals(cache.getSize(), cache.getKeys().size());
694
695 assertEquals(2, cache.getSize());
696 Thread.sleep(1010);
697 assertEquals(2, cache.getKeys().size());
698
699 assertEquals(0, cache.getKeysWithExpiryCheck().size());
700 }
701
702 /**
703 * Test size after multiple calls, with put and remove
704 */
705 public void testSizeMultipleCallsWithPutAndRemove() throws Exception {
706
707 Cache cache = new Cache("test3", 1, true, true, 0, 0);
708 manager.addCache(cache);
709 cache.put(new Element("key1", "value1"));
710 cache.put(new Element("key2", "value1"));
711
712
713 assertEquals(2, cache.getSize());
714 assertEquals(2, cache.getSize());
715 assertEquals(2, cache.getSize());
716 assertEquals(2, cache.getSize());
717 assertEquals(2, cache.getSize());
718 cache.remove("key1");
719 assertEquals(1, cache.getSize());
720 assertEquals(1, cache.getSize());
721 assertEquals(1, cache.getSize());
722 assertEquals(1, cache.getSize());
723 assertEquals(1, cache.getSize());
724 cache.remove("key2");
725 assertEquals(0, cache.getSize());
726 assertEquals(0, cache.getSize());
727 assertEquals(0, cache.getSize());
728 assertEquals(0, cache.getSize());
729 assertEquals(0, cache.getSize());
730 }
731
732 /**
733 * Checks the expense of checking for duplicates
734 * Typical Results Duplicate Check: 8ms versus 3ms for No Duplicate Check
735 * <p/>
736 * 66ms for 1000, 6ms for no duplicate/expiry
737 * 187565 for 100000, where 500 is the in-memory size. 964ms without checking expiry. 134ms for getKeysNoDuplicateCheckTime
738 * 18795 for 100000, where 50000 is in-memory size. 873ms without checking expiry. 158ms for getKeysNoDuplicateCheckTime
739 */
740 public void testGetKeysPerformance() throws Exception {
741
742 Cache cache = new Cache("test4", 1000, true, true, 0, 0);
743 manager.addCache(cache);
744
745 for (int i = 0; i < 2000; i++) {
746 cache.put(new Element("key" + i, "value"));
747 }
748
749 Thread.sleep(1000);
750 StopWatch stopWatch = new StopWatch();
751 List keys = cache.getKeys();
752 assertTrue("Should be 2000 keys. ", keys.size() == 2000);
753 long getKeysTime = stopWatch.getElapsedTime();
754 cache.getKeysNoDuplicateCheck();
755 long getKeysNoDuplicateCheckTime = stopWatch.getElapsedTime();
756 LOG.info("Time to get 1000 keys: With Duplicate Check: " + getKeysTime
757 + " Without Duplicate Check: " + getKeysNoDuplicateCheckTime);
758 assertTrue("Getting keys took more than 150ms", getKeysTime < 100);
759 }
760
761 /**
762 * Checks the expense of checking in-memory size
763 * 3467890 bytes in 1601ms for JDK1.4.2
764 */
765 public void testCalculateInMemorySizePerformanceAndReasonableness() throws Exception {
766
767 Cache cache = new Cache("test4", 1000, true, true, 0, 0);
768 manager.addCache(cache);
769
770
771 for (int i = 0; i < 1000; i++) {
772 HashMap map = new HashMap(100);
773 for (int j = 0; j < 100; j++) {
774 map.put("key" + j, new String[]{"adfdafs", "asdfdsafa", "sdfasdf"});
775 }
776 cache.put(new Element("key" + i, map));
777 }
778
779 StopWatch stopWatch = new StopWatch();
780 long size = cache.calculateInMemorySize();
781 assertTrue("Size is " + size + ". Check it for reasonableness.", size > 100000 && size < 5000000);
782 long elapsed = stopWatch.getElapsedTime();
783 LOG.info("In-memory size in bytes: " + size
784 + " time to calculate in ms: " + elapsed);
785 assertTrue("Calculate memory size takes less than 3.5 seconds", elapsed < 3500);
786 }
787
788
789 /**
790 * Expire elements and verify size is correct.
791 */
792 public void testGetSizeAfterExpiry() throws Exception {
793
794 Cache cache = new Cache("test", 1, true, false, 5, 2);
795 manager.addCache(cache);
796 cache.put(new Element("key1", "value1"));
797 cache.put(new Element("key2", "value1"));
798
799
800 Thread.sleep(5010);
801 assertEquals(null, cache.get("key1"));
802 assertEquals(null, cache.get("key2"));
803
804 assertEquals(0, cache.getSize());
805 }
806
807 /**
808 * Test create and access times
809 */
810 public void testAccessTimes() throws Exception {
811
812 Cache cache = new Cache("test", 5, true, false, 5, 2);
813 assertEquals(Status.STATUS_UNINITIALISED, cache.getStatus());
814 manager.addCache(cache);
815 Element newElement = new Element("key1", "value1");
816 long creationTime = newElement.getCreationTime();
817 assertTrue(newElement.getCreationTime() > (System.currentTimeMillis() - 500));
818 assertTrue(newElement.getHitCount() == 0);
819 assertTrue(newElement.getLastAccessTime() == 0);
820
821 cache.put(newElement);
822
823 Element element = cache.get("key1");
824 assertNotNull(element);
825 assertEquals(creationTime, element.getCreationTime());
826 assertTrue(element.getLastAccessTime() != 0);
827 assertTrue(element.getHitCount() == 1);
828
829
830 cache.put(element);
831 element = cache.get("key1");
832 assertEquals(creationTime, element.getCreationTime());
833 assertTrue(element.getLastAccessTime() != 0);
834 assertTrue(element.getHitCount() == 1);
835 }
836
837 /**
838 * Tests initialisation failures
839 */
840 public void testInitialiseFailures() {
841 try {
842 Cache cache = new Cache("testInitialiseFailures2", 1, false, false, 5, 1);
843 cache.initialise();
844
845 cache.initialise();
846 fail("Should have thrown IllegalArgumentException");
847 } catch (IllegalStateException e) {
848
849 }
850 }
851
852 /**
853 * Tests putting nulls throws correct exception
854 *
855 * @throws Exception
856 */
857 public void testPutFailures() throws Exception {
858 Cache cache = new Cache("testPutFailures", 1, false, false, 5, 1);
859 manager.addCache(cache);
860
861 try {
862 cache.put(null);
863 fail("Should have thrown IllegalArgumentException");
864 } catch (IllegalArgumentException e) {
865
866 }
867
868 try {
869 cache.putQuiet(null);
870 fail("Should have thrown IllegalArgumentException");
871 } catch (IllegalArgumentException e) {
872
873 }
874
875
876 cache.putQuiet(new Element(null, null));
877 }
878
879 /**
880 * Tests memory store size
881 *
882 * @throws Exception
883 */
884 public void testGetMemoryStoreSize() throws Exception {
885 Cache cache = new Cache("testGetMemoryStoreSize", 10, false, false, 100, 200);
886 manager.addCache(cache);
887
888 assertEquals(0, cache.getMemoryStoreSize());
889
890 cache.put(new Element("key1", "value1"));
891 assertEquals(1, cache.getMemoryStoreSize());
892
893 cache.put(new Element("key2", "value2"));
894 assertEquals(2, cache.getMemoryStoreSize());
895
896 cache.put(new Element("key3", "value3"));
897 cache.put(new Element("key4", "value4"));
898
899 cache.put(new Element(new Object(), Object.class));
900 assertEquals(5, cache.getMemoryStoreSize());
901
902 cache.remove("key4");
903 cache.remove("key3");
904 assertEquals(3, cache.getMemoryStoreSize());
905
906 cache.removeAll();
907 assertEquals(0, cache.getMemoryStoreSize());
908 }
909
910 /**
911 * Tests flushing the cache
912 *
913 * @throws Exception
914 */
915 public void testFlushWhenOverflowToDisk() throws Exception {
916 Cache cache = new Cache("testGetMemoryStoreSize", 50, true, false, 100, 200);
917 manager.addCache(cache);
918
919 assertEquals(0, cache.getMemoryStoreSize());
920
921 for (int i = 0; i < 100; i++) {
922 cache.put(new Element("" + i, new Date()));
923 }
924
925 cache.put(new Element("key", new Object()));
926 cache.put(new Element(new Object(), new Object()));
927 cache.put(new Element(new Object(), "value"));
928
929
930 cache.put(new Element(null, null));
931 cache.put(new Element(null, null));
932
933 cache.put(new Element("nullValue", null));
934
935 assertEquals(50, cache.getMemoryStoreSize());
936 assertEquals(55, cache.getDiskStoreSize());
937
938 cache.flush();
939 assertEquals(0, cache.getMemoryStoreSize());
940
941 assertEquals(100, cache.getDiskStoreSize());
942
943 }
944
945
946 /**
947 * When flushing large MemoryStores, OutOfMemory issues can happen if we are
948 * not careful to move each to Element to the DiskStore, rather than copy them all
949 * and then delete them from the MemoryStore.
950 * <p/>
951 * This test manipulates a MemoryStore right on the edge of what can fit into the 64MB standard VM size.
952 * An inefficient spool will cause an OutOfMemoryException.
953 *
954 * @throws Exception
955 */
956 public void testMemoryEfficiencyOfFlushWhenOverflowToDisk() throws Exception {
957 Cache cache = new Cache("testGetMemoryStoreSize", 40000, true, false, 100, 200);
958 manager.addCache(cache);
959
960 assertEquals(0, cache.getMemoryStoreSize());
961
962 for (int i = 0; i < 80000; i++) {
963 cache.put(new Element("" + i, new byte[480]));
964 }
965
966 assertEquals(40000, cache.getMemoryStoreSize());
967 assertEquals(40000, cache.getDiskStoreSize());
968
969 long beforeMemory = measureMemoryUse();
970 cache.flush();
971
972
973 Thread.sleep(5000);
974
975 long afterMemory = measureMemoryUse();
976 long memoryIncrease = afterMemory - beforeMemory;
977 assertTrue(memoryIncrease < 40000000);
978
979 assertEquals(0, cache.getMemoryStoreSize());
980 assertEquals(80000, cache.getDiskStoreSize());
981
982 }
983
984
985 /**
986 * Tests using elements with null values. They should work as normal.
987 *
988 * @throws Exception
989 */
990 public void testElementWithNullValue() throws Exception {
991 Cache cache = new Cache("testElementWithNullValue", 10, false, false, 100, 200);
992 manager.addCache(cache);
993
994 Object key1 = new Object();
995 Element element = new Element(key1, null);
996 cache.put(element);
997 assertNotNull(cache.get(key1));
998 assertNotNull(cache.getQuiet(key1));
999 assertSame(element, cache.get(key1));
1000 assertSame(element, cache.getQuiet(key1));
1001 assertNull(cache.get(key1).getObjectValue());
1002 assertNull(cache.getQuiet(key1).getObjectValue());
1003
1004 assertEquals(false, cache.isExpired(element));
1005 }
1006
1007
1008 /**
1009 * Tests using elements with null values. They should work as normal.
1010 *
1011 * @throws Exception
1012 */
1013 public void testNonSerializableElement() throws Exception {
1014 Cache cache = new Cache("testElementWithNonSerializableValue", 1, true, false, 100, 200);
1015 manager.addCache(cache);
1016
1017 Element element1 = new Element("key1", new Object());
1018 Element element2 = new Element("key2", new Object());
1019 cache.put(element1);
1020 cache.put(element2);
1021
1022
1023 assertNull(cache.get("key1"));
1024
1025
1026 assertNotNull(cache.get("key2"));
1027 }
1028
1029
1030 /**
1031 * Tests what happens when an Element throws an Error on serialization. This mimics
1032 * what a nasty error like OutOfMemoryError could do.
1033 * <p/>
1034 * Before a change to the SpoolThread to handle this situation this test failed and generated the following log message.
1035 * Jun 28, 2006 7:17:16 PM net.sf.ehcache.store.DiskStore put
1036 * SEVERE: testThreadKillerCache: Elements cannot be written to disk store because the spool thread has died.
1037 *
1038 * @throws Exception
1039 */
1040 public void testSpoolThreadHandlesThreadKiller() throws Exception {
1041 Cache cache = new Cache("testThreadKiller", 1, true, false, 100, 200);
1042 manager.addCache(cache);
1043
1044 Element elementThreadKiller = new Element("key", new ThreadKiller());
1045 cache.put(elementThreadKiller);
1046 Element element1 = new Element("key1", "one");
1047 Element element2 = new Element("key2", "two");
1048 cache.put(element1);
1049 cache.put(element2);
1050
1051 Thread.sleep(2000);
1052
1053 assertNotNull(cache.get("key1"));
1054 assertNotNull(cache.get("key2"));
1055 }
1056
1057 /**
1058 * Tests disk store and memory store size
1059 *
1060 * @throws Exception
1061 */
1062 public void testGetDiskStoreSize() throws Exception {
1063 Cache cache = new Cache("testGetDiskStoreSize", 1, true, false, 100, 200);
1064 manager.addCache(cache);
1065 assertEquals(0, cache.getDiskStoreSize());
1066
1067 cache.put(new Element("key1", "value1"));
1068 assertEquals(0, cache.getDiskStoreSize());
1069 assertEquals(1, cache.getSize());
1070
1071 cache.put(new Element("key2", "value2"));
1072 assertEquals(2, cache.getSize());
1073 assertEquals(1, cache.getDiskStoreSize());
1074 assertEquals(1, cache.getMemoryStoreSize());
1075
1076 cache.put(new Element("key3", "value3"));
1077 cache.put(new Element("key4", "value4"));
1078 assertEquals(4, cache.getSize());
1079 assertEquals(3, cache.getDiskStoreSize());
1080 assertEquals(1, cache.getMemoryStoreSize());
1081
1082
1083 assertNotNull(cache.getMemoryStore().get("key4"));
1084 cache.remove("key4");
1085 assertEquals(3, cache.getSize());
1086 assertEquals(3, cache.getDiskStoreSize());
1087 assertEquals(0, cache.getMemoryStoreSize());
1088
1089
1090 assertNotNull(cache.getDiskStore().get("key1"));
1091 cache.remove("key1");
1092 assertEquals(2, cache.getSize());
1093 assertEquals(2, cache.getDiskStoreSize());
1094 assertEquals(0, cache.getMemoryStoreSize());
1095
1096
1097 cache.put(new Element("key5", "value5"));
1098 assertEquals(3, cache.getSize());
1099 assertEquals(2, cache.getDiskStoreSize());
1100 assertEquals(1, cache.getMemoryStoreSize());
1101
1102
1103 cache.removeAll();
1104 assertEquals(0, cache.getSize());
1105 assertEquals(0, cache.getDiskStoreSize());
1106 assertEquals(0, cache.getMemoryStoreSize());
1107
1108
1109 cache.put(new Element(new Object(), new Object()));
1110 cache.put(new Element(new Object(), new Object()));
1111 cache.put(new Element(new Object(), new Object()));
1112 assertEquals(1, cache.getSize());
1113 assertEquals(0, cache.getDiskStoreSize());
1114 assertEquals(1, cache.getMemoryStoreSize());
1115
1116 }
1117
1118 /**
1119 * Tests that attempting to clone a cache fails with the right exception.
1120 *
1121 * @throws Exception
1122 */
1123 public void testCloneFailures() throws Exception {
1124 Cache cache = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1125 manager.addCache(cache);
1126 try {
1127 cache.clone();
1128 fail("Should have thrown CloneNotSupportedException");
1129 } catch (CloneNotSupportedException e) {
1130
1131 }
1132 }
1133
1134
1135 /**
1136 * Tests that the toString() method works.
1137 */
1138 public void testToString() {
1139 Cache cache = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1140 assertTrue(cache.toString().indexOf("testGetMemoryStore") > -1);
1141 assertEquals(389, cache.toString().length());
1142 }
1143
1144
1145 /**
1146 * When does equals mean the same thing as == ?
1147 *
1148 * @throws CacheException
1149 * @throws InterruptedException
1150 */
1151 public void testEquals() throws CacheException, InterruptedException {
1152 Cache cache = new Cache("cache", 1, true, false, 100, 200, false, 1);
1153 manager.addCache(cache);
1154
1155 Element element1 = new Element("1", new Date());
1156 Element element2 = new Element("2", new Date());
1157 cache.put(element1);
1158 cache.put(element2);
1159
1160
1161 Element elementFromStore = cache.get("2");
1162 assertEquals(element2, elementFromStore);
1163 assertTrue(element2 == elementFromStore);
1164
1165
1166 Thread.sleep(300);
1167
1168
1169 Element elementFromDiskStore = cache.get("1");
1170 assertEquals(element1, elementFromDiskStore);
1171 assertTrue(element1 != elementFromDiskStore);
1172 }
1173
1174 /**
1175 * Tests the uniqueness of the GUID
1176 */
1177 public void testGuid() {
1178 Cache cache1 = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1179 Cache cache2 = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1180 String guid1 = cache1.getGuid();
1181 String guid2 = cache2.getGuid();
1182 assertEquals(cache1.getName(), cache2.getName());
1183 assertTrue(!guid1.equals(guid2));
1184
1185 }
1186
1187
1188 /**
1189 * SoftReference behaviour testing.
1190 */
1191 public void testSoftReferences() {
1192 Map map = new HashMap();
1193 for (int i = 0; i < 100; i++) {
1194 map.put(new Integer(i), new SoftReference(new byte[1000000]));
1195 }
1196
1197 int counter = 0;
1198 for (int i = 0; i < 100; i++) {
1199 SoftReference softReference = (SoftReference) map.get(new Integer(i));
1200 byte[] payload = (byte[]) softReference.get();
1201 if (payload != null) {
1202 LOG.info("Value found for " + i);
1203 counter++;
1204 }
1205 }
1206
1207 assertTrue("You should get more than this out of SoftReferences", counter > 32);
1208
1209 }
1210
1211
1212 /**
1213 * Does the Object API work?
1214 */
1215 public void testAPIObjectCompatibility() {
1216
1217 Cache cache = new Cache("test", 5, true, false, 5, 2);
1218 manager.addCache(cache);
1219
1220 Object objectKey = new Object();
1221 Object objectValue = new Object();
1222 Element objectElement = new Element(objectKey, objectValue);
1223 cache.put(objectElement);
1224
1225
1226 Element retrievedElement = cache.get(objectKey);
1227 assertNotNull(retrievedElement);
1228 try {
1229 retrievedElement.getObjectValue();
1230 } catch (CacheException e) {
1231
1232 }
1233
1234
1235 retrievedElement = cache.get(objectKey);
1236 assertEquals(objectElement, retrievedElement);
1237
1238
1239 retrievedElement = cache.get(objectKey);
1240 assertEquals(objectValue, retrievedElement.getObjectValue());
1241
1242 }
1243
1244
1245 /**
1246 * Does the Serializable API work?
1247 */
1248 public void testAPISerializableCompatibility() {
1249
1250 Cache cache = new Cache("test", 5, true, false, 5, 2);
1251 manager.addCache(cache);
1252
1253
1254 Serializable key = new String();
1255 Element objectElement = new Element(key, new String());
1256 cache.put(objectElement);
1257 Object retrievedObject = cache.get(key);
1258 assertEquals(retrievedObject, objectElement);
1259
1260
1261 assertEquals(objectElement, retrievedObject);
1262 }
1263
1264
1265
1266 }