View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
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 static junit.framework.Assert.assertSame;
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertNull;
24  import static org.junit.Assert.assertTrue;
25  import static org.junit.Assert.fail;
26  
27  import java.io.ByteArrayInputStream;
28  import java.io.Serializable;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.Date;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Random;
36  import java.util.Vector;
37  import java.util.concurrent.ExecutionException;
38  import java.util.concurrent.ExecutorService;
39  import java.util.concurrent.Executors;
40  import java.util.concurrent.Future;
41  import java.util.concurrent.TimeUnit;
42  import java.util.concurrent.atomic.AtomicLong;
43  
44  import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
45  import net.sf.ehcache.config.CacheConfiguration;
46  import net.sf.ehcache.event.CacheEventListener;
47  import net.sf.ehcache.event.RegisteredEventListeners;
48  import net.sf.ehcache.exceptionhandler.ExceptionHandlingDynamicCacheProxy;
49  import net.sf.ehcache.loader.CacheLoader;
50  import net.sf.ehcache.loader.CountingCacheLoader;
51  import net.sf.ehcache.loader.ExceptionThrowingLoader;
52  import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
53  import net.sf.ehcache.store.compound.CompoundStore;
54  
55  import org.junit.After;
56  import org.junit.Ignore;
57  import org.junit.Test;
58  import org.slf4j.Logger;
59  import org.slf4j.LoggerFactory;
60  
61  /***
62   * Tests for a Cache
63   * <p/>
64   * Since expiration is rounded on seconds, we need to at least go up to the last
65   * millisecond before the next second in many of the tests
66   *
67   * @author Greg Luck, Claus Ibsen
68   * @version $Id: CacheTest.java 2539 2010-07-02 10:58:13Z alexsnaps $
69   */
70  public class CacheTest extends AbstractCacheTest {
71  
72      private static final Logger LOG = LoggerFactory.getLogger(CacheTest.class.getName());
73  
74  
75      /***
76       * teardown
77       */
78      @Override
79      @After
80      public void tearDown() throws Exception {
81          super.tearDown();
82      }
83  
84      /***
85       * Gets the sample cache 1
86       */
87      protected Ehcache getSampleCache1() {
88          Cache cache = manager.getCache("sampleCache1");
89          return cache;
90      }
91  
92      /***
93       * Creates a cache
94       *
95       * @return
96       */
97      protected Ehcache createTestCache() {
98          Cache cache = new Cache("test4", 1000, true, true, 0, 0);
99          manager.addCache(cache);
100         return cache;
101     }
102 
103     /***
104      * Checks we cannot use a cache after shutdown
105      */
106     @Test
107     public void testUseCacheAfterManagerShutdown() throws CacheException {
108         Ehcache cache = getSampleCache1();
109         manager.shutdown();
110         Element element = new Element("key", "value");
111         try {
112             cache.getSize();
113             fail();
114         } catch (IllegalStateException e) {
115             assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
116         }
117         try {
118             cache.put(element);
119             fail();
120         } catch (IllegalStateException e) {
121             assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
122         }
123         try {
124             cache.get("key");
125             fail();
126         } catch (IllegalStateException e) {
127             assertEquals("The sampleCache1 Cache is not alive.", e.getMessage());
128         }
129 
130     }
131     
132     /***
133      * Test multiple calls to dispose is not a problem
134      */
135     @Test
136     public void testMultipleDispose() {
137         Ehcache cache = new Cache("testCache", 1, true, false, 5, 2);
138         manager.addCache(cache);
139         cache.dispose();
140         // call dispose multiple times, shouldn't throw IllegalStateException anymore
141         for (int i = 0; i < 10; i++) {
142             cache.dispose();
143         }
144     }
145 
146 
147     /***
148      * Checks we cannot use a cache outside the manager
149      */
150     @Test
151     public void testUseCacheOutsideManager() throws CacheException {
152         //Not put into manager.
153         Cache cache = new Cache("testCache", 1, true, false, 5, 2);
154         Element element = new Element("key", "value");
155         try {
156             cache.getSize();
157             fail();
158         } catch (IllegalStateException e) {
159             assertEquals("The testCache Cache is not alive.", e.getMessage());
160         }
161         try {
162             cache.put(element);
163             fail();
164         } catch (IllegalStateException e) {
165             assertEquals("The testCache Cache is not alive.", e.getMessage());
166         }
167         try {
168             cache.get("key");
169             fail();
170         } catch (IllegalStateException e) {
171             assertEquals("The testCache Cache is not alive.", e.getMessage());
172         }
173     }
174 
175     /***
176      * Checks when and how we can set the cache name.
177      */
178     @Test
179     public void testSetCacheName() throws CacheException {
180         //Not put into manager.
181         Ehcache cache = new Cache("testCache", 1, true, false, 5, 2);
182 
183         try {
184             cache.setName(null);
185             fail();
186         } catch (IllegalArgumentException e) {
187             //expected
188         }
189 
190         cache.setName("name/with/slash");
191 
192         manager.addCache(cache);
193         try {
194             cache.setName("trying_to_change_name_after_initialised");
195             fail();
196         } catch (IllegalStateException e) {
197             //expected
198         }
199     }
200 
201 
202     /***
203      * Test using a cache which has been removed and replaced.
204      */
205     @Test
206     public void testStaleCacheReference() throws CacheException {
207         manager.addCache("test");
208         Ehcache cache = manager.getCache("test");
209         assertNotNull(cache);
210         cache.put(new Element("key1", "value1"));
211 
212         assertEquals("value1", cache.get("key1").getObjectValue());
213         manager.removeCache("test");
214         manager.addCache("test");
215 
216         try {
217             cache.get("key1");
218             fail();
219         } catch (IllegalStateException e) {
220             assertEquals("The test Cache is not alive.", e.getMessage());
221         }
222     }
223 
224     /***
225      * Tests getting the cache name
226      *
227      * @throws Exception
228      */
229     @Test
230     public void testCacheName() throws Exception {
231         manager.addCache("test");
232         Ehcache cache = manager.getCache("test");
233         assertEquals("test", cache.getName());
234         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
235     }
236 
237 
238     /***
239      * Tests getting the cache name
240      *
241      * @throws Exception
242      */
243     @Test
244     public void testCacheWithNoIdle() throws Exception {
245         Ehcache cache = manager.getCache("sampleCacheNoIdle");
246         assertEquals("sampleCacheNoIdle", cache.getName());
247         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
248         assertEquals(0, cache.getCacheConfiguration().getTimeToIdleSeconds());
249     }
250 
251     /***
252      * Test expiry based on time to live
253      * <cache name="sampleCacheNoIdle"
254      * maxElementsInMemory="1000"
255      * eternal="false"
256      * timeToLiveSeconds="5"
257      * overflowToDisk="false"
258      * />
259      */
260     @Test
261     public void testExpiryBasedOnTimeToLiveWhenNoIdle() throws Exception {
262         //Set size so the second element overflows to disk.
263         Ehcache cache = manager.getCache("sampleCacheNoIdle");
264         cache.put(new Element("key1", "value1"));
265         cache.put(new Element("key2", "value1"));
266         assertNotNull(cache.get("key1"));
267         assertNotNull(cache.get("key2"));
268 
269         //Test time to idle. Should not idle out because not specified
270         Thread.sleep(2999);
271         assertNotNull(cache.get("key1"));
272         assertNotNull(cache.get("key2"));
273 
274         //Test time to live.
275         Thread.sleep(5999);
276         assertNull(cache.get("key1"));
277         assertNull(cache.get("key2"));
278     }
279 
280 
281     /***
282      * Tests that the version and lastUpdate get upped for each put.
283      * <cache name="sampleCacheNoIdle"
284      * maxElementsInMemory="1000"
285      * eternal="false"
286      * timeToLiveSeconds="5"
287      * overflowToDisk="false"
288      * />
289      */
290     @Test
291     public void testLastUpdate() throws Exception {
292         //Set size so the second element overflows to disk.
293         Ehcache cache = manager.getCache("sampleCache1");
294         long beforeElementCreation = System.currentTimeMillis();
295         //put in delay because time resolution is not exact on Windows
296         Thread.sleep(10);
297         cache.put(new Element("key1", "value1"));
298         Element element = cache.get("key1");
299         assertTrue(element.getCreationTime() >= beforeElementCreation);
300         LOG.info("version: " + element.getVersion());
301         LOG.info("creationTime: " + element.getCreationTime());
302         LOG.info("lastUpdateTime: " + element.getLastUpdateTime());
303         assertEquals(0, element.getLastUpdateTime());
304 
305         cache.put(new Element("key1", "value1"));
306         element = cache.get("key1");
307         LOG.info("version: " + element.getVersion());
308         LOG.info("creationTime: " + element.getCreationTime());
309         LOG.info("lastUpdateTime: " + element.getLastUpdateTime());
310 
311         cache.put(new Element("key1", "value1"));
312         element = cache.get("key1");
313         LOG.info("version: " + element.getVersion());
314         LOG.info("creationTime: " + element.getCreationTime());
315         LOG.info("lastUpdateTime: " + element.getLastUpdateTime());
316     }
317 
318 
319     /***
320      * When to search the disk store
321      */
322     @Test
323     public void testOverflowToDiskAndDiskPersistent() throws Exception {
324         Ehcache cache = manager.getCache("sampleIdlingExpiringCache");
325 
326         for (int i = 0; i < 1001; i++) {
327             cache.put(new Element("key" + i, "value1"));
328         }
329 
330         assertNotNull(cache.get("key0"));
331 
332         for (int i = 0; i < 1001; i++) {
333             cache.put(new Element("key" + i, "value1"));
334             assertNotNull(cache.get("key" + i));
335         }
336     }
337 
338 
339     /***
340      * Test expiry based on time to live for a cache with config
341      * <cache name="sampleCacheNoIdle"
342      * maxElementsInMemory="1000"
343      * eternal="false"
344      * timeToLiveSeconds="5"
345      * overflowToDisk="false"
346      * />
347      * <p/>
348      * where an Elment override is set on TTL
349      */
350     @Test
351     public void testExpiryBasedOnTimeToLiveWhenNoIdleElementOverride() throws Exception {
352         //Set size so the second element overflows to disk.
353         Ehcache cache = manager.getCache("sampleCacheNoIdle");
354         Element element1 = new Element("key1", "value1");
355         element1.setTimeToLive(3);
356         cache.put(element1);
357 
358         Element element2 = new Element("key2", "value1");
359         element2.setTimeToLive(3);
360         cache.put(element2);
361         assertNotNull(cache.get("key1"));
362         assertNotNull(cache.get("key2"));
363 
364         //Test time to idle. Should not idle out because not specified
365         Thread.sleep(1999);
366         assertNotNull(cache.get("key1"));
367         assertNotNull(cache.get("key2"));
368 
369         //Test time to live.
370         Thread.sleep(4999);
371         assertNull(cache.get("key1"));
372         assertNull(cache.get("key2"));
373     }
374 
375     /***
376      * Test expiry based on time to live for a cache with config
377      * <cache name="sampleCacheNoIdle"
378      * maxElementsInMemory="1000"
379      * eternal="false"
380      * timeToLiveSeconds="5"
381      * overflowToDisk="false"
382      * />
383      * <p/>
384      * where an Element override is set on TTL
385      */
386     @Test
387     public void testExpiryBasedOnTimeToIdleElementOverride() throws Exception {
388         //Set size so the second element overflows to disk.
389         Ehcache cache = manager.getCache("sampleCacheNoIdle");
390         assertEquals(30, cache.getCacheConfiguration().getDiskSpoolBufferSizeMB());
391         Element element1 = new Element("key1", "value1");
392         element1.setTimeToIdle(1);
393         cache.put(element1);
394 
395         Element element2 = new Element("key2", "value1");
396         element2.setTimeToIdle(1);
397         cache.put(element2);
398         assertNotNull(cache.get("key1"));
399         assertNotNull(cache.get("key2"));
400 
401         //Test time to idle
402         Thread.sleep(1999);
403         assertNull(cache.get("key1"));
404         assertNull(cache.get("key2"));
405 
406     }
407 
408 
409     /***
410      * Test expiry based on time to live for a cache with config
411      * <cache name="sampleCacheNoIdle"
412      * maxElementsInMemory="1000"
413      * eternal="false"
414      * timeToLiveSeconds="5"
415      * overflowToDisk="false"
416      * />
417      * <p/>
418      * where an Elment override is set on TTL
419      */
420     @Test
421     public void testExpiryBasedEternalElementOverride() throws Exception {
422         //Set size so the second element overflows to disk.
423         Ehcache cache = manager.getCache("sampleCacheNoIdle");
424         Element element1 = new Element("key1", "value1");
425         element1.setEternal(true);
426         cache.put(element1);
427 
428         Element element2 = new Element("key2", "value1");
429         element2.setEternal(true);
430         cache.put(element2);
431         assertNotNull(cache.get("key1"));
432         assertNotNull(cache.get("key2"));
433 
434         Thread.sleep(5999);
435         assertNotNull(cache.get("key1"));
436         assertNotNull(cache.get("key2"));
437 
438     }
439 
440     /***
441      * Test expiry based on time to live. Even though eternal is false, because there are no
442      * expiry or idle times, it is eternal.
443      * <cache name="sampleCacheNotEternalButNoIdleOrExpiry"
444      * maxElementsInMemory="1000"
445      * eternal="false"
446      * overflowToDisk="false"
447      * />
448      */
449     @Test
450     public void testExpirySampleCacheNotEternalButNoIdleOrExpiry() throws Exception {
451         //Set size so the second element overflows to disk.
452         Ehcache cache = manager.getCache("sampleCacheNotEternalButNoIdleOrExpiry");
453         cache.put(new Element("key1", "value1"));
454         cache.put(new Element("key2", "value1"));
455         assertNotNull(cache.get("key1"));
456         assertNotNull(cache.get("key2"));
457 
458         //Test time to idle. Should not idle out because not specified
459         Thread.sleep(2999);
460         assertNotNull(cache.get("key1"));
461         assertNotNull(cache.get("key2"));
462 
463         //Test time to live.
464         Thread.sleep(5999);
465         assertNotNull(cache.get("key1"));
466         assertNotNull(cache.get("key2"));
467     }
468 
469 
470     /***
471      * Test overflow to disk = false
472      */
473     @Test
474     public void testNoOverflowToDisk() throws Exception {
475         //Set size so the second element overflows to disk.
476         Cache cache = new Cache("test", 1, false, true, 5, 2);
477         manager.addCache(cache);
478         cache.put(new Element("key1", "value1"));
479         cache.put(new Element("key2", "value1"));
480         assertNull(cache.get("key1"));
481         assertNotNull(cache.get("key2"));
482     }
483 
484 
485     /***
486      * Test Caches with persistent stores dispose properly. Tests:
487      * <ol>
488      * <li>No exceptions are thrown on dispose
489      * <li>You cannot re add a cache after it has been disposed and removed
490      * <li>You can create a new cache with the same name
491      * </ol>
492      */
493     @Test
494     public void testCreateAddDisposeAdd() throws CacheException {
495         Cache cache = new Cache("test2", 1, true, true, 0, 0, true, 120);
496         manager.addCache(cache);
497         cache.put(new Element("key1", "value1"));
498         cache.put(new Element("key2", "value1"));
499         int sizeFromGetSize = cache.getSize();
500         int sizeFromKeys = cache.getKeys().size();
501         assertEquals(sizeFromGetSize, sizeFromKeys);
502         assertEquals(2, cache.getSize());
503         //package protected method, only available to tests. Called by teardown
504         cache.dispose();
505         manager.removeCache("test2");
506 
507 
508         try {
509             manager.addCache(cache);
510             fail();
511         } catch (CacheException e) {
512             //expected
513         }
514 
515         //Add a new cache with the same name as the disposed one.
516         Cache cache2 = new Cache("test2", 1, true, true, 0, 0, true, 120);
517         manager.addCache(cache2);
518         Ehcache cacheFromManager = manager.getCache("test2");
519         assertTrue(cacheFromManager.getStatus().equals(Status.STATUS_ALIVE));
520 
521     }
522 
523     /***
524      * Test expiry based on time to live
525      */
526     @Test
527     public void testExpiryBasedOnTimeToLive() throws Exception {
528         //Set size so the second element overflows to disk.
529         Cache cache = new Cache("test", 1, true, false, 3, 0);
530         manager.addCache(cache);
531         cache.put(new Element("key1", "value1"));
532         cache.put(new Element("key2", "value1"));
533 
534         //Test time to live
535         assertNotNull(cache.get("key1"));
536         assertNotNull(cache.get("key2"));
537         Thread.sleep(1020);
538         //Test time to live
539         assertNotNull(cache.get("key1"));
540         assertNotNull(cache.get("key2"));
541         Thread.sleep(1020);
542         //Test time to live
543         assertNotNull(cache.get("key1"));
544         assertNotNull(cache.get("key2"));
545         Thread.sleep(1959);
546         assertNull(cache.get("key1"));
547         assertNull(cache.get("key2"));
548     }
549 
550 
551     /***
552      * Tests that a cache created from defaults will expire as per
553      * the default expiry policy.
554      *
555      * @throws Exception
556      */
557     @Test
558     public void testExpiryBasedOnTimeToLiveForDefault() throws Exception {
559         String name = "ThisIsACacheWhichIsNotConfiguredAndWillThereforeUseDefaults";
560         Ehcache cache = null;
561         CacheManager manager = CacheManager.getInstance();
562         cache = manager.getCache(name);
563         if (cache == null) {
564             LOG.warn("Could not find configuration for " + name
565                     + ". Configuring using the defaultCache settings.");
566             manager.addCache(name);
567             cache = manager.getCache(name);
568         }
569 
570         cache.put(new Element("key1", "value1"));
571         cache.put(new Element("key2", "value1"));
572 
573         //Test time to live
574         assertNotNull(cache.get("key1"));
575         assertNotNull(cache.get("key2"));
576         Thread.sleep(10999);
577         assertNull(cache.get("key1"));
578         assertNull(cache.get("key2"));
579 
580 
581     }
582 
583 
584     /***
585      * Test expiry based on time to live.
586      * <p/>
587      * Elements are put quietly back into the cache after being cloned.
588      * The elements should expire as if the putQuiet had not happened.
589      */
590     @Test
591     public void testExpiryBasedOnTimeToLiveAfterPutQuiet() throws Exception {
592         //Set size so the second element overflows to disk.
593         Cache cache = new Cache("test", 1, true, false, 5, 2);
594         manager.addCache(cache);
595         cache.put(new Element("key1", "value1"));
596         cache.put(new Element("key2", "value1"));
597 
598         Element element1 = cache.get("key1");
599         Element element2 = cache.get("key2");
600         assertNotNull(element1);
601         assertNotNull(element2);
602 
603         //Test time to live
604         Thread.sleep(2999);
605         //Should not affect age
606         cache.putQuiet((Element) element2.clone());
607         cache.putQuiet((Element) element2.clone());
608         Thread.sleep(3000);
609         assertNull(cache.get("key1"));
610         assertNull(cache.get("key2"));
611     }
612 
613     /***
614      * Test expiry based on time to live
615      */
616     @Test
617     public void testNoIdleOrExpiryBasedOnTimeToLiveForEternal() throws Exception {
618         //Set size so the second element overflows to disk.
619         Cache cache = new Cache("test", 1, true, true, 5, 2);
620         manager.addCache(cache);
621         cache.put(new Element("key1", "value1"));
622         cache.put(new Element("key2", "value1"));
623 
624         //Test time to live
625         assertNotNull(cache.get("key1"));
626         assertNotNull(cache.get("key2"));
627 
628         //Check that we did not idle out
629         Thread.sleep(2999);
630         assertNotNull(cache.get("key1"));
631         assertNotNull(cache.get("key2"));
632 
633         //Check that we did not expire out
634         Thread.sleep(3999);
635         assertNotNull(cache.get("key1"));
636         assertNotNull(cache.get("key2"));
637     }
638 
639     /***
640      * Test expiry based on time to idle.
641      */
642     @Test
643     public void testExpiryBasedOnTimeToIdle() throws Exception {
644         //Set size so the second element overflows to disk.
645         Cache cache = new Cache("test", 1, true, false, 6, 2);
646         manager.addCache(cache);
647         cache.put(new Element("key1", "value1"));
648         cache.put(new Element("key2", "value1"));
649 
650         //Test time to idle
651         Element element1 = cache.get("key1");
652         Element element2 = cache.get("key2");
653         assertNotNull(element1);
654         assertNotNull(element2);
655         Thread.sleep(3000);
656         assertNull(cache.get("key1"));
657         assertNull(cache.get("key2"));
658 
659         //Test effect of get
660         cache.put(new Element("key1", "value1"));
661         cache.put(new Element("key2", "value1"));
662         Thread.sleep(1000);
663         assertNotNull(cache.get("key1"));
664         assertNotNull(cache.get("key2"));
665 
666         Thread.sleep(3000);
667         assertNull(cache.get("key1"));
668         assertNull(cache.get("key2"));
669     }
670 
671 
672     /***
673      * Test expiry based on time to idle.
674      */
675     @Test
676     public void testExpiryBasedOnTimeToIdleAfterPutQuiet() throws Exception {
677         //Set size so the second element overflows to disk.
678         Cache cache = new Cache("test", 1, true, false, 5, 3);
679         manager.addCache(cache);
680         cache.put(new Element("key1", "value1"));
681         cache.put(new Element("key2", "value1"));
682 
683         //Test time to idle
684         Element element1 = cache.get("key1");
685         Element element2 = cache.get("key2");
686         assertNotNull(element1);
687         assertNotNull(element2);
688 
689         //Now, getQuiet and check still times out 2 seconds after last get
690         Thread.sleep(1050);
691         element1 = cache.getQuiet("key1");
692         element2 = cache.getQuiet("key2");
693         Thread.sleep(2949);
694         assertNull(cache.getQuiet("key1"));
695         assertNull(cache.getQuiet("key2"));
696 
697         //Now put back in with putQuiet. Should be immediately expired
698         cache.putQuiet((Element) element1.clone());
699         cache.putQuiet((Element) element2.clone());
700         assertNull(cache.get("key1"));
701         element2 = cache.get("key2");
702         assertNull(element2);
703     }
704 
705     /***
706      * Test element statistics, including get and getQuiet
707      * eternal="false"
708      * timeToIdleSeconds="5"
709      * timeToLiveSeconds="10"
710      * overflowToDisk="true"
711      */
712     @Test
713     public void testElementStatistics() throws Exception {
714         //Set size so the second element overflows to disk.
715         Cache cache = new Cache("test", 1, true, false, 5, 2);
716         manager.addCache(cache);
717         
718         cache.setStatisticsEnabled(true);
719         
720         cache.put(new Element("key1", "value1"));
721         cache.put(new Element("key2", "value1"));
722 
723         Element element1 = cache.get("key1");
724         assertEquals("Should be one", 1, element1.getHitCount());
725         element1 = cache.getQuiet("key1");
726         assertEquals("Should be one", 1, element1.getHitCount());
727         element1 = cache.get("key1");
728         assertEquals("Should be two", 2, element1.getHitCount());
729     }
730 
731     /***
732      * Test cache statistics, including get and getQuiet
733      */
734     @Test
735     public void testCacheStatistics() throws Exception {
736         //Set size so the second element overflows to disk.
737         Cache cache = new Cache("test", 1, true, false, 5, 2);
738         manager.addCache(cache);
739         
740         cache.setStatisticsEnabled(true);
741         
742         cache.put(new Element("key1", "value1"));
743         cache.put(new Element("key2", "value1"));
744 
745         Element element1 = cache.get("key1");
746         assertEquals("Should be one", 1, element1.getHitCount());
747         assertEquals("Should be one", 1, cache.getStatistics().getCacheHits());
748         element1 = cache.getQuiet("key1");
749         assertEquals("Should be one", 1, element1.getHitCount());
750         assertEquals("Should be one", 1, cache.getStatistics().getCacheHits());
751         element1 = cache.get("key1");
752         assertEquals("Should be two", 2, element1.getHitCount());
753         assertEquals("Should be two", 2, cache.getStatistics().getCacheHits());
754 
755 
756         assertEquals("Should be 0", 0, cache.getStatistics().getCacheMisses());
757         cache.get("doesnotexist");
758         assertEquals("Should be 1", 1, cache.getStatistics().getCacheMisses());
759 
760 
761     }
762 
763     /***
764      * Checks that getQuiet works how we expect it to
765      *
766      * @throws Exception
767      */
768     @Test
769     public void testGetQuietAndPutQuiet() throws Exception {
770         //Set size so the second element overflows to disk.
771         Cache cache = new Cache("test", 1, true, false, 5, 2);
772         manager.addCache(cache);
773         
774         cache.setStatisticsEnabled(true);
775         
776         cache.put(new Element("key1", "value1"));
777         cache.put(new Element("key2", "value1"));
778 
779         Element element1 = cache.get("key1");
780         long lastAccessedElement1 = element1.getLastAccessTime();
781         long hitCountElement1 = element1.getHitCount();
782         assertEquals("Should be two", 1, element1.getHitCount());
783         assertEquals(1L, cache.getStatistics().getCacheHits());
784 
785         element1 = cache.getQuiet("key1");
786         element1 = cache.getQuiet("key1");
787         assertEquals(1L, cache.getStatistics().getCacheHits());
788         Element clonedElement1 = (Element) element1.clone();
789         cache.putQuiet(clonedElement1);
790         element1 = cache.getQuiet("key1");
791         assertEquals("last access time should be unchanged",
792                 lastAccessedElement1, element1.getLastAccessTime());
793         assertEquals("hit count should be unchanged",
794                 hitCountElement1, element1.getHitCount());
795         element1 = cache.get("key1");
796         assertEquals("Should be two", 2, element1.getHitCount());
797     }
798 
799     /***
800      * Test size with put and remove.
801      * <p/>
802      * It checks that size makes sense, and also that getKeys.size() matches getSize()
803      */
804     @Test
805     public void testSizeWithPutAndRemove() throws Exception {
806         //Set size so the second element overflows to disk.
807         Cache cache = new Cache("test2", 1, true, true, 0, 0);
808         manager.addCache(cache);
809         cache.put(new Element("key1", "value1"));
810         cache.put(new Element("key2", "value1"));
811         int sizeFromGetSize = cache.getSize();
812         int sizeFromKeys = cache.getKeys().size();
813         assertEquals(sizeFromGetSize, sizeFromKeys);
814         assertEquals(2, cache.getSize());
815         cache.put(new Element("key1", "value1"));
816         cache.put(new Element("key1", "value1"));
817 
818         //key1 should be in the Disk Store
819         assertEquals(cache.getSize(), cache.getKeys().size());
820         assertEquals(2, cache.getSize());
821         //there were two of these, so size will now be one
822         cache.remove("key1");
823         assertEquals(cache.getSize(), cache.getKeys().size());
824         assertEquals(1, cache.getSize());
825         cache.remove("key2");
826         assertEquals(cache.getSize(), cache.getKeys().size());
827         assertEquals(0, cache.getSize());
828 
829         //try null values
830         cache.removeAll();
831         Object object1 = new Object();
832         Object object2 = new Object();
833         cache.put(new Element(object1, null));
834         cache.put(new Element(object2, null));
835         //Cannot overflow therefore just one
836         assertEquals(1, cache.getSize());
837         Element nullValueElement = cache.get(object2);
838         assertNull(nullValueElement.getValue());
839         assertNull(nullValueElement.getObjectValue());
840 
841     }
842 
843     /***
844      * Test getKeys after expiry
845      * <p/>
846      * Makes sure that if an element is expired, its key should also be expired
847      */
848     @Test
849     public void testGetKeysAfterExpiry() throws Exception {
850         //Set size so the second element overflows to disk.
851         Cache cache = new Cache("test2", 1, true, false, 1, 0);
852         manager.addCache(cache);
853         String key1 = "key1";
854         cache.put(new Element(key1, "value1"));
855         cache.put(new Element("key2", "value1"));
856         //getSize uses getKeys().size(), so these should be the same
857         assertEquals(cache.getSize(), cache.getKeys().size());
858         //getKeys does not do an expiry check, so the expired elements are counted
859         assertEquals(2, cache.getSize());
860         String keyFromDisk = (String) cache.get(key1).getObjectKey();
861         assertEquals(key1, keyFromDisk);
862         Thread.sleep(1999);
863         assertEquals(2, cache.getKeys().size());
864         //getKeysWithExpiryCheck does check and gives the correct answer of 0
865         assertEquals(0, cache.getKeysWithExpiryCheck().size());
866     }
867 
868 
869     /***
870      * Answers the question of whether key references are preserved as elements are written to disk.
871      * This is not a mandatory part of the API. If this test breaks in future it should be removed.
872      */
873     @Test
874     public void testKeysEqualsEquals() throws Exception {
875         //Set size so the second element overflows to disk.
876         Cache cache = new Cache("test2", 0, true, false, 1, 0);
877         manager.addCache(cache);
878         String key1 = "key1";
879         cache.put(new Element(key1, "value1"));
880         cache.put(new Element("key2", "value1"));
881         String keyFromDisk = (String) cache.get(key1).getObjectKey();
882         assertTrue(key1 == keyFromDisk);
883     }
884 
885     /***
886      * Test size after multiple calls, with put and remove
887      */
888     @Test
889     public void testSizeMultipleCallsWithPutAndRemove() throws Exception {
890         //Set size so the second element overflows to disk.
891         Cache cache = new Cache("test3", 1, true, true, 0, 0);
892         manager.addCache(cache);
893         cache.put(new Element("key1", "value1"));
894         cache.put(new Element("key2", "value1"));
895 
896         //key1 should be in the Disk Store
897         assertEquals(2, cache.getSize());
898         assertEquals(2, cache.getSize());
899         assertEquals(2, cache.getSize());
900         assertEquals(2, cache.getSize());
901         assertEquals(2, cache.getSize());
902         cache.remove("key1");
903         assertEquals(1, cache.getSize());
904         assertEquals(1, cache.getSize());
905         assertEquals(1, cache.getSize());
906         assertEquals(1, cache.getSize());
907         assertEquals(1, cache.getSize());
908         cache.remove("key2");
909         assertEquals(0, cache.getSize());
910         assertEquals(0, cache.getSize());
911         assertEquals(0, cache.getSize());
912         assertEquals(0, cache.getSize());
913         assertEquals(0, cache.getSize());
914     }
915 
916 
917     /***
918      * Expire elements and verify size is correct.
919      */
920     @Test
921     public void testGetSizeAfterExpiry() throws Exception {
922         //Set size so the second element overflows to disk.
923         Cache cache = new Cache("test", 1, true, false, 1, 0);
924         manager.addCache(cache);
925         cache.put(new Element("key1", "value1"));
926         cache.put(new Element("key2", "value1"));
927 
928         // Let the idle expire
929         Thread.sleep(1999);
930         assertEquals(null, cache.get("key1"));
931         assertEquals(null, cache.get("key2"));
932 
933         assertEquals(0, cache.getSize());
934     }
935 
936     /***
937      * Test create and access times
938      */
939     @Test
940     public void testAccessTimes() throws Exception {
941         //Set size so the second element overflows to disk.
942         Cache cache = new Cache("test", 5, true, false, 5, 2);
943         assertEquals(Status.STATUS_UNINITIALISED, cache.getStatus());
944         manager.addCache(cache);
945         Element newElement = new Element("key1", "value1");
946         long creationTime = newElement.getCreationTime();
947         assertTrue(newElement.getCreationTime() > (System.currentTimeMillis() - 500));
948         assertTrue(newElement.getHitCount() == 0);
949         assertTrue(newElement.getLastAccessTime() == 0);
950 
951         cache.put(newElement);
952 
953         Element element = cache.get("key1");
954         assertNotNull(element);
955         assertEquals(creationTime, element.getCreationTime());
956         assertTrue(element.getLastAccessTime() != 0);
957         assertTrue(element.getHitCount() == 1);
958 
959         //Check that access statistics were reset but not creation time
960         cache.put(element);
961         element = cache.get("key1");
962         assertEquals(creationTime, element.getCreationTime());
963         assertTrue(element.getLastAccessTime() != 0);
964         assertTrue(element.getHitCount() == 1);
965     }
966 
967     /***
968      * Tests initialisation failures
969      */
970     @Test
971     public void testInitialiseFailures() {
972         try {
973             Cache cache = new Cache("testInitialiseFailures2", 1, false, false, 5, 1);
974             cache.initialise();
975 
976             cache.initialise();
977             fail("Should have thrown IllegalArgumentException");
978         } catch (IllegalStateException e) {
979             //noop
980         }
981     }
982 
983     /***
984      * Nulls should be ignored
985      *
986      * @throws Exception
987      */
988     @Test
989     public void testNullPuts() throws Exception {
990         Cache cache = new Cache("testPutFailures", 1, false, false, 5, 1);
991         manager.addCache(cache);
992 
993         cache.put(null);
994         cache.put(null, false);
995         cache.putQuiet(null);
996         cache.putQuiet(new Element(null, null));
997 
998         //Null Elements like this are ignored
999         cache.put(new Element(null, "dog"));
1000         cache.put(new Element(null, null));
1001 
1002         //Null Elements like this are ignored
1003         cache.putQuiet(new Element(null, "dog"));
1004         cache.putQuiet(new Element(null, null));
1005     }
1006 
1007 
1008     /***
1009      * Tests cache, memory store and disk store sizes from config
1010      */
1011     @Test
1012     public void testSizes() throws Exception {
1013         Ehcache cache = getSampleCache1();
1014 
1015         assertEquals(0, cache.getMemoryStoreSize());
1016 
1017         for (int i = 0; i < 10010; i++) {
1018             cache.put(new Element("key" + i, "value1"));
1019         }
1020 
1021         Thread.sleep(1000);
1022 
1023         assertEquals(10010, cache.getSize());
1024         assertEquals(10000, cache.getMemoryStoreSize());
1025         assertEquals(10, cache.getDiskStoreSize());
1026 
1027         //NonSerializable
1028         Thread.sleep(15);
1029         cache.put(new Element(new Object(), Object.class));
1030 
1031         Thread.sleep(1000);
1032         
1033         assertEquals(10011, cache.getSize());
1034         assertEquals(11, cache.getDiskStoreSize());
1035         assertEquals(10000, cache.getMemoryStoreSize());
1036         assertEquals(10000, cache.getMemoryStoreSize());
1037         assertEquals(10000, cache.getMemoryStoreSize());
1038         assertEquals(10000, cache.getMemoryStoreSize());
1039 
1040 
1041         cache.remove("key4");
1042         cache.remove("key3");
1043 
1044         assertEquals(10009, cache.getSize());
1045         //cannot make any guarantees as no elements have been getted, and all are equally likely to be evicted.
1046         //assertEquals(10000, cache.getMemoryStoreSize());
1047         //assertEquals(9, cache.getDiskStoreSize());
1048 
1049 
1050         cache.removeAll();
1051         assertEquals(0, cache.getSize());
1052         assertEquals(0, cache.getMemoryStoreSize());
1053         assertEquals(0, cache.getDiskStoreSize());
1054 
1055     }
1056 
1057 
1058     //@Test
1059 
1060     public void testSizesContinuous() throws Exception {
1061         while (true) {
1062             testFlushWhenOverflowToDisk();
1063         }
1064     }
1065 
1066 
1067     /***
1068      * Tests flushing the cache, with the default, which is to clear
1069      * <p/>
1070      * Note: Which element gets evicted is probabilistic. 1.5 and earlier were deterministic. Thus
1071      * the variation in what gets into the DiskStore.
1072      *
1073      * @throws Exception
1074      */
1075     @Test
1076     public void testFlushWhenOverflowToDisk() throws Exception {
1077         if (manager.getCache("testFlushWhenOverflowToDisk") == null) {
1078             manager.addCache(new Cache("testFlushWhenOverflowToDisk", 50, true, false, 100, 200, true, 120));
1079         }
1080         Cache cache = manager.getCache("testFlushWhenOverflowToDisk");
1081         cache.removeAll();
1082 
1083         assertEquals(0, cache.getMemoryStoreSize());
1084         assertEquals(0, cache.getDiskStoreSize());
1085 
1086 
1087         for (int i = 0; i < 100; i++) {
1088             cache.put(new Element("" + i, new Date()));
1089         }
1090 
1091         Thread.sleep(200);
1092         
1093         for (int i = 0; i < 100; i++) {
1094             cache.get("" + i);
1095         }
1096         assertEquals(50, cache.getMemoryStoreSize());
1097         assertEquals(100, cache.getDiskStoreSize());
1098         assertEquals(100, cache.getSize());
1099 
1100 
1101         //Should get selected. But this is probabilistic
1102         cache.put(new Element("key", new String("sdf")));
1103         cache.put(new Element("key2", new String("fdgdf")));
1104         cache.put(new Element("key1", "value"));
1105 
1106         //get it and make sure it is mru
1107         Thread.sleep(200);
1108         cache.get("key1");
1109 
1110         assertEquals(103, cache.getSize());
1111         assertEquals(50, cache.getMemoryStoreSize());
1112         assertEquals(103, cache.getDiskStoreSize());
1113 
1114 
1115         //these "null" Elements are ignored and do not get put in
1116         cache.put(new Element(null, null));
1117         cache.put(new Element(null, null));
1118 
1119         assertEquals(103, cache.getSize());
1120         assertEquals(50, cache.getMemoryStoreSize());
1121         assertEquals(103, cache.getDiskStoreSize());
1122 
1123         //this one does
1124         cache.put(new Element("nullValue", null));
1125 
1126         Thread.sleep(200);
1127 
1128         LOG.info("Size: " + cache.getDiskStoreSize());
1129 
1130         assertEquals(50, cache.getMemoryStoreSize());
1131         assertEquals(104, cache.getDiskStoreSize());
1132 
1133         cache.flush();
1134         Thread.sleep(200);
1135         
1136         assertEquals(0, cache.getMemoryStoreSize());
1137         //Non Serializable Elements get discarded
1138         assertEquals(104, cache.getDiskStoreSize());
1139 
1140         cache.removeAll();
1141 
1142     }
1143 
1144     @Test
1145     public void testFlushWithoutClear() throws InterruptedException {
1146 
1147         CacheManager cacheManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache.xml");
1148         Cache cache = cacheManager.getCache("SimplePageCachingFilter");
1149         cache.removeAll();
1150         for (int i = 0; i < 100; i++) {
1151             cache.put(new Element("" + i, new Date()));
1152         }
1153         
1154         Thread.sleep(200);
1155 
1156         for (int i = 0; i < 100; i++) {            
1157             cache.get("" + i);
1158         }
1159 
1160         assertEquals(10, cache.getMemoryStoreSize());
1161         assertEquals(100, cache.getDiskStoreSize());
1162 
1163         cache.flush();
1164         Thread.sleep(200);
1165 
1166         assertEquals(10, cache.getMemoryStoreSize());
1167         assertEquals(100, cache.getDiskStoreSize());
1168         cacheManager.shutdown();
1169 
1170     }
1171 
1172     @Test
1173     public void testFlushWithClear() throws InterruptedException {
1174 
1175         CacheManager cacheManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache.xml");
1176         Cache cache = cacheManager.getCache("SimplePageFragmentCachingFilter");
1177         cache.removeAll();
1178         for (int i = 0; i < 100; i++) {
1179             cache.put(new Element("" + i, new Date()));
1180         }
1181         
1182         Thread.sleep(200);
1183         
1184         for (int i = 0; i < 100; i++) {            
1185             cache.get("" + i);
1186         }
1187 
1188         assertEquals(10, cache.getMemoryStoreSize());
1189         assertEquals(100, cache.getDiskStoreSize());
1190 
1191         cache.flush();
1192         Thread.sleep(200);
1193 
1194         assertEquals(0, cache.getMemoryStoreSize());
1195         assertEquals(100, cache.getDiskStoreSize());
1196         cacheManager.shutdown();
1197 
1198     }
1199 
1200 
1201     /***
1202      * Shows the effect of jamming large amounts of puts into a cache that overflows to disk.
1203      * The DiskStore should cause puts to back off and avoid an out of memory error.
1204      */
1205     @Test
1206     public void testBehaviourOnDiskStoreBackUp() throws Exception {
1207         Cache cache = new Cache("testGetMemoryStoreSize", 1000, true, false, 100, 200, false, 0);
1208         manager.addCache(cache);
1209 
1210         assertEquals(0, cache.getMemoryStoreSize());
1211 
1212         Element a = null;
1213         int i = 0;
1214         try {
1215             for (; i < 150000; i++) {
1216                 String key = i + "";
1217                 String value = key;
1218                 a = new Element(key, value + "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD");
1219                 cache.put(a);
1220             }
1221         } catch (OutOfMemoryError e) {
1222             LOG.info("OutOfMemoryError: " + e.getMessage() + " " + i);
1223             fail();
1224         }
1225     }
1226 
1227 
1228     /***
1229      * Tests using elements with null values. They should work as normal.
1230      *
1231      * @throws Exception
1232      */
1233     @Test
1234     public void testElementWithNullValue() throws Exception {
1235         Cache cache = new Cache("testElementWithNullValue", 10, false, false, 100, 200);
1236         manager.addCache(cache);
1237 
1238         Object key1 = new Object();
1239         Element element = new Element(key1, null);
1240         cache.put(element);
1241         assertNotNull(cache.get(key1));
1242         assertNotNull(cache.getQuiet(key1));
1243         assertSame(element, cache.get(key1));
1244         assertSame(element, cache.getQuiet(key1));
1245         assertNull(cache.get(key1).getObjectValue());
1246         assertNull(cache.getQuiet(key1).getObjectValue());
1247 
1248         assertEquals(false, cache.isExpired(element));
1249     }
1250 
1251 
1252     /***
1253      * Tests put works correctly for Elements with overriden TTL
1254      *
1255      * @throws Exception
1256      */
1257     @Test
1258     public void testPutWithOverriddenTTLAndTTI() throws Exception {
1259         Cache cache = new Cache("testElementWithNullValue", 10, false, false, 1, 1);
1260         manager.addCache(cache);
1261 
1262         Object key = new Object();
1263         Element element = new Element(key, "value");
1264         element.setTimeToLive(3);
1265         cache.put(element);
1266         Thread.sleep(1050);
1267         assertNotNull(cache.get(key));
1268         assertSame(element, cache.get(key));
1269 
1270         Element element2 = new Element(key, "value");
1271         cache.put(element2);
1272         Thread.sleep(1999);
1273         assertNull(cache.get(key));
1274 
1275         Element element3 = new Element(key, "value");
1276         element3.setTimeToLive(5);
1277         cache.put(element3);
1278         Thread.sleep(1999);
1279         assertSame(element3, cache.get(key));
1280 
1281     }
1282 
1283 
1284     /***
1285      * Tests putQuiet works correctly for Elements with overriden TTL
1286      *
1287      * @throws Exception
1288      */
1289     @Test
1290     public void testPutQuietWithOverriddenTTLAndTTI() throws Exception {
1291         Cache cache = new Cache("testElementWithNullValue", 10, false, false, 1, 1);
1292         manager.addCache(cache);
1293 
1294         Object key = new Object();
1295         Element element = new Element(key, "value");
1296         element.setTimeToLive(3);
1297         cache.putQuiet(element);
1298         Thread.sleep(1050);
1299         assertNotNull(cache.get(key));
1300         assertSame(element, cache.get(key));
1301 
1302         Element element2 = new Element(key, "value");
1303         cache.putQuiet(element2);
1304         Thread.sleep(1999);
1305         assertNull(cache.get(key));
1306 
1307         Element element3 = new Element(key, "value");
1308         element3.setTimeToLive(5);
1309         cache.putQuiet(element3);
1310         Thread.sleep(1999);
1311         assertSame(element3, cache.get(key));
1312 
1313     }
1314 
1315 
1316     /***
1317      * Tests using elements with null values. They should work as normal.
1318      *
1319      * @throws Exception
1320      */
1321     @Test
1322     public void testNonSerializableElement() throws Exception {
1323         Cache cache = new Cache("testElementWithNonSerializableValue", 1, true, false, 100, 200);
1324         manager.addCache(cache);
1325 
1326         Element element1 = new Element("key1", new Object());
1327         Element element2 = new Element("key2", new Object());
1328         cache.put(element1);
1329         cache.put(element2);
1330 
1331         //Removed because could not overflow
1332         if (cache.get("key1") == null) {
1333             assertNotNull(cache.get("key2"));
1334         } else {
1335             assertNull(cache.get("key2"));
1336         }
1337     }
1338 
1339 
1340     /***
1341      * Tests serialization of Serializable classes with null values.
1342      *
1343      * @throws Exception
1344      */
1345     @Test
1346     public void testNullCollectionsAreSerializable() throws Exception {
1347         Cache cache = new Cache("testElementWithNonSerializableValue", 1, true, false, 100, 200);
1348         manager.addCache(cache);
1349         ArrayList arrayList = null;
1350 
1351         Element element1 = new Element("key1", arrayList);
1352         Element element2 = new Element("key2", arrayList);
1353         cache.put(element1);
1354         cache.put(element2);
1355 
1356         //Still retrievable because null Serializable classes are still Serializable
1357         Element element = cache.get("key1");
1358         assertNotNull(element);
1359         assertNull(element.getValue());
1360 
1361         //Still retrievable because null Serializable classes are still Serializable
1362         assertNotNull(cache.get("key2"));
1363     }
1364 
1365 
1366     /***
1367      * Tests what happens when an Element throws an Error on serialization. This mimics
1368      * what a nasty error like OutOfMemoryError could do.
1369      * <p/>
1370      * Before a change to the SpoolAndExpiryThread to handle this situation this test failed and generated the following log message.
1371      * Jun 28, 2006 7:17:16 PM net.sf.ehcache.store.DiskStore put
1372      * SEVERE: testThreadKillerCache: Elements cannot be written to disk store because the spool thread has died.
1373      *
1374      * @throws Exception
1375      */
1376     @Test
1377     public void testSpoolThreadHandlesThreadKiller() throws Exception {
1378         Cache cache = new Cache("testThreadKiller", 0, true, false, 100, 200);
1379         manager.addCache(cache);
1380 
1381         Element elementThreadKiller = new Element("key", new ThreadKiller());
1382         cache.put(elementThreadKiller);
1383         Thread.sleep(2999);
1384         Element element1 = new Element("key1", "one");
1385         Element element2 = new Element("key2", "two");
1386         cache.put(element1);
1387         cache.put(element2);
1388 
1389         Thread.sleep(2999);
1390 
1391         assertNotNull(cache.get("key1"));
1392         assertNotNull(cache.get("key2"));
1393     }
1394 
1395     /***
1396      * Tests disk store and memory store size
1397      *
1398      * @throws Exception
1399      */
1400     @Test
1401     public void testGetDiskStoreSize() throws Exception {
1402         Cache cache = new Cache("testGetDiskStoreSize", 1, true, false, 100, 200);
1403         manager.addCache(cache);
1404         assertEquals(0, cache.getDiskStoreSize());
1405 
1406         cache.put(new Element("key1", "value1"));
1407         assertEquals(0, cache.getDiskStoreSize());
1408         assertEquals(1, cache.getSize());
1409 
1410         cache.put(new Element("key2", "value2"));
1411         assertEquals(2, cache.getSize());
1412         assertEquals(1, cache.getDiskStoreSize());
1413         assertEquals(1, cache.getMemoryStoreSize());
1414 
1415         cache.put(new Element("key3", "value3"));
1416         cache.put(new Element("key4", "value4"));
1417         assertEquals(4, cache.getSize());
1418         assertEquals(3, cache.getDiskStoreSize());
1419         assertEquals(1, cache.getMemoryStoreSize());
1420 
1421         // remove last element inserted (is in memory store)
1422         assertTrue(((CompoundStore) cache.getStore()).unretrievedGet("key4") instanceof Element);
1423         cache.remove("key4");
1424         assertEquals(3, cache.getSize());
1425         assertEquals(3, cache.getDiskStoreSize());
1426         assertEquals(0, cache.getMemoryStoreSize());
1427 
1428         // remove key1 element
1429         assertFalse(((CompoundStore) cache.getStore()).unretrievedGet("key1") instanceof Element);
1430         cache.remove("key1");
1431         assertEquals(2, cache.getSize());
1432         assertEquals(2, cache.getDiskStoreSize());
1433         assertEquals(0, cache.getMemoryStoreSize());
1434 
1435         // add another
1436         cache.put(new Element("key5", "value5"));
1437         assertEquals(3, cache.getSize());
1438         assertEquals(2, cache.getDiskStoreSize());
1439         assertEquals(1, cache.getMemoryStoreSize());
1440 
1441         // remove all
1442         cache.removeAll();
1443         assertEquals(0, cache.getSize());
1444         assertEquals(0, cache.getDiskStoreSize());
1445         assertEquals(0, cache.getMemoryStoreSize());
1446 
1447         //Check behaviour of NonSerializable objects
1448         cache.put(new Element(new Object(), new Object()));
1449         cache.put(new Element(new Object(), new Object()));
1450         cache.put(new Element(new Object(), new Object()));
1451         
1452         Thread.sleep(200);
1453         
1454         assertEquals(1, cache.getSize());
1455         assertEquals(0, cache.getDiskStoreSize());
1456         assertEquals(1, cache.getMemoryStoreSize());
1457 
1458     }
1459 
1460     /***
1461      * Tests that attempting to clone a cache fails with the right exception.
1462      *
1463      * @throws Exception
1464      */
1465     @Test
1466     public void testCloneFailures() throws Exception {
1467         Cache cache = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1468         manager.addCache(cache);
1469         try {
1470             cache.clone();
1471             fail("Should have thrown CloneNotSupportedException");
1472         } catch (CloneNotSupportedException e) {
1473             //noop
1474         }
1475     }
1476 
1477 
1478     /***
1479      * Tests that the toString() method works.
1480      */
1481     @Test
1482     public void testToString() {
1483         Ehcache cache = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1484         assertTrue(cache.toString().indexOf("testGetMemoryStore") > -1);
1485         assertEquals(410, cache.toString().length());
1486     }
1487 
1488 
1489     /***
1490      * When does equals mean the same thing as == ?
1491      *
1492      * @throws CacheException
1493      * @throws InterruptedException
1494      */
1495     @Test
1496     public void testEquals() throws CacheException, InterruptedException {
1497         Cache cache = new Cache("cache", 1, true, false, 100, 200, false, 1);
1498         manager.addCache(cache);
1499 
1500         Element element1 = new Element("1", new Date());
1501         Element element2 = new Element("2", new Date());
1502         cache.put(element1);
1503         cache.put(element2);
1504 
1505         //Test equals and == from an Element retrieved from the MemoryStore
1506         Element elementFromStore = cache.get("2");
1507         assertEquals(element2, elementFromStore);
1508         assertTrue(element2 == elementFromStore);
1509 
1510         //Give the spool a chance to make sure it really got serialized to Disk
1511         Thread.sleep(300);
1512 
1513         //Test equals and == from an Element retrieved from the MemoryStore
1514         Element elementFromDiskStore = cache.get("1");
1515         assertEquals(element1, elementFromDiskStore);
1516         assertTrue(element1 != elementFromDiskStore);
1517     }
1518 
1519     /***
1520      * When does equals mean the same thing as == ?
1521      *
1522      * @throws CacheException
1523      * @throws InterruptedException
1524      */
1525     @Test
1526     public void testIsKeyInCache() throws CacheException, InterruptedException {
1527         Cache cache = new Cache("cache", 1, true, false, 100, 200, false, 1);
1528         manager.addCache(cache);
1529 
1530         Element element1 = new Element("1", new Date());
1531         Element element2 = new Element("2", new Date());
1532         cache.put(element1);
1533         cache.put(element2);
1534 
1535         assertTrue(cache.isKeyInCache("1"));
1536         assertTrue(cache.isKeyInCache("2"));
1537         assertFalse(cache.isKeyInCache(null));
1538     }
1539 
1540     /***
1541      * Tests the uniqueness of the GUID
1542      */
1543     @Test
1544     public void testGuid() {
1545         Ehcache cache1 = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1546         Ehcache cache2 = new Cache("testGetMemoryStore", 10, false, false, 100, 200);
1547         String guid1 = cache1.getGuid();
1548         String guid2 = cache2.getGuid();
1549         assertEquals(cache1.getName(), cache2.getName());
1550         assertTrue(!guid1.equals(guid2));
1551 
1552     }
1553 
1554 
1555     /***
1556      * Does the Object API work?
1557      */
1558     @Test
1559     public void testAPIObjectCompatibility() {
1560         Cache cache = new Cache("test", 5, true, false, 5, 2);
1561         manager.addCache(cache);
1562 
1563         Object objectKey = new Object();
1564         Object objectValue = new Object();
1565         Element objectElement = new Element(objectKey, objectValue);
1566         cache.put(objectElement);
1567 
1568         //Cannot get it back using get
1569         Element retrievedElement = cache.get(objectKey);
1570         assertNotNull(retrievedElement);
1571         try {
1572             retrievedElement.getObjectValue();
1573         } catch (CacheException e) {
1574             //expected
1575         }
1576 
1577         //Test that equals works
1578         retrievedElement = cache.get(objectKey);
1579         assertEquals(objectElement, retrievedElement);
1580 
1581         //Can with getObjectValue
1582         retrievedElement = cache.get(objectKey);
1583         assertEquals(objectValue, retrievedElement.getObjectValue());
1584 
1585     }
1586 
1587 
1588     /***
1589      * Does the Serializable API work?
1590      */
1591     @Test
1592     public void testAPISerializableCompatibility() {
1593         Cache cache = new Cache("test", 5, true, false, 5, 2);
1594         manager.addCache(cache);
1595 
1596         //Try object compatibility
1597         Serializable key = new String();
1598         Element objectElement = new Element(key, new String());
1599         cache.put(objectElement);
1600         Object retrievedObject = cache.get(key);
1601         assertEquals(retrievedObject, objectElement);
1602 
1603         //Test that equals works
1604         assertEquals(objectElement, retrievedObject);
1605     }
1606 
1607     /***
1608      * Test issues reported.
1609      */
1610     @Test
1611     public void testDiskStoreFlorian() throws InterruptedException {
1612         manager.shutdown();
1613 
1614         byte[] config = ("<ehcache> \n" +
1615                 "<diskStore path=\"java.io.tmpdir\"/> \n" +
1616                 "<defaultCache \n" +
1617                 "            maxElementsInMemory=\"10000\" \n" +
1618                 "            eternal=\"false\" \n" +
1619                 "            timeToIdleSeconds=\"120\" \n" +
1620                 "            timeToLiveSeconds=\"120\" \n" +
1621                 "            overflowToDisk=\"true\" \n" +
1622                 "            diskPersistent=\"false\" \n" +
1623                 "            diskExpiryThreadIntervalSeconds=\"120\" \n" +
1624                 "            memoryStoreEvictionPolicy=\"LRU\" \n" +
1625                 "            /> " +
1626                 "\n" +
1627                 "<cache name=\"testCache\" \n" +
1628                 "       maxElementsInMemory=\"20000\" \n" +
1629                 "       eternal=\"false\" \n" +
1630                 "       overflowToDisk=\"false\" \n" +
1631                 "       timeToIdleSeconds=\"300\" \n" +
1632                 "       timeToLiveSeconds=\"600\" \n" +
1633                 "       diskPersistent=\"false\" \n" +
1634                 "       diskExpiryThreadIntervalSeconds=\"1\" \n" +
1635                 "       memoryStoreEvictionPolicy=\"LFU\" \n" +
1636                 "/>           \n" +
1637                 "<cache name=\"test2Cache\" \n" +
1638                 "       maxElementsInMemory=\"20000\" \n" +
1639                 "       eternal=\"false\" \n" +
1640                 "       overflowToDisk=\"true\" \n" +
1641                 "       timeToIdleSeconds=\"300\" \n" +
1642                 "       timeToLiveSeconds=\"600\" \n" +
1643                 "       diskPersistent=\"false\" \n" +
1644                 "       diskExpiryThreadIntervalSeconds=\"1\" \n" +
1645                 "       memoryStoreEvictionPolicy=\"LFU\" \n" +
1646                 "/> \n" +
1647                 "</ehcache> ").getBytes();
1648 
1649 
1650         CacheManager cacheManager = new CacheManager(new ByteArrayInputStream(config));
1651         Cache cache = new Cache("test3cache", 20000, false, true, 50, 30);
1652         //assertTrue(cache.getCacheConfiguration().isOverflowToDisk());
1653         cacheManager.addCache(cache);
1654 
1655         //todo size is slow
1656         for (int i = 0; i < 25000; i++) {
1657             cache.put(new Element(i + "", "value"));
1658 //            assertEquals(i + 1, cache.getSize());
1659         }
1660         assertEquals(20000, cache.getSize());
1661 //        assertEquals(5000, cache.getDiskStoreSize());
1662     }
1663 
1664 
1665 
1666 
1667     /***
1668      * Tests added from 1606323 Elements not stored in memory or on disk. This was supposedly
1669      * a bug but works.
1670      * This test passes.
1671      *
1672      * @throws Exception
1673      */
1674     @Test
1675     public void testTimeToLive15552000() throws Exception {
1676         long timeToLiveSeconds = 15552000;
1677         doRunTest(timeToLiveSeconds);
1678     }
1679 
1680     /***
1681      * This test passes.
1682      *
1683      * @throws Exception
1684      */
1685     @Test
1686     public void testTimeToLive604800() throws Exception {
1687         long timeToLiveSeconds = 604800;
1688         doRunTest(timeToLiveSeconds);
1689     }
1690 
1691     private void doRunTest(long timeToLiveSeconds) {
1692         String name = "memoryAndDiskCache";
1693         int maxElementsInMemory = 1000;
1694         MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = MemoryStoreEvictionPolicy.LRU;
1695         boolean overflowToDisk = true;
1696         String diskStorePath = "java.io.tmp.dir/cache";
1697         boolean eternal = false;
1698         long timeToIdleSeconds = 0;
1699         boolean diskPersistent = true;
1700         long diskExpiryThreadIntervalSeconds = 3600;
1701         RegisteredEventListeners registeredEventListeners = null;
1702         BootstrapCacheLoader bootstrapCacheLoader = null;
1703 
1704         Cache memoryAndDisk = new Cache(
1705                 name,
1706                 maxElementsInMemory,
1707                 memoryStoreEvictionPolicy,
1708                 overflowToDisk,
1709                 diskStorePath,
1710                 eternal,
1711                 timeToLiveSeconds,
1712                 timeToIdleSeconds,
1713                 diskPersistent,
1714                 diskExpiryThreadIntervalSeconds,
1715                 registeredEventListeners,
1716                 bootstrapCacheLoader);
1717 
1718         this.manager.addCache(memoryAndDisk);
1719 
1720         String key = "test";
1721         Object value = "value";
1722 
1723         memoryAndDisk.put(new Element(key, value));
1724 
1725         assertTrue(memoryAndDisk.isElementInMemory(key));
1726     }
1727 
1728     /***
1729      * Tests get from a finalize method, following a mailing list post from Felix Satyaputr
1730      *
1731      * @throws InterruptedException
1732      */
1733     @Test
1734     public void testGetQuietFromFinalize() throws InterruptedException {
1735 
1736 
1737         final Cache cache = new Cache("test", 1, true, false, 5, 2);
1738         manager.addCache(cache);
1739 
1740         cache.put(new Element("key", "value"));
1741         cache.put(new Element("key2", "value"));
1742         cache.put(new Element("key3", "value"));
1743         cache.put(new Element("key4", "value"));
1744         cache.put(new Element("key5", "value"));
1745 
1746         //wait for overflow to kick in
1747         Thread.sleep(200);
1748 
1749         createTestObject();
1750 
1751         //try to get object finalized
1752         System.gc();
1753         Thread.sleep(200);
1754         System.gc();
1755 
1756 
1757     }
1758 
1759     private void createTestObject() {
1760         new TestObject();
1761     }
1762 
1763 
1764     /***
1765      * A class with a finalize implementation.
1766      */
1767     class TestObject {
1768 
1769         /***
1770          * Override the Object finalize method
1771          */
1772         @Override
1773         protected void finalize() throws Throwable {
1774             manager.getCache("test").getQuiet("key");
1775             LOG.info("finalize run from thread " + Thread.currentThread().getName());
1776             super.finalize();
1777         }
1778     }
1779 
1780 
1781     @Test
1782     public void testGetWithLoader() {
1783 
1784         /***
1785          *
1786          */
1787         class TestCacheLoader implements CacheLoader {
1788 
1789 
1790             public Object load(Object key, Object argument) throws CacheException {
1791                 LOG.info("load1 " + key);
1792                 return key;
1793             }
1794 
1795             public Map loadAll(Collection keys, Object argument) throws CacheException {
1796                 return null;
1797             }
1798 
1799 
1800             public String getName() {
1801                 return null;
1802             }
1803 
1804             public CacheLoader clone(Ehcache cache) throws CloneNotSupportedException {
1805                 return null;
1806             }
1807 
1808             public void init() {
1809                 //noop
1810             }
1811 
1812             public void dispose() throws CacheException {
1813                 //noop
1814             }
1815 
1816             public Status getStatus() {
1817                 return null;
1818             }
1819 
1820             public Object load(Object o) throws CacheException {
1821                 LOG.info("load2 " + o + " " + o.getClass());
1822                 if (o.equals("c")) {
1823                     return null;
1824                 }
1825                 return o;
1826             }
1827 
1828             public Map loadAll(Collection collection) throws CacheException {
1829                 return null;
1830             }
1831 
1832 
1833         }
1834 
1835         Cache cache = manager.getCache("sampleCache1");
1836         cache.registerCacheLoader(new TestCacheLoader());
1837 
1838 
1839         Element element = cache.get("a");
1840         assertNull(element);
1841 
1842         element = cache.getWithLoader("b", null, null);
1843         assertNotNull(element);
1844 
1845         //should be null
1846         element = cache.getWithLoader("c", null, null);
1847         assertNull(element);
1848     }
1849 
1850     /***
1851      * Tests the async load with a single item
1852      */
1853     @Test
1854     public void testAsynchronousLoad() throws InterruptedException, ExecutionException {
1855 
1856         CountingCacheLoader countingCacheLoader = new CountingCacheLoader();
1857         Cache cache = manager.getCache("sampleCache1");
1858         cache.registerCacheLoader(countingCacheLoader);
1859         ExecutorService executorService = cache.getExecutorService();
1860 
1861         Future future = cache.asynchronousLoad("key1", null, null);
1862 
1863         Object object = future.get();
1864         assertTrue(future.isDone());
1865         assertNull(object);
1866 
1867         assertFalse(executorService.isShutdown());
1868 
1869         assertEquals(1, cache.getSize());
1870         assertEquals(1, countingCacheLoader.getLoadCounter());
1871     }
1872 
1873     /***
1874      * Tests the async load with a single item
1875      */
1876     @Test
1877     public void testGetWithLoaderException() {
1878         Cache cache = manager.getCache("sampleCache1");
1879         cache.registerCacheLoader(new ExceptionThrowingLoader());
1880         try {
1881             cache.getWithLoader("key1", null, null);
1882             fail();
1883         } catch (CacheException e) {
1884             //expected
1885         }
1886     }
1887 
1888 
1889     /***
1890      * Tests the loadAll async method
1891      */
1892     @Test
1893     public void testAsynchronousLoadAll() throws InterruptedException, ExecutionException {
1894 
1895         CountingCacheLoader countingCacheLoader = new CountingCacheLoader();
1896         Cache cache = manager.getCache("sampleCache1");
1897         cache.registerCacheLoader(countingCacheLoader);
1898         ExecutorService executorService = cache.getExecutorService();
1899 
1900         List keys = new ArrayList();
1901         for (int i = 0; i < 1000; i++) {
1902             keys.add(Integer.valueOf(i));
1903         }
1904 
1905         Future future = cache.asynchronousLoadAll(keys, null);
1906         assertFalse(future.isDone());
1907 
1908         Object object = future.get();
1909         assertTrue(future.isDone());
1910         assertNull(object);
1911 
1912         assertFalse(executorService.isShutdown());
1913 
1914         assertEquals(1000, cache.getSize());
1915         assertEquals(1000, countingCacheLoader.getLoadAllCounter());
1916     }
1917 
1918     /***
1919      * Tests programmatically disabling and enabling a cache
1920      */
1921     @Test
1922     public void testEnableAndDisable() throws Exception {
1923         Ehcache cache = manager.getCache("sampleCacheNoIdle");
1924         cache.put(new Element("key1put", "value1"));
1925         cache.put(new Element("key1putQuiet", "value1"));
1926         assertFalse(cache.isDisabled());
1927         assertNotNull(cache.get("key1put"));
1928         assertNotNull(cache.get("key1putQuiet"));
1929 
1930         //now disable
1931         cache.setDisabled(true);
1932 
1933         assertTrue(cache.isDisabled());
1934         assertNull(cache.get("key1put"));
1935         assertNull(cache.get("key1putQuiet"));
1936 
1937         cache.put(new Element("key2put", "value1"));
1938         cache.put(new Element("key2putQuiet", "value1"));
1939         assertNull(cache.get("key2put"));
1940         assertNull(cache.get("key2putQuiet"));
1941     }
1942 
1943 
1944     /***
1945      * Run testConcurrentPutsAreConsistent() repeatedly for 50 times to shake out issues that happen rarely.
1946      */
1947     @Test
1948     public void testConcurrentPutsAreConsistentRepeatedly() throws InterruptedException {
1949         for (int i = 0; i < 20; i++) {
1950             manager.removalAll();
1951             testConcurrentPutsAreConsistent();
1952         }
1953     }
1954 
1955     /***
1956      * Shows a consistency problem as reported against 1.6.0.
1957      * <p/>
1958      * Does not happen when not using DiskStore
1959      * Putting synchronized on put/get on cache fixes it
1960      * Only happens when the Element is retrieved from the DiskStore. Debugging shows
1961      * that the problem is caused by puts not getting through or coming in the wrong order
1962      * Putting synchronized on MemoryStore.put() fixes the issue. That is the applied fix.
1963      * <p/>
1964      * The exact cause is unknown but the behaviour of ConcurrentHashMap is suspected.
1965      */
1966     @Test
1967     public void testConcurrentPutsAreConsistent() throws InterruptedException {
1968         Cache cache = new Cache("someName", 100, true, true, 0, 0);
1969         manager.addCache(cache);
1970 
1971         cache.setStatisticsEnabled(true);
1972         
1973         ExecutorService executor = Executors.newFixedThreadPool(10);
1974 
1975         for (int i = 0; i < 5000; i++) {
1976             executor.execute(new CacheTestRunnable(cache, String.valueOf(i)));
1977         }
1978         executor.shutdown();
1979         executor.awaitTermination(10, TimeUnit.SECONDS);
1980 
1981         assertEquals("Failures: ", 0, CacheTestRunnable.FAILURES.size());
1982         assertEquals(5000, cache.getStatistics().getCacheHits());
1983 
1984     }
1985 
1986     /***
1987      * A runnable that sets 5 times in a row then calls get and checks it is the last value set
1988      */
1989     private static final class CacheTestRunnable implements Runnable {
1990         static final List FAILURES = new ArrayList();
1991 
1992         private Ehcache cache;
1993         private String key;
1994 
1995         private CacheTestRunnable(Ehcache cache, String key) {
1996             this.cache = cache;
1997             this.key = key;
1998         }
1999 
2000         public void run() {
2001             setValue("new value");
2002             setValue("new value2");
2003             setValue("new value3");
2004             setValue("new value4");
2005             setValue("new value5");
2006 
2007             Element element = cache.get(key);
2008             String value = element.getValue().toString();
2009             boolean result = value.equals("new value5");
2010             if (!result) {
2011                 LOG.info("key is: " + key + " value: " + value + " version: " + element.getVersion());
2012                 FAILURES.add("key is: " + key + " value: " + value);
2013             }
2014         }
2015 
2016         private void setValue(String valueToSet) {
2017             cache.put(new Element(key, valueToSet));
2018         }
2019 
2020     }
2021 
2022     /***
2023      * test cache clones do not have same statistics
2024      *
2025      * @throws Exception
2026      */
2027     @Test
2028     public void testCloneCompleteness() throws Exception {
2029         Cache cache = new Cache("testGetMemoryStore", 10, false, false, 100,
2030                 200);
2031         Cache clone = cache.clone();
2032         clone.setName("testGetMemoryStoreClone");
2033         manager.addCache(cache);
2034         manager.addCache(clone);
2035 
2036         cache.setStatisticsEnabled(true);
2037         clone.setStatisticsEnabled(true);
2038         
2039         assertFalse(cache.getGuid().equals(clone.getGuid()));
2040 
2041         // validate updating the statistics of one cache does NOT affect a
2042         // cloned one
2043         cache.get("notFoundKey");
2044         assertEquals(1, cache.getStatistics().getCacheMisses());
2045         assertEquals(0, clone.getStatistics().getCacheMisses());
2046     }
2047 
2048 
2049     /***
2050      * Checks that notification only happens once when clearOnFlush is false i.e.
2051      * The impact of this is that there will be one copy in each store.
2052      */
2053     @Test
2054     public void testRemoveListenersCalledOnce() {
2055         Cache cache = manager.getCache("sampleCache1");
2056         RemoveCountingListener l = new RemoveCountingListener();
2057         cache.getCacheEventNotificationService().registerListener(l);
2058 
2059         cache.getCacheConfiguration().setDiskPersistent(true);
2060         cache.getCacheConfiguration().setClearOnFlush(false);
2061 
2062         Element element = new Element("foo", "bar", 1L);
2063 
2064         cache.put(element);
2065 
2066         cache.flush();
2067 
2068         cache.remove("foo");
2069 
2070         assertEquals(1, l.count);
2071         assertSame(element, l.element);
2072 
2073     }
2074 
2075     /***
2076      * test listener
2077      */
2078     private static class RemoveCountingListener implements CacheEventListener {
2079 
2080         private int count;
2081         private Element element;
2082 
2083         public void notifyElementRemoved(Ehcache cache, Element element)
2084                 throws CacheException {
2085             count++;
2086             this.element = element;
2087         }
2088 
2089         public void dispose() {
2090 
2091         }
2092 
2093         public void notifyElementEvicted(Ehcache cache, Element element) {
2094 
2095         }
2096 
2097         public void notifyElementExpired(Ehcache cache, Element element) {
2098 
2099         }
2100 
2101         public void notifyElementPut(Ehcache cache, Element element)
2102                 throws CacheException {
2103 
2104         }
2105 
2106         public void notifyElementUpdated(Ehcache cache, Element element)
2107                 throws CacheException {
2108         }
2109 
2110         public void notifyRemoveAll(Ehcache cache) {
2111 
2112         }
2113 
2114         @Override
2115         public Object clone() throws CloneNotSupportedException {
2116             return super.clone();
2117         }
2118     }
2119 
2120     /***
2121      * Checks that TTL of Long.MAX_VALUE means value never expires.
2122      * See EHC-432.
2123      */
2124     @Test
2125     public void testMaxLongTTLIsEternal() {
2126         long maxLiveTime = Long.MAX_VALUE;
2127 
2128         final Cache cache = new Cache("bla", 5000, false, false, maxLiveTime, 0);
2129         final CacheManager cacheManager = CacheManager.create();
2130 
2131         cacheManager.addCache(cache);
2132 
2133         Element e = new Element("key", "bla");
2134         cache.put(e);
2135 
2136         // theoretically we should wait a long time here but the error from EHC-432 
2137         // has already shown up in the put.  And we don't have time to wait forever
2138         // to verify this.
2139 
2140         Element e2 = cache.get("key");
2141         assertNotNull(e2);
2142     }
2143 
2144     /***
2145      * Checks that TTL of Integer.MAX_VALUE means value never expires.
2146      * See EHC-432.
2147      */
2148     @Test
2149     public void testMaxIntegerTTLIsEternal() {
2150         long maxLiveTime = Integer.MAX_VALUE;
2151 
2152         final Cache cache = new Cache("bla", 5000, false, false, maxLiveTime, 0);
2153         final CacheManager cacheManager = CacheManager.create();
2154 
2155         cacheManager.addCache(cache);
2156 
2157         Element e = new Element("key", "bla");
2158         cache.put(e);
2159 
2160         // theoretically we should wait a long time here but the error from EHC-432 
2161         // has already shown up in the put.  And we don't have time to wait forever
2162         // to verify this.
2163 
2164         Element e2 = cache.get("key");
2165         assertNotNull(e2);
2166     }
2167 
2168     /***
2169      * Versioning is broken when updates are done. If an Element constructor specifying a version is used, it should
2170      * be preserved. If not the version should start at one and then be incremented.
2171      *
2172      * todo This test fails. When the implementation is corrected it will pass. This test is therefore currently marked @Ignore
2173      *
2174      * See EHC-666
2175      */
2176     @Test
2177     @Ignore
2178     public void testVersioningShouldBePreserved() {
2179 
2180         CacheManager cacheManager = CacheManager.getInstance();
2181         cacheManager.addCache(new Cache("mltest", 50, MemoryStoreEvictionPolicy.LRU, true, null, true, 0, 0, false, 120, null, null, 0, 2, false));
2182         Cache cache = cacheManager.getCache("mltest");
2183 
2184         Element a = new Element("a key", "a value", 1L);
2185         cache.put(a);
2186         Element aAfter = cache.get("a key");
2187         assertEquals(1L, aAfter.getVersion());
2188 
2189         LOG.info("Element after first put with specific version." + aAfter);
2190 
2191         //A second put of the same key, where the version is not explicitly mentioned, gets updated by the cache.
2192         Element b = new Element("a key", "a value");
2193         cache.put(b);
2194         Element bAfter = cache.get("a key");
2195         assertFalse(1L == bAfter.getVersion());
2196         LOG.info("Element after second put. No version." + bAfter);
2197 
2198         //Explicit Version should be preserved
2199         Element c = new Element("a key", "a value", 3L);
2200         cache.put(c);
2201         LOG.info("Element after third put with specific version." + cache.get("a key"));
2202         Element cAfter = cache.get("a key");
2203         assertEquals(3L, cAfter.getVersion());
2204 
2205     }
2206 
2207 }
2208