View Javadoc

1   /**
2    *  Copyright 2003-2006 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache;
18  
19  import junit.framework.TestCase;
20  import net.sf.ehcache.config.CacheConfiguration;
21  import net.sf.ehcache.config.Configuration;
22  import net.sf.ehcache.config.ConfigurationFactory;
23  import net.sf.ehcache.config.DiskStoreConfiguration;
24  import net.sf.ehcache.event.RegisteredEventListeners;
25  import net.sf.ehcache.store.DiskStore;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import java.io.File;
30  import java.io.FileInputStream;
31  import java.io.InputStream;
32  import java.net.URL;
33  import java.util.Date;
34  
35  /**
36   * Tests for CacheManager
37   *
38   * @author Greg Luck
39   * @version $Id: CacheManagerTest.java 52 2006-04-24 14:50:03Z gregluck $
40   */
41  public class CacheManagerTest extends TestCase {
42      private static final Log LOG = LogFactory.getLog(CacheManagerTest.class.getName());
43  
44      /**
45       * the CacheManager Singleton instance
46       */
47      protected CacheManager singletonManager;
48  
49      /**
50       * a CacheManager which is created as an instance
51       */
52      protected CacheManager instanceManager;
53  
54      /**
55       * Shutdown managers and check for thread leak.
56       */
57      protected void tearDown() throws Exception {
58          if (singletonManager != null) {
59              singletonManager.shutdown();
60          }
61          if (instanceManager != null) {
62              instanceManager.shutdown();
63          }
64      }
65  
66  
67      /**
68       * Tests that the CacheManager was successfully created
69       */
70      public void testCreateCacheManager() throws CacheException {
71          singletonManager = CacheManager.create();
72          assertNotNull(singletonManager);
73          assertTrue(singletonManager.getCacheNames().length == 8);
74      }
75  
76      /**
77       * Tests that the CacheManager was successfully created
78       */
79      public void testCreateCacheManagerFromFile() throws CacheException {
80          singletonManager = CacheManager.create(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
81          assertNotNull(singletonManager);
82          assertEquals(5, singletonManager.getCacheNames().length);
83      }
84  
85      /**
86       * Tests that the CacheManager was successfully created from a Configuration
87       */
88      public void testCreateCacheManagerFromConfiguration() throws CacheException {
89          File file = new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
90          Configuration configuration = ConfigurationFactory.parseConfiguration(file);
91          CacheManager manager = new CacheManager(configuration);
92          assertNotNull(manager);
93          assertEquals(5, manager.getCacheNames().length);
94          manager.shutdown();
95      }
96  
97      /**
98       * Tests that the CacheManager was successfully created
99       */
100     public void testCreateCacheManagerFromInputStream() throws Exception {
101         InputStream fis = new FileInputStream(new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml").getAbsolutePath());
102         try {
103             singletonManager = CacheManager.create(fis);
104         } finally {
105             fis.close();
106         }
107         assertNotNull(singletonManager);
108         assertEquals(5, singletonManager.getCacheNames().length);
109     }
110 
111     /**
112      * Tests that creating a second cache manager with the same disk path will fail.
113      */
114     public void testCreateTwoCacheManagersWithSamePath() throws CacheException {
115         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
116 
117         singletonManager = CacheManager.create(secondCacheConfiguration);
118         try {
119             instanceManager = new CacheManager(secondCacheConfiguration);
120             fail();
121         } catch (CacheException e) {
122             //expected
123         }
124     }
125 
126     /**
127      * Tests that two CacheManagers were successfully created
128      */
129     public void testTwoCacheManagers() throws CacheException {
130         Element element1 = new Element(1 + "", new Date());
131         Element element2 = new Element(2 + "", new Date());
132 
133         CacheManager.getInstance().getCache("sampleCache1").put(element1);
134 
135         //Check can start second one with a different disk path
136         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
137         instanceManager = new CacheManager(secondCacheConfiguration);
138         instanceManager.getCache("sampleCache1").put(element2);
139 
140         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
141         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
142 
143         //shutting down instance should leave singleton unaffected
144         instanceManager.shutdown();
145         assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
146 
147         //Try shutting and recreating a new instance cache manager
148         instanceManager = new CacheManager(secondCacheConfiguration);
149         instanceManager.getCache("sampleCache1").put(element2);
150         CacheManager.getInstance().shutdown();
151         assertEquals(element2, instanceManager.getCache("sampleCache1").get(2 + ""));
152 
153         //Try shutting and recreating the singleton cache manager
154         CacheManager.getInstance().getCache("sampleCache1").put(element2);
155         assertNull(CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
156         assertEquals(element2, CacheManager.getInstance().getCache("sampleCache1").get(2 + ""));
157     }
158 
159     /**
160      * Create and destory cache managers and see what happens with threads.
161      * Each Cache creates at least two threads. These should all be killed when the Cache
162      * disposes. Doing that 800 times as in that test gives the reassurance.
163      */
164     public void testForCacheManagerThreadLeak() throws CacheException, InterruptedException {
165         //Check can start second one with a different disk path
166         int startingThreadCount = countThreads();
167 
168         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
169         for (int i = 0; i < 100; i++) {
170             instanceManager = new CacheManager(secondCacheConfiguration);
171             instanceManager.shutdown();
172         }
173         //Give the spools a chance to exit
174         Thread.sleep(300);
175         int endingThreadCount = countThreads();
176         //Allow a bit of variation.
177         assertTrue(endingThreadCount < startingThreadCount + 2);
178 
179     }
180 
181     /**
182      * It should be possible to create a new CacheManager instance with the same disk configuration,
183      * provided the first was shutdown. Note that any persistent disk stores will be available to the second cache manager.
184      */
185     public void testInstanceCreateShutdownCreate() throws CacheException {
186         singletonManager = CacheManager.create();
187 
188         URL secondCacheConfiguration = this.getClass().getResource("/ehcache-2.xml");
189         instanceManager = new CacheManager(secondCacheConfiguration);
190         instanceManager.shutdown();
191 
192         //shutting down instance should leave singleton ok
193         assertTrue(singletonManager.getCacheNames().length == 8);
194 
195 
196         instanceManager = new CacheManager(secondCacheConfiguration);
197         assertNotNull(instanceManager);
198         assertTrue(instanceManager.getCacheNames().length == 8);
199 
200 
201     }
202 
203     /**
204      * Tests programmatic creation of CacheManager with a programmatic Configuration.
205      * <p/>
206      * Tests:
207      * <ol>
208      * <li>adding a cache by name, which will use default cache
209      * <li>adding a Cache object
210      * <li>setting the DiskStore directory path
211      * </ol>
212      *
213      * @throws CacheException
214      */
215     public void testCreateCacheManagersProgrammatically() throws CacheException {
216 
217         Configuration configuration = new Configuration();
218         assertNotNull(configuration);
219 
220         CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
221         defaultCacheConfiguration.setEternal(false);
222         defaultCacheConfiguration.setName("defaultCache");
223         configuration.addDefaultCache(defaultCacheConfiguration);
224 
225         DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration();
226         diskStoreConfiguration.setPath("java.io.tmpdir");
227         configuration.addDiskStore(diskStoreConfiguration);
228 
229         instanceManager = new CacheManager(configuration);
230         assertNotNull(instanceManager);
231         assertEquals(0, instanceManager.getCacheNames().length);
232 
233         instanceManager.addCache("toBeDerivedFromDefaultCache");
234         Cache cache = new Cache("testCache", 1, true, false, 5, 2);
235         instanceManager.addCache(cache);
236 
237 
238         assertEquals(2, instanceManager.getCacheNames().length);
239 
240     }
241 
242     /**
243      * Checks we can get a cache
244      */
245     public void testGetCache() throws CacheException {
246         instanceManager = CacheManager.create();
247         Cache cache = instanceManager.getCache("sampleCache1");
248         assertNotNull(cache);
249     }
250 
251     /**
252      * Does the cache hang on to its instance?
253      */
254     public void testCacheManagerReferenceInstance() {
255         instanceManager = new CacheManager();
256         instanceManager.addCache("test");
257         Cache cache = instanceManager.getCache("test");
258         assertEquals("test", cache.getName());
259         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
260         CacheManager reference = cache.getCacheManager();
261         assertTrue(reference == instanceManager);
262     }
263 
264     /**
265      * Does a cache with a reference to a singleton hang on to it?
266      */
267     public void testCacheManagerReferenceSingleton() {
268         singletonManager = CacheManager.create();
269         singletonManager.addCache("test");
270         Cache cache = singletonManager.getCache("test");
271         assertEquals("test", cache.getName());
272         assertEquals(Status.STATUS_ALIVE, cache.getStatus());
273         CacheManager reference = cache.getCacheManager();
274         assertTrue(reference == singletonManager);
275     }
276 
277     /**
278      * Checks we can disable ehcache using a system property
279      */
280     public void testDisableEhcache() throws CacheException, InterruptedException {
281         System.setProperty(Cache.NET_SF_EHCACHE_DISABLED, "true");
282         Thread.sleep(1000);
283         instanceManager = CacheManager.create();
284         Cache cache = instanceManager.getCache("sampleCache1");
285         assertNotNull(cache);
286         cache.put(new Element("key123", "value"));
287         Element element = cache.get("key123");
288         assertNull("When the disabled property is set all puts should be discarded", element);
289 
290         cache.putQuiet(new Element("key1234", "value"));
291         assertNull("When the disabled property is set all puts should be discarded", cache.get("key1234"));
292 
293         System.setProperty(Cache.NET_SF_EHCACHE_DISABLED, "false");
294 
295 
296     }
297 
298     /**
299      * Tests shutdown after shutdown.
300      */
301     public void testShutdownAfterShutdown() throws CacheException {
302         instanceManager = CacheManager.create();
303         assertEquals(Status.STATUS_ALIVE, instanceManager.getStatus());
304         instanceManager.shutdown();
305         assertEquals(Status.STATUS_SHUTDOWN, instanceManager.getStatus());
306         instanceManager.shutdown();
307         assertEquals(Status.STATUS_SHUTDOWN, instanceManager.getStatus());
308     }
309 
310     /**
311      * Tests create, shutdown, create
312      */
313     public void testCreateShutdownCreate() throws CacheException {
314         singletonManager = CacheManager.create();
315         assertEquals(Status.STATUS_ALIVE, singletonManager.getStatus());
316         singletonManager.shutdown();
317 
318         //check we can recreate the CacheManager on demand.
319         singletonManager = CacheManager.create();
320         assertNotNull(singletonManager);
321         assertTrue(singletonManager.getCacheNames().length == 8);
322         assertEquals(Status.STATUS_ALIVE, singletonManager.getStatus());
323 
324         singletonManager.shutdown();
325         assertEquals(Status.STATUS_SHUTDOWN, singletonManager.getStatus());
326     }
327 
328     /**
329      * Tests removing a cache
330      */
331     public void testRemoveCache() throws CacheException {
332         singletonManager = CacheManager.create();
333         Cache cache = singletonManager.getCache("sampleCache1");
334         assertNotNull(cache);
335         singletonManager.removeCache("sampleCache1");
336         cache = singletonManager.getCache("sampleCache1");
337         assertNull(cache);
338 
339         //NPE tests
340         singletonManager.removeCache(null);
341         singletonManager.removeCache("");
342     }
343 
344     /**
345      * Tests adding a new cache with default config
346      */
347     public void testAddCache() throws CacheException {
348         singletonManager = CacheManager.create();
349         singletonManager.addCache("test");
350         Cache cache = singletonManager.getCache("test");
351         assertNotNull(cache);
352         assertEquals("test", cache.getName());
353         String[] cacheNames = singletonManager.getCacheNames();
354         boolean match = false;
355         for (int i = 0; i < cacheNames.length; i++) {
356             String cacheName = cacheNames[i];
357             if (cacheName.equals("test")) {
358                 match = true;
359             }
360         }
361         assertTrue(match);
362 
363         //NPE tests
364         singletonManager.addCache("");
365     }
366 
367     /**
368      * Bug 1457268. Instance of RegisteredEventListeners shared between caches created from default cache.
369      * The issue also results in sharing of all references.
370      * This test makes sure each cache has its own.
371      */
372     public void testCachesCreatedFromDefaultDoNotShareListenerReferences() {
373         singletonManager = CacheManager.create();
374         singletonManager.addCache("newfromdefault1");
375         Cache cache1 = singletonManager.getCache("newfromdefault1");
376         singletonManager.addCache("newfromdefault2");
377         Cache cache2 = singletonManager.getCache("newfromdefault2");
378 
379         RegisteredEventListeners listeners1 = cache1.getCacheEventNotificationService();
380         RegisteredEventListeners listeners2 = cache2.getCacheEventNotificationService();
381         assertTrue(listeners1 != listeners2);
382 
383         DiskStore diskStore1 = cache1.getDiskStore();
384         DiskStore diskStore2 = cache2.getDiskStore();
385         assertTrue(diskStore1 != diskStore2);
386 
387     }
388 
389     /**
390      * Test using a cache which has been removed and replaced.
391      */
392     public void testStaleCacheReference() throws CacheException {
393         singletonManager = CacheManager.create();
394         singletonManager.addCache("test");
395         Cache cache = singletonManager.getCache("test");
396         assertNotNull(cache);
397         cache.put(new Element("key1", "value1"));
398 
399         assertEquals("value1", cache.get("key1").getObjectValue());
400         singletonManager.removeCache("test");
401         singletonManager.addCache("test");
402 
403         try {
404             cache.get("key1");
405             fail();
406         } catch (IllegalStateException e) {
407             assertEquals("The test Cache is not alive.", e.getMessage());
408         }
409     }
410 
411     /**
412      * Tests that we can run 69 caches, most with disk stores, with no ill effects
413      * <p/>
414      * Check that this is fast.
415      */
416     public void testCreateCacheManagerWithManyCaches() throws CacheException, InterruptedException {
417         singletonManager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache-big.xml");
418         assertNotNull(singletonManager);
419         assertEquals(69, singletonManager.getCacheNames().length);
420 
421         String[] names = singletonManager.getCacheNames();
422         for (int i = 0; i < names.length; i++) {
423             String name = names[i];
424             Cache cache = singletonManager.getCache(name);
425             for (int j = 0; i < 100; i++) {
426                 cache.put(new Element(new Integer(j), "value"));
427             }
428         }
429         StopWatch stopWatch = new StopWatch();
430         for (int repeats = 0; repeats < 5000; repeats++) {
431             for (int i = 0; i < names.length; i++) {
432                 String name = names[i];
433                 Cache cache = singletonManager.getCache(name);
434                 for (int j = 0; i < 100; i++) {
435                     Element element = cache.get(name + j);
436                     if ((element == null)) {
437                         cache.put(new Element(new Integer(j), "value"));
438                     }
439                 }
440             }
441         }
442         long elapsedTime = stopWatch.getElapsedTime();
443         LOG.info("Time taken was: " + elapsedTime);
444         assertTrue(elapsedTime < 5000);
445     }
446 
447     private int countThreads() {
448 
449         /**
450          * A class for visiting threads
451          */
452         class ThreadVisitor {
453 
454             private int threadCount;
455 
456 
457             // This method recursively visits all thread groups under `group'.
458             private void visit(ThreadGroup group, int level) {
459                 // Get threads in `group'
460                 int numThreads = group.activeCount();
461                 Thread[] threads = new Thread[numThreads * 2];
462                 numThreads = group.enumerate(threads, false);
463 
464                 // Enumerate each thread in `group'
465                 for (int i = 0; i < numThreads; i++) {
466                     // Get thread
467                     Thread thread = threads[i];
468                     threadCount++;
469                     LOG.info(thread);
470                 }
471 
472                 // Get thread subgroups of `group'
473                 int numGroups = group.activeGroupCount();
474                 ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
475                 numGroups = group.enumerate(groups, false);
476 
477                 // Recursively visit each subgroup
478                 for (int i = 0; i < numGroups; i++) {
479                     visit(groups[i], level + 1);
480                 }
481             }
482 
483         }
484 
485         // Find the root thread group
486         ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
487         while (root.getParent() != null) {
488             root = root.getParent();
489         }
490 
491         // Visit each thread group
492         ThreadVisitor visitor = new ThreadVisitor();
493         visitor.visit(root, 0);
494         return visitor.threadCount;
495 
496 
497     }
498 
499 
500 }