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
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
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
144 instanceManager.shutdown();
145 assertEquals(element1, CacheManager.getInstance().getCache("sampleCache1").get(1 + ""));
146
147
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
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
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
174 Thread.sleep(300);
175 int endingThreadCount = countThreads();
176
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
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
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
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
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
458 private void visit(ThreadGroup group, int level) {
459
460 int numThreads = group.activeCount();
461 Thread[] threads = new Thread[numThreads * 2];
462 numThreads = group.enumerate(threads, false);
463
464
465 for (int i = 0; i < numThreads; i++) {
466
467 Thread thread = threads[i];
468 threadCount++;
469 LOG.info(thread);
470 }
471
472
473 int numGroups = group.activeGroupCount();
474 ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
475 numGroups = group.enumerate(groups, false);
476
477
478 for (int i = 0; i < numGroups; i++) {
479 visit(groups[i], level + 1);
480 }
481 }
482
483 }
484
485
486 ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
487 while (root.getParent() != null) {
488 root = root.getParent();
489 }
490
491
492 ThreadVisitor visitor = new ThreadVisitor();
493 visitor.visit(root, 0);
494 return visitor.threadCount;
495
496
497 }
498
499
500 }