1   /**
2    *  Copyright 2003-2007 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 junit.framework.TestCase;
20  import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
21  import net.sf.ehcache.config.CacheConfiguration;
22  import net.sf.ehcache.config.Configuration;
23  import net.sf.ehcache.config.ConfigurationFactory;
24  import net.sf.ehcache.config.DiskStoreConfiguration;
25  import net.sf.ehcache.distribution.RMIBootstrapCacheLoader;
26  import net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator;
27  import net.sf.ehcache.event.RegisteredEventListeners;
28  import net.sf.ehcache.event.CacheEventListener;
29  import net.sf.ehcache.store.DiskStore;
30  import net.sf.ehcache.store.Store;
31  import net.sf.ehcache.constructs.blocking.BlockingCache;
32  import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
33  import net.sf.ehcache.constructs.blocking.CountingCacheEntryFactory;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  import java.io.File;
38  import java.io.FileInputStream;
39  import java.io.InputStream;
40  import java.net.URL;
41  import java.util.Date;
42  import java.util.Set;
43  import java.util.Iterator;
44  
45  /**
46   * Tests for CacheManager
47   *
48   * @author Greg Luck
49   * @version $Id: CacheManagerTest.java 512 2007-07-10 09:18:45Z gregluck $
50   */
51  public class CacheManagerTest extends TestCase {
52      private static final Log LOG = LogFactory.getLog(CacheManagerTest.class.getName());
53  
54      
55  
56      /**
57       * the CacheManager Singleton instance
58       */
59      protected CacheManager singletonManager;
60  
61      /**
62       * a CacheManager which is created as an instance
63       */
64      protected CacheManager instanceManager;
65  
66      /**
67       * Shutdown managers.
68       * Check that the manager is removed from CacheManager.ALL_CACHE_MANAGERS
69       */
70      protected void tearDown() throws Exception {
71          if (singletonManager != null) {
72              if (singletonManager.getStatus().equals(Status.STATUS_ALIVE)) {
73                  assertTrue(CacheManager.ALL_CACHE_MANAGERS.contains(singletonManager));
74              }
75              singletonManager.shutdown();
76              assertFalse(CacheManager.ALL_CACHE_MANAGERS.contains(singletonManager));
77          }
78          if (instanceManager != null) {
79              if (instanceManager.getStatus().equals(Status.STATUS_ALIVE)) {
80                  assertTrue(CacheManager.ALL_CACHE_MANAGERS.contains(instanceManager));
81              }
82              instanceManager.shutdown();
83              assertFalse(CacheManager.ALL_CACHE_MANAGERS.contains(instanceManager));
84          }
85      }
86  
87  
88  
89  
90      /**
91       * Tests that the CacheManager was successfully created
92       */
93      public void testCreateCacheManager() throws CacheException {
94          singletonManager = CacheManager.create();
95          assertNotNull(singletonManager);
96          assertEquals(12, singletonManager.getCacheNames().length);
97      }
98  
99      /**
100      * Tests that the CacheManager was successfully created
101      */
102     public void testCreateCacheManagerFromFile() throws CacheException {
103         singletonManager = CacheManager.create(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
104         assertNotNull(singletonManager);
105         assertEquals(6, singletonManager.getCacheNames().length);
106     }
107 
108     /**
109      * Tests that the CacheManager was successfully created from a Configuration
110      */
111     public void testCreateCacheManagerFromConfiguration() throws CacheException {
112         File file = new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
113         Configuration configuration = ConfigurationFactory.parseConfiguration(file);
114         CacheManager manager = new CacheManager(configuration);
115         assertNotNull(manager);
116         assertEquals(6, manager.getCacheNames().length);
117         manager.shutdown();
118     }
119 
120     /**
121      * Tests that the CacheManager was successfully created
122      */
123     public void testCreateCacheManagerFromInputStream() throws Exception {
124         InputStream fis = new FileInputStream(new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml").getAbsolutePath());
125         try {
126             singletonManager = CacheManager.create(fis);
127         } finally {
128             fis.close();
129         }
130         assertNotNull(singletonManager);
131         assertEquals(6, singletonManager.getCacheNames().length);
132     }
133 
134     /**
135      * Tests that creating a second cache manager with the same disk path will fail.
136      */
137     public void testCreateTwoCacheManagersWithSamePath() throws CacheException {
138         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
139 
140         singletonManager = CacheManager.create(secondCacheConfiguration);
141         instanceManager = new CacheManager(secondCacheConfiguration);
142 
143         String intialDiskStorePath = System.getProperty("java.io.tmpdir") + File.separator + "second";
144 
145         File diskStorePathDir = new File(intialDiskStorePath);
146         File[] files = diskStorePathDir.listFiles();
147         File newDiskStorePath = null;
148         boolean newDiskStorePathFound = false;
149         for (int i = 0; i < files.length; i++) {
150             File file = files[i];
151             if (file.isDirectory()) {
152                 if (file.getName().indexOf(DiskStore.AUTO_DISK_PATH_DIRECTORY_PREFIX) != -1) {
153                     newDiskStorePathFound = true;
154                     newDiskStorePath = file;
155                     break;
156                 }
157             }
158         }
159         assertTrue(newDiskStorePathFound);
160         newDiskStorePath.delete();
161 
162 
163     }
164 
165     /**
166      * Tests that two CacheManagers were successfully created
167      */
168     public void testTwoCacheManagers() throws CacheException {
169         Element element1 = new Element(1 + "", new Date());
170         Element element2 = new Element(2 + "", new Date());
171 
172         CacheManager.getInstance().getCache("sampleCache1").put(element1);
173 
174         //Check can start second one with a different disk path
175         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
176         instanceManager = new CacheManager(secondCacheConfiguration);
177         instanceManager.getCache("sampleCache1").put(element2);
178 
179         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
180         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
181 
182         //shutting down instance should leave singleton unaffected
183         instanceManager.shutdown();
184         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
185 
186         //Try shutting and recreating a new instance cache manager
187         instanceManager = new CacheManager(secondCacheConfiguration);
188         instanceManager.getCache("sampleCache1").put(element2);
189         CacheManager.getInstance().shutdown();
190         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
191 
192         //Try shutting and recreating the singleton cache manager
193         CacheManager.getInstance().getCache("sampleCache1").put(element2);
194         assertNull(CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
195         assertEquals(element2, CacheManager.getInstance().getCache("sampleCache1").get(2 + ""));
196     }
197 
198     /**
199      * Tests that two CacheManagers were successfully created
200      */
201     public void testTwoCacheManagersWithSameConfiguration() throws CacheException {
202         Element element1 = new Element(1 + "", new Date());
203         Element element2 = new Element(2 + "", new Date());
204 
205 
206         String fileName = AbstractCacheTest.TEST_CONFIG_DIR + "ehcache.xml";
207         CacheManager.create(fileName).getCache("sampleCache1").put(element1);
208 
209         //Check can start second one with the same config
210         instanceManager = new CacheManager(fileName);
211         instanceManager.getCache("sampleCache1").put(element2);
212 
213         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
214         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
215 
216         //shutting down instance should leave singleton unaffected
217         instanceManager.shutdown();
218         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
219 
220         //Try shutting and recreating a new instance cache manager
221         instanceManager = new CacheManager(fileName);
222         instanceManager.getCache("sampleCache1").put(element2);
223         CacheManager.getInstance().shutdown();
224         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
225 
226         //Try shutting and recreating the singleton cache manager
227         CacheManager.getInstance().getCache("sampleCache1").put(element2);
228         assertNull(CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
229         assertEquals(element2, CacheManager.getInstance().getCache("sampleCache1").get(2 + ""));
230     }
231 
232     /**
233      * Create and destory cache managers and see what happens with threads.
234      * Each Cache creates at least two threads. These should all be killed when the Cache
235      * disposes. Doing that 800 times as in that test gives the reassurance.
236      */
237     public void testForCacheManagerThreadLeak() throws CacheException, InterruptedException {
238         //Check can start second one with a different disk path
239         int startingThreadCount = countThreads();
240 
241         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
242         for (int i = 0; i < 100; i++) {
243             instanceManager = new CacheManager(secondCacheConfiguration);
244             instanceManager.shutdown();
245         }
246         //Give the spools a chance to exit
247         Thread.sleep(300);
248         int endingThreadCount = countThreads();
249         //Allow a bit of variation.
250         assertTrue(endingThreadCount < startingThreadCount + 2);
251 
252     }
253 
254 
255     /**
256      * The expiry threads and spool threads share are now combined. This should save some.
257      *
258      * ehcache-big.xml has 70 caches that overflow to disk. Check that the DiskStore is not using
259      * more than 1 thread per DiskStore.
260      *
261      * ehcache-1.2.3 had 126 threads for this test.
262      * ehcache-1.2.4 has 71. 70 for the DiskStore thread and one shutdown hook
263      *                     
264      */
265     public void testCacheManagerThreads() throws CacheException, InterruptedException {
266         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache-big.xml");
267         int threads = countThreads();
268         assertTrue("More than 75 threads: " + threads , countThreads() <= 75);
269     }
270 
271     /**
272      * It should be possible to create a new CacheManager instance with the same disk configuration,
273      * provided the first was shutdown. Note that any persistent disk stores will be available to the second cache manager.
274      */
275     public void testInstanceCreateShutdownCreate() throws CacheException {
276         singletonManager = CacheManager.create();
277 
278         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
279         instanceManager = new CacheManager(secondCacheConfiguration);
280         instanceManager.shutdown();
281 
282         //shutting down instance should leave singleton ok
283         assertEquals(12, singletonManager.getCacheNames().length);
284 
285 
286         instanceManager = new CacheManager(secondCacheConfiguration);
287         assertNotNull(instanceManager);
288         assertEquals(8, instanceManager.getCacheNames().length);
289 
290 
291     }
292 
293     /**
294      * Tests programmatic creation of CacheManager with a programmatic Configuration.
295      * <p/>
296      * Tests:
297      * <ol>
298      * <li>adding a cache by name, which will use default cache
299      * <li>adding a Cache object
300      * <li>setting the DiskStore directory path
301      * </ol>
302      *
303      * @throws CacheException
304      */
305     public void testCreateCacheManagersProgrammatically() throws CacheException {
306 
307         Configuration configuration = new Configuration();
308         assertNotNull(configuration);
309 
310         CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
311         defaultCacheConfiguration.setEternal(false);
312         defaultCacheConfiguration.setName("defaultCache");
313         configuration.addDefaultCache(defaultCacheConfiguration);
314 
315         DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration();
316         diskStoreConfiguration.setPath("java.io.tmpdir");
317         configuration.addDiskStore(diskStoreConfiguration);
318 
319         instanceManager = new CacheManager(configuration);
320         assertNotNull(instanceManager);
321         assertEquals(0, instanceManager.getCacheNames().length);
322 
323         instanceManager.addCache("toBeDerivedFromDefaultCache");
324         Cache cache = new Cache("testCache", 1, true, false, 5, 2);
325         instanceManager.addCache(cache);
326 
327 
328         assertEquals(2, instanceManager.getCacheNames().length);
329 
330     }
331 
332     /**
333      * Checks we can get a cache
334      */
335     public void testGetCache() throws CacheException {
336         instanceManager = CacheManager.create();
337         Ehcache cache = instanceManager.getCache("sampleCache1");
338         assertNotNull(cache);
339     }
340 
341     /**
342      * Does the cache hang on to its instance?
343      */
344     public void testCacheManagerReferenceInstance() {
345         instanceManager = new CacheManager();
346         instanceManager.addCache("test");
347         Ehcache cache = instanceManager.getCache("test");
348         assertEquals("test", cache.getName());
349         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
350         CacheManager reference = cache.getCacheManager();
351         assertTrue(reference == instanceManager);
352     }
353 
354     /**
355      * Does a cache with a reference to a singleton hang on to it?
356      */
357     public void testCacheManagerReferenceSingleton() {
358         singletonManager = CacheManager.create();
359         singletonManager.addCache("test");
360         Ehcache cache = singletonManager.getCache("test");
361         assertEquals("test", cache.getName());
362         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
363         CacheManager reference = cache.getCacheManager();
364         assertTrue(reference == singletonManager);
365     }
366 
367     /**
368      * Checks we can disable ehcache using a system property
369      */
370     public void testDisableEhcache() throws CacheException, InterruptedException {
371         System.setProperty(Cache.NET_SF_EHCACHE_DISABLED, "true");
372         Thread.sleep(1000);
373         instanceManager = CacheManager.create();
374         Ehcache cache = instanceManager.getCache("sampleCache1");
375         assertNotNull(cache);
376         cache.put(new Element("key123", "value"));
377         Element element = cache.get("key123");
378         assertNull("When the disabled property is set all puts should be discarded", element);
379 
380         cache.putQuiet(new Element("key1234", "value"));
381         assertNull("When the disabled property is set all puts should be discarded", cache.get("key1234"));
382 
383         System.setProperty(Cache.NET_SF_EHCACHE_DISABLED, "false");
384 
385 
386     }
387 
388     /**
389      * Tests shutdown after shutdown.
390      */
391     public void testShutdownAfterShutdown() throws CacheException {
392         instanceManager = CacheManager.create();
393         assertEquals(Status.STATUS_ALIVE, instanceManager.getStatus());
394         instanceManager.shutdown();
395         assertEquals(Status.STATUS_SHUTDOWN, instanceManager.getStatus());
396         instanceManager.shutdown();
397         assertEquals(Status.STATUS_SHUTDOWN, instanceManager.getStatus());
398     }
399 
400     /**
401      * Tests create, shutdown, create
402      */
403     public void testCreateShutdownCreate() throws CacheException {
404         singletonManager = CacheManager.create();
405         assertEquals(Status.STATUS_ALIVE, singletonManager.getStatus());
406         singletonManager.shutdown();
407 
408         //check we can recreate the CacheManager on demand.
409         singletonManager = CacheManager.create();
410         assertNotNull(singletonManager);
411         assertEquals(12, singletonManager.getCacheNames().length);
412         assertEquals(Status.STATUS_ALIVE, singletonManager.getStatus());
413 
414         singletonManager.shutdown();
415         assertEquals(Status.STATUS_SHUTDOWN, singletonManager.getStatus());
416     }
417 
418     /**
419      * Tests removing a cache
420      */
421     public void testRemoveCache() throws CacheException {
422         singletonManager = CacheManager.create();
423         Ehcache cache = singletonManager.getCache("sampleCache1");
424         assertNotNull(cache);
425         singletonManager.removeCache("sampleCache1");
426         cache = singletonManager.getCache("sampleCache1");
427         assertNull(cache);
428 
429         //NPE tests
430         singletonManager.removeCache(null);
431         singletonManager.removeCache("");
432     }
433 
434     /**
435      * Tests adding a new cache with default config
436      */
437     public void testAddCache() throws CacheException {
438         singletonManager = CacheManager.create();
439         singletonManager.addCache("test");
440         singletonManager.addCache("test2");
441         Ehcache cache = singletonManager.getCache("test");
442         assertNotNull(cache);
443         assertEquals("test", cache.getName());
444         String[] cacheNames = singletonManager.getCacheNames();
445         boolean match = false;
446         for (int i = 0; i < cacheNames.length; i++) {
447             String cacheName = cacheNames[i];
448             if (cacheName.equals("test")) {
449                 match = true;
450             }
451         }
452         assertTrue(match);
453 
454         //NPE tests
455         singletonManager.addCache("");
456     }
457 
458     /**
459      * Tests we can add caches from the default where the default has listeners.
460      */
461     public void testAddCacheFromDefaultWithListeners() throws CacheException {
462         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + File.separator + "distribution"
463                 + File.separator + "ehcache-distributed1.xml");
464         singletonManager.addCache("test");
465         Ehcache cache = singletonManager.getCache("test");
466         assertNotNull(cache);
467         assertEquals("test", cache.getName());
468 
469         Set listeners = cache.getCacheEventNotificationService().getCacheEventListeners();
470         assertEquals(1, listeners.size());
471         for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
472             CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
473             assertTrue(cacheEventListener instanceof RMIAsynchronousCacheReplicator);
474         }
475     }
476 
477     /**
478      * Bug 1457268. Instance of RegisteredEventListeners shared between caches created from default cache.
479      * The issue also results in sharing of all references.
480      * This test makes sure each cache has its own.
481      */
482     public void testCachesCreatedFromDefaultDoNotShareListenerReferences() {
483         singletonManager = CacheManager.create();
484         singletonManager.addCache("newfromdefault1");
485         Cache cache1 = singletonManager.getCache("newfromdefault1");
486         singletonManager.addCache("newfromdefault2");
487         Cache cache2 = singletonManager.getCache("newfromdefault2");
488 
489         RegisteredEventListeners listeners1 = cache1.getCacheEventNotificationService();
490         RegisteredEventListeners listeners2 = cache2.getCacheEventNotificationService();
491         assertTrue(listeners1 != listeners2);
492 
493         Store diskStore1 = cache1.getDiskStore();
494         Store diskStore2 = cache2.getDiskStore();
495         assertTrue(diskStore1 != diskStore2);
496 
497     }
498 
499     /**
500      * Do bootstrap cache loaders work ok when created from the default cache?
501      */
502     public void testCachesCreatedFromDefaultWithBootstrapSet() {
503         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "distribution/ehcache-distributed1.xml");
504         singletonManager.addCache("newfromdefault1");
505         Cache newfromdefault1 = singletonManager.getCache("newfromdefault1");
506         singletonManager.addCache("newfromdefault2");
507         Cache newfromdefault2 = singletonManager.getCache("newfromdefault2");
508 
509         assertTrue(newfromdefault1 != newfromdefault2);
510 
511         BootstrapCacheLoader bootstrapCacheLoader1 = ((Cache) newfromdefault1).getBootstrapCacheLoader();
512         BootstrapCacheLoader bootstrapCacheLoader2 = ((Cache) newfromdefault2).getBootstrapCacheLoader();
513 
514         assertTrue(bootstrapCacheLoader1 != bootstrapCacheLoader2);
515 
516         assertNotNull(bootstrapCacheLoader1);
517         assertEquals(RMIBootstrapCacheLoader.class, bootstrapCacheLoader1.getClass());
518         assertEquals(true, bootstrapCacheLoader1.isAsynchronous());
519         assertEquals(5000000, ((RMIBootstrapCacheLoader) bootstrapCacheLoader1).getMaximumChunkSizeBytes());
520 
521     }
522 
523     /**
524      * Does clone work ok?
525      */
526     public void testCachesCreatedFromDefaultDoNotInteract() {
527         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "distribution/ehcache-distributed1.xml");
528         singletonManager.addCache("newfromdefault1");
529         Cache newfromdefault1 = singletonManager.getCache("newfromdefault1");
530         singletonManager.addCache("newfromdefault2");
531         Cache newfromdefault2 = singletonManager.getCache("newfromdefault2");
532 
533         assertTrue(newfromdefault1 != newfromdefault2);
534         assertFalse(newfromdefault1.getName().equals(newfromdefault2.getName()));
535         //status is an enum style class, so it ok for them to point to the same instance if they are the same
536         assertTrue(newfromdefault1.getStatus() == newfromdefault2.getStatus());
537         assertFalse(newfromdefault1.getGuid() == newfromdefault2.getGuid());
538     }
539 
540     /**
541      * Test using a cache which has been removed and replaced.
542      */
543     public void testStaleCacheReference() throws CacheException {
544         singletonManager = CacheManager.create();
545         singletonManager.addCache("test");
546         Ehcache cache = singletonManager.getCache("test");
547         assertNotNull(cache);
548         cache.put(new Element("key1", "value1"));
549 
550         assertEquals("value1", cache.get("key1").getObjectValue());
551         singletonManager.removeCache("test");
552         singletonManager.addCache("test");
553 
554         try {
555             cache.get("key1");
556             fail();
557         } catch (IllegalStateException e) {
558             assertEquals("The test Cache is not alive.", e.getMessage());
559         }
560     }
561 
562     /**
563      * Tests that we can run 69 caches, most with disk stores, with no ill effects
564      * <p/>
565      * Check that this is fast.
566      */
567     public void testCreateCacheManagerWithManyCaches() throws CacheException, InterruptedException {
568         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache-big.xml");
569         assertNotNull(singletonManager);
570         assertEquals(69, singletonManager.getCacheNames().length);
571 
572         String[] names = singletonManager.getCacheNames();
573         for (int i = 0; i < names.length; i++) {
574             String name = names[i];
575             Ehcache cache = singletonManager.getCache(name);
576             for (int j = 0; i < 100; i++) {
577                 cache.put(new Element(new Integer(j), "value"));
578             }
579         }
580         StopWatch stopWatch = new StopWatch();
581         for (int repeats = 0; repeats < 5000; repeats++) {
582             for (int i = 0; i < names.length; i++) {
583                 String name = names[i];
584                 Ehcache cache = singletonManager.getCache(name);
585                 for (int j = 0; i < 100; i++) {
586                     Element element = cache.get(name + j);
587                     if ((element == null)) {
588                         cache.put(new Element(new Integer(j), "value"));
589                     }
590                 }
591             }
592         }
593         long elapsedTime = stopWatch.getElapsedTime();
594         LOG.info("Time taken was: " + elapsedTime);
595         assertTrue("Time taken was: " + elapsedTime, elapsedTime < 5000);
596     }
597 
598     private int countThreads() {
599 
600         /**
601          * A class for visiting threads
602          */
603         class ThreadVisitor {
604 
605             private int threadCount;
606 
607 
608             // This method recursively visits all thread groups under `group'.
609             private void visit(ThreadGroup group, int level) {
610                 // Get threads in `group'
611                 int numThreads = group.activeCount();
612                 Thread[] threads = new Thread[numThreads * 2];
613                 numThreads = group.enumerate(threads, false);
614 
615                 // Enumerate each thread in `group'
616                 for (int i = 0; i < numThreads; i++) {
617                     // Get thread
618                     Thread thread = threads[i];
619                     threadCount++;
620                     LOG.debug(thread);
621                 }
622 
623                 // Get thread subgroups of `group'
624                 int numGroups = group.activeGroupCount();
625                 ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
626                 numGroups = group.enumerate(groups, false);
627 
628                 // Recursively visit each subgroup
629                 for (int i = 0; i < numGroups; i++) {
630                     visit(groups[i], level + 1);
631                 }
632             }
633 
634         }
635 
636         // Find the root thread group
637         ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
638         while (root.getParent() != null) {
639             root = root.getParent();
640         }
641 
642         // Visit each thread group
643         ThreadVisitor visitor = new ThreadVisitor();
644         visitor.visit(root, 0);
645         return visitor.threadCount;
646 
647 
648     }
649 
650 
651     /**
652      * Shows that a decorated cache can be substituted
653      */
654     public void testDecoratorRequiresDecoratedCache() {
655 
656         singletonManager = CacheManager.create();
657         Ehcache cache = singletonManager.getEhcache("sampleCache1");
658         //decorate and substitute
659         BlockingCache newBlockingCache = new BlockingCache(cache);
660         singletonManager.replaceCacheWithDecoratedCache(cache, newBlockingCache);
661         Ehcache blockingCache = singletonManager.getEhcache("sampleCache1");
662         blockingCache.get("unknownkey");
663     }
664 
665 
666     /**
667      * Shows that a decorated cache can be substituted
668      */
669     public void testDecoratorFailsIfUnderlyingCacheNotSame() {
670 
671         singletonManager = CacheManager.create();
672         Ehcache cache = singletonManager.getEhcache("sampleCache1");
673         Ehcache cache2 = singletonManager.getEhcache("sampleCache2");
674         //decorate and substitute
675         BlockingCache newBlockingCache = new BlockingCache(cache2);
676         try {
677             singletonManager.replaceCacheWithDecoratedCache(cache, newBlockingCache);
678         } catch (CacheException e) {
679             //expected
680         }
681     }
682 
683     /**
684      * Shows that a decorated cache has decorated behaviour for methods that override Cache methods, without
685      * requiring a cast.
686      */
687     public void testDecoratorOverridesDefaultBehaviour() {
688 
689         singletonManager = CacheManager.create();
690         Ehcache cache = singletonManager.getEhcache("sampleCache1");
691         Element element = cache.get("key");
692         //default behaviour for a missing key
693         assertNull(element);
694 
695         //decorate and substitute
696         SelfPopulatingCache selfPopulatingCache = new SelfPopulatingCache(cache, new CountingCacheEntryFactory("value"));
697         selfPopulatingCache.get("key");
698         singletonManager.replaceCacheWithDecoratedCache(cache, selfPopulatingCache);
699 
700         Ehcache decoratedCache = singletonManager.getEhcache("sampleCache1");
701         Element element2 = cache.get("key");
702         assertEquals("value", element2.getObjectValue());
703     }
704 
705 
706     /**
707      * Test added after bug with multiple cachemanagers and programmatic cache creation
708      */
709     public void testMultipleCacheManagers() {
710         CacheManager[] managers = new CacheManager[2];
711         managers[0] = new CacheManager(makeCacheManagerConfig());
712         managers[1] = new CacheManager(makeCacheManagerConfig());
713 
714         managers[0].shutdown();
715         managers[1].shutdown();
716 
717 
718     }
719 
720     private static Configuration makeCacheManagerConfig() {
721         Configuration config = new Configuration();
722         CacheConfiguration defaults = new CacheConfiguration();
723         defaults.setEternal(true);
724         defaults.setDiskPersistent(false);
725         defaults.setOverflowToDisk(false);
726         defaults.setMaxElementsInMemory(10);
727         config.setDefaultCacheConfiguration(defaults);
728         return config;
729     }
730 
731     /**
732      * Make sure we can manipulate tmpdir. This is so continous integration builds can get
733      * the disk path zapped each run.
734      * 
735      */
736     public void testTmpDir() {
737         String tmp = System.getProperty("java.io.tmpdir");
738         System.setProperty("java.io.tmpdir", "greg");
739         assertEquals("greg", System.getProperty("java.io.tmpdir"));
740         System.setProperty("java.io.tmpdir", tmp);
741         assertEquals(tmp, System.getProperty("java.io.tmpdir"));
742 
743     }
744 }