001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064: package com.jcorporate.expresso.core.cache;
065:
066: import com.jcorporate.expresso.core.dbobj.ValidValue;
067: import com.jcorporate.expresso.services.test.ExpressoTestCase;
068: import com.jcorporate.expresso.services.test.TestSystemInitializer;
069: import junit.framework.Test;
070: import junit.framework.TestSuite;
071: import org.apache.log4j.Logger;
072:
073: /**
074: * A test case to verify the functions of the Expresso CacheManager and related
075: * objects.
076: *
077: * @author Michael Nash
078: * @since Expresso 4.0
079: */
080: public class CacheTest extends ExpressoTestCase {
081: private static final Logger log = Logger.getLogger(CacheTest.class);
082: private static int NUM_ITERATIONS = 40;
083:
084: /**
085: * Cache name, may be modified
086: */
087: private String cacheName = "testcache";
088:
089: /**
090: * Constructs a test case with the given name.
091: *
092: * @param name the testname
093: * @throws Exception upon instantiation error
094: */
095: public CacheTest(String name) throws Exception {
096: super (name);
097:
098: }
099:
100: /* CacheTest(String) */
101:
102: /**
103: * Main Thread for running this test
104: *
105: * @param args command arguments
106: * @throws Exception upon error
107: */
108: public static void main(String[] args) throws Exception {
109: //Set the system properties we need
110: junit.textui.TestRunner.run(suite());
111: }
112:
113: /**
114: * Helper function called from CacheTestThread for multiple instances
115: * of caches
116: *
117: * @param newName The new cache name
118: */
119: public void setCacheName(String newName) {
120: cacheName = newName;
121: }
122:
123: /**
124: * Sets up the fixture, for example, open a network connection. This method
125: * is called before a test is executed.
126: */
127: public void setUp() throws Exception {
128: try {
129: CacheManager.createCache(TestSystemInitializer
130: .getTestContext(), cacheName, false);
131:
132: /* Create an ordered cache as well */
133: CacheManager.createCache(TestSystemInitializer
134: .getTestContext(), cacheName + "O", true);
135: } catch (java.util.ConcurrentModificationException cme) {
136: log.error("Error Setting Up", cme);
137: throw cme;
138: }
139: }
140:
141: /* setUp() */
142:
143: /**
144: * Counts the number of test cases executed by run(TestResult result).
145: *
146: * @return integer (1)
147: */
148: public int countTestCases() {
149: return 1;
150: }
151:
152: /* countTestCases() */
153:
154: /**
155: * Define the suite of tests that verify each function of the cache
156: *
157: * @return junit.framework.TestSuite
158: */
159: public static Test suite() throws Exception {
160: TestSuite suite = new TestSuite("Cache Tests");
161:
162: for (int i = 0; i < NUM_ITERATIONS; i++) {
163: suite.addTestSuite(CacheTest.class);
164: }
165:
166: return suite;
167: }
168:
169: /* suite() */
170:
171: /**
172: * Tears down the fixture, for example, close a network connection. This
173: * method is called after a test is executed.
174: */
175: public void tearDown() throws Exception {
176: try {
177: CacheManager.clear(TestSystemInitializer.getTestContext(),
178: cacheName);
179: CacheManager.clear(TestSystemInitializer.getTestContext(),
180: cacheName + "O");
181: } catch (java.util.ConcurrentModificationException cme) {
182: log.error("Error Tearing Down", cme);
183: throw cme;
184: }
185: }
186:
187: /* tearDown() */
188:
189: /**
190: * Test adding an item to a cache that does not exist to ensure it gets
191: * created
192: */
193: public void testCreateCache() {
194: try {
195: ValidValue b = new ValidValue("b", "b");
196: ValidValue c = new ValidValue("c", "c");
197:
198: if (CacheManager.existsCache(TestSystemInitializer
199: .getTestContext(), cacheName)) {
200: if (log.isInfoEnabled()) {
201: log.debug("Clearing cache: " + cacheName);
202: }
203:
204: CacheManager.clear(TestSystemInitializer
205: .getTestContext(), cacheName);
206: }
207:
208: CacheManager.addItem(
209: TestSystemInitializer.getTestContext(), cacheName,
210: b);
211:
212: ValidValue retrieved = (ValidValue) CacheManager.getItem(
213: TestSystemInitializer.getTestContext(), cacheName,
214: "b");
215:
216: if (retrieved == null) {
217: log
218: .warn("'b' didn't exist in the test cache. This may or may"
219: + " not be a problem depending if we've removed caches or not");
220: } else {
221: if (!retrieved.getDescription().equals("b")) {
222: fail("Unable to retrieve item 'b' from test cache");
223: } else {
224: log.debug("Got item 'b' back from cache");
225: }
226: }
227: } catch (CacheException ce) {
228: log.error(ce);
229: fail("CacheException occurred - see log");
230: } catch (java.util.ConcurrentModificationException cme) {
231: cme.printStackTrace();
232: log.error(cme);
233: fail("ConcurrantModificationException - see log");
234: }
235: }
236:
237: /* testCreateCache() */
238:
239: /**
240: * Test adding an item to a cache that does not exist to ensure it gets
241: * created
242: */
243: public void testCreateOrderedCache() {
244: try {
245: ValidValue b = new ValidValue("bO", "bO");
246: ValidValue c = new ValidValue("cO", "cO");
247:
248: if (CacheManager.existsCache(TestSystemInitializer
249: .getTestContext(), cacheName + "O")) {
250: CacheManager.clear(TestSystemInitializer
251: .getTestContext(), cacheName + "O");
252: }
253:
254: CacheManager.addItem(
255: TestSystemInitializer.getTestContext(), cacheName
256: + "O", b);
257:
258: ValidValue retrieved = (ValidValue) CacheManager.getItem(
259: TestSystemInitializer.getTestContext(), cacheName
260: + "O", "bO");
261:
262: assertTrue(
263: "Got null back for item 'bO' from ordered test cache",
264: retrieved != null);
265: assertTrue("Unable to retrieve item 'bO' from test cache",
266: retrieved.getDescription().equals("bO"));
267: } catch (CacheException ce) {
268: log.error(ce);
269: fail("CacheException occurred - see log");
270: } catch (java.util.ConcurrentModificationException cme) {
271: log.error(cme);
272: fail("ConcurrantModificationException - see log");
273: }
274: }
275:
276: /* testCreateOrderedCache() */
277:
278: /**
279: * Test multiple items to ensure the value and it's appropriate key are not
280: * being mixed up
281: */
282: public void testMultipleItems() {
283: try {
284: ValidValue b = new ValidValue("b", "b");
285: ValidValue c = new ValidValue("c", "c");
286: CacheManager.addItem(
287: TestSystemInitializer.getTestContext(), cacheName,
288: b);
289: CacheManager.addItem(
290: TestSystemInitializer.getTestContext(), cacheName,
291: c);
292:
293: ValidValue retrieved = (ValidValue) CacheManager.getItem(
294: TestSystemInitializer.getTestContext(), cacheName,
295: "b");
296:
297: assertTrue(
298: "Got null back for item 'b' from ordered test cache",
299: retrieved != null);
300: assertTrue("Unable to retrieve item 'b' from test cache",
301: retrieved.getDescription().equals("b"));
302:
303: retrieved = (ValidValue) CacheManager.getItem(
304: TestSystemInitializer.getTestContext(), cacheName,
305: "c");
306: assertTrue(
307: "Got null back for item 'b' from ordered test cache",
308: retrieved != null);
309:
310: assertTrue("Unable to retrieve item 'c' from test cache",
311: retrieved.getDescription().equals("c"));
312:
313: } catch (CacheException ce) {
314: log.error(ce);
315: fail("CacheException occurred - see log");
316: } catch (java.util.ConcurrentModificationException cme) {
317: log.error(cme);
318: fail("ConcurrantModificationException - see log");
319: }
320: }
321:
322: /* testMultipleItems() */
323:
324: /**
325: * Test multiple items to ensure the value and it's appropriate key are not
326: * being mixed up
327: */
328: public void testOrderedMultipleItems() {
329: try {
330: ValidValue b = new ValidValue("bO", "bO");
331: ValidValue c = new ValidValue("cO", "cO");
332: CacheManager.addItem(
333: TestSystemInitializer.getTestContext(), cacheName
334: + "O", b);
335: CacheManager.addItem(
336: TestSystemInitializer.getTestContext(), cacheName
337: + "O", c);
338:
339: ValidValue retrieved = (ValidValue) CacheManager.getItem(
340: TestSystemInitializer.getTestContext(), cacheName
341: + "O", "bO");
342:
343: assertTrue(
344: "Got null back for item 'b0' from ordered test cache",
345: retrieved != null);
346: assertTrue("Unable to retrieve item 'bO' from test cache",
347: retrieved.getDescription().equals("bO"));
348:
349: retrieved = (ValidValue) CacheManager.getItem(
350: TestSystemInitializer.getTestContext(), cacheName
351: + "O", "cO");
352:
353: assertTrue(
354: "Got null back for item 'c0' from ordered test cache",
355: retrieved != null);
356:
357: assertTrue("Unable to retrieve item 'cO' from test cache",
358: retrieved.getDescription().equals("cO"));
359: } catch (CacheException ce) {
360: log.error(ce);
361: fail("CacheException occurred - see log");
362: } catch (java.util.ConcurrentModificationException cme) {
363: log.error(cme);
364: fail("ConcurrantModificationException - see log");
365: }
366: }
367:
368: /* testMultipleItems() */
369:
370: /**
371: * All this class's goal is to try to test if we're going to get a
372: * <code>java.util.ConcurrentModificationException</code> or
373: * <code>java.lang.NullPointerException</code>. We write and trash
374: * various cache names. We don't care if the values exist, we're just
375: * randomly beating on the cache to try to get an exception
376: */
377: public void testRandomCaches() {
378: String[] aCacheNames = { "random-testCache-1",
379: "random-testCache-2", "random-testCache-3" };
380: ValidValue[] a = { new ValidValue("a", "a"),
381: new ValidValue("b", "b"), new ValidValue("c", "c") };
382:
383: try {
384: for (int i = 0; i < aCacheNames.length; i++) {
385: CacheManager.createCache(TestSystemInitializer
386: .getTestContext(), aCacheNames[i], true);
387:
388: for (int j = 0; j < a.length; j++) {
389: CacheManager.addItem(TestSystemInitializer
390: .getTestContext(), aCacheNames[i], a[j],
391: 10000);
392: CacheManager.getItemCount(TestSystemInitializer
393: .getTestContext(), aCacheNames[i]);
394: CacheManager.getItem(TestSystemInitializer
395: .getTestContext(), aCacheNames[i], a[j]
396: .getKey());
397: CacheManager.removeItem(TestSystemInitializer
398: .getTestContext(), aCacheNames[i], a[j]);
399: }
400: }
401:
402: for (int i = 0; i < aCacheNames.length; i++) {
403: CacheManager.clear(TestSystemInitializer
404: .getTestContext(), aCacheNames[i]);
405: }
406:
407: for (int i = 0; i < aCacheNames.length; i++) {
408: CacheManager.createCache(TestSystemInitializer
409: .getTestContext(), aCacheNames[i], true);
410:
411: for (int j = 0; j < a.length; j++) {
412: CacheManager.addItem(TestSystemInitializer
413: .getTestContext(), aCacheNames[i], a[j],
414: 10000);
415: CacheManager.getItemCount(TestSystemInitializer
416: .getTestContext(), aCacheNames[i]);
417: CacheManager.getItem(TestSystemInitializer
418: .getTestContext(), aCacheNames[i], a[j]
419: .getKey());
420: CacheManager.removeItem(TestSystemInitializer
421: .getTestContext(), aCacheNames[i], a[j]);
422: }
423: }
424:
425: for (int i = 0; i < aCacheNames.length; i++) {
426: CacheManager.clear(TestSystemInitializer
427: .getTestContext(), aCacheNames[i]);
428: }
429: } catch (java.util.ConcurrentModificationException ce) {
430: ce.printStackTrace();
431: fail("Error during random tests: " + ce.getMessage());
432: } catch (java.lang.NullPointerException npe) {
433: npe.printStackTrace();
434: fail("Error during random tests." + npe.getMessage());
435: } catch (Throwable t) {
436: t.printStackTrace();
437: fail("Error during random tests." + t.getMessage());
438: }
439: }
440:
441: /**
442: * Tests to make sure that when an item is removed from one cache, potentially
443: * because it is stale, that related caches should be cleared as well.
444: */
445: public void testRelatedCaches() {
446: try {
447: CacheSystem cs = CacheManager
448: .getCacheSystem(TestSystemInitializer
449: .getTestContext());
450:
451: /* Now test "related" caches - we create 2 caches, one listening to the */
452: /* other, then modify an item */
453: /* in the first cache & make sure the second gets cleared */
454: cs.createCache("firstCache" + cacheName, false);
455:
456: ValidValue a = new ValidValue("a", "a");
457: cs.addItem("firstCache" + cacheName, a);
458: cs.createCache("secondCache" + cacheName, false);
459:
460: ValidValue b = new ValidValue("b", "b");
461: cs.addItem("secondCache" + cacheName, b);
462:
463: ValidValue returnValue1 = (ValidValue) cs.getItem(
464: "secondCache" + cacheName, b.getKey());
465:
466: assertTrue(
467: "Item 'b' did not cache correctly in secondCache",
468: returnValue1 != null);
469:
470: cs.addListener("secondCache" + cacheName, "firstCache"
471: + cacheName);
472: cs.removeItem("firstCache" + cacheName, a);
473:
474: /* this should have cleared secondCache */
475: ValidValue returnValue = (ValidValue) cs.getItem(
476: "secondCache" + cacheName, b.getKey());
477:
478: assertTrue("Cache secondCache" + cacheName
479: + " should have been cleared when"
480: + "item was deleted from firstCache" + cacheName
481: + " - cache listener error", returnValue == null);
482:
483: } catch (CacheException ce) {
484: log.error(ce);
485: fail("CacheException ocurred - see log");
486: } catch (java.util.ConcurrentModificationException cme) {
487: log.error(cme);
488: fail("ConcurrantModificationException - see log");
489: }
490: }
491:
492: /**
493: * Checks listeners when dealing with put vs. add functionality.
494: */
495: public void testRelatedCachesWithAddingUnmodifiedItems() {
496: try {
497: CacheSystem cs = CacheManager
498: .getCacheSystem(TestSystemInitializer
499: .getTestContext());
500:
501: /* Now test "related" caches - we create 2 caches, one listening to the */
502: /* other, then modify an item */
503: /* in the first cache & make sure the second gets cleared */
504: cs.createCache("firstCache" + cacheName, false);
505:
506: ValidValue a = new ValidValue("a", "a");
507: cs.addItem("firstCache" + cacheName, a);
508: cs.createCache("secondCache" + cacheName, false);
509:
510: ValidValue b = new ValidValue("b", "b");
511: cs.addItem("secondCache" + cacheName, b);
512:
513: ValidValue returnValue1 = (ValidValue) CacheManager
514: .getItem(TestSystemInitializer.getTestContext(),
515: "secondCache" + cacheName, b.getKey());
516:
517: assertTrue(
518: "Item 'b' did not cache correctly in secondCache",
519: returnValue1 != null);
520:
521: cs.addListener("secondCache" + cacheName, "firstCache"
522: + cacheName);
523:
524: ValidValue c = new ValidValue("c", "c");
525: ValidValue d = new ValidValue("d", "d");
526:
527: //This should NOT clear second cache
528: cs.put("firstCache" + cacheName, c);
529:
530: ValidValue returnValue = (ValidValue) CacheManager.getItem(
531: TestSystemInitializer.getTestContext(),
532: "secondCache" + cacheName, b.getKey());
533:
534: assertTrue("returnValue should not be null",
535: returnValue != null);
536:
537: cs.addItem("firstCache" + cacheName, d);
538:
539: /* this should have cleared secondCache */
540: returnValue = (ValidValue) CacheManager.getItem(
541: TestSystemInitializer.getTestContext(),
542: "secondCache" + cacheName, b.getKey());
543:
544: assertTrue("returnValue should now be null",
545: returnValue == null);
546:
547: } catch (CacheException ce) {
548: log.error(ce);
549: fail("CacheException ocurred - see log");
550: } catch (java.util.ConcurrentModificationException cme) {
551: log.error(cme);
552: fail("ConcurrantModificationException - see log");
553: }
554: }
555:
556: /**
557: * Most basic possible test. If you put something in a cache, can you get
558: * it back out again?
559: */
560: public void testSimpleCaching() {
561: try {
562: ValidValue a = new ValidValue("a", "a");
563: CacheManager.addItem(
564: TestSystemInitializer.getTestContext(), cacheName,
565: a);
566:
567: ValidValue retrieved = (ValidValue) CacheManager.getItem(
568: TestSystemInitializer.getTestContext(), cacheName,
569: "a");
570:
571: if (retrieved == null) {
572: fail("Got null back for item 'a' from test cache");
573: } else {
574: if (!retrieved.getDescription().equals("a")) {
575: fail("Unable to retrieve item 'a' from test cache");
576: } else {
577: log.debug("Got item 'a' back from cache");
578: }
579: }
580: } catch (CacheException ce) {
581: log.error(ce);
582: fail("Cache exception occurred - see log");
583: } catch (java.util.ConcurrentModificationException cme) {
584: log.error("Error testing simple caching", cme);
585: throw cme;
586: }
587: }
588:
589: /**
590: * Most basic possible test. If you put something in a cache, can you get
591: * it back out again?
592: */
593: public void testSimpleOrderedCaching() {
594: try {
595: ValidValue a = new ValidValue("aO", "aO");
596: CacheManager.addItem(
597: TestSystemInitializer.getTestContext(), cacheName
598: + "O", a);
599:
600: ValidValue retrieved = (ValidValue) CacheManager.getItem(
601: TestSystemInitializer.getTestContext(), cacheName
602: + "O", "aO");
603:
604: if (retrieved == null) {
605: fail("Got null back for item 'aO' from ordered test cache");
606: } else {
607: if (!retrieved.getDescription().equals("aO")) {
608: fail("Unable to retrieve item 'aO' from ordered test cache");
609: } else {
610: log.debug("Got item 'aO' back from cache");
611: }
612: }
613: } catch (CacheException ce) {
614: log.error(ce);
615: fail("Cache exception occurred - see log");
616: } catch (java.util.ConcurrentModificationException cme) {
617: log.error(cme);
618: fail("ConcurrantModificationException - see log");
619: }
620: }
621:
622: }
|