001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.oscache.general;
006:
007: import java.util.Date;
008:
009: import com.opensymphony.oscache.base.*;
010: import com.opensymphony.oscache.extra.CacheEntryEventListenerImpl;
011: import com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl;
012:
013: import junit.framework.Test;
014: import junit.framework.TestSuite;
015:
016: /**
017: * Test all the public methods of the GeneralCacheAdministrator class. Since
018: * this class extends the TestAbstractCacheAdministrator class, the
019: * AbstractCacheAdministrator is tested when invoking this class.
020: *
021: * $Id: TestGeneralCacheAdministrator.java 425 2007-03-18 09:45:03Z larst $
022: * @version $Revision: 425 $
023: * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
024: */
025: public class TestGeneralCacheAdministrator extends
026: TestAbstractCacheAdministrator {
027: // Constants used thru all the tests
028: private static final String KEY = "Test General Cache Admin Key";
029: private static final int NO_REFRESH_NEEDED = CacheEntry.INDEFINITE_EXPIRY;
030: private static final int REFRESH_NEEDED = 0;
031: private static final String CONTENT = "Content for the general cache admin test";
032: private static final String WILL_NOT_FLUSH_PATTERN = "This key won't flush";
033: private static final String GROUP1 = "group1";
034: private static final String GROUP2 = "group2";
035: private static final String GROUP3 = "group3";
036:
037: // Constants for listener counters
038: private static final int NB_CACHE_HITS = 7;
039: private static final int NB_CACHE_STALE_HITS = 7;
040: private static final int NB_CACHE_MISSED = 1;
041: private static final int NB_ADD = 7;
042: private static final int NB_UPDATED = 2;
043: private static final int NB_FLUSH = 3;
044: private static final int NB_REMOVED = 0;
045: private static final int NB_GROUP_FLUSH = 2;
046: private static final int NB_PATTERN_FLUSH = 1;
047:
048: // Static instance of a cache administrator
049: static GeneralCacheAdministrator admin = null;
050:
051: // Declare the listeners
052: private CacheEntryEventListenerImpl cacheEntryEventListener = null;
053: private CacheMapAccessEventListenerImpl cacheMapAccessEventListener = null;
054:
055: /**
056: * Class constructor
057: * <p>
058: * @param str Test name (required by JUnit)
059: */
060: public TestGeneralCacheAdministrator(String str) {
061: super (str);
062: }
063:
064: /**
065: * Test suite required to test this project
066: * <p>
067: * @return suite The test suite
068: */
069: public static Test suite() {
070: return new TestSuite(TestGeneralCacheAdministrator.class);
071: }
072:
073: /**
074: * Abstract method used by the TestAbstractCacheAdministrator class
075: * <p>
076: * @return An administrator instance
077: */
078: public AbstractCacheAdministrator getAdmin() {
079: return admin;
080: }
081:
082: /**
083: * This method is invoked before each testXXXX methods of the
084: * class. It set ups the variables required for each tests.
085: */
086: public void setUp() {
087: // At first invocation, create a administrator
088: admin = new GeneralCacheAdministrator();
089: assertNotNull(admin);
090: cacheEntryEventListener = new CacheEntryEventListenerImpl();
091: cacheMapAccessEventListener = new CacheMapAccessEventListenerImpl();
092:
093: // Register the listeners on the cache map
094: admin.getCache().addCacheEventListener(cacheEntryEventListener);
095: admin.getCache().addCacheEventListener(
096: cacheMapAccessEventListener);
097: }
098:
099: /**
100: * Validate the CacheEntryEventListener's data
101: */
102: public void testCacheEntryEventListenerCounters() {
103: populate();
104: assertEquals(NB_ADD, cacheEntryEventListener
105: .getEntryAddedCount());
106: assertEquals(NB_REMOVED, cacheEntryEventListener
107: .getEntryRemovedCount());
108: assertEquals(NB_UPDATED, cacheEntryEventListener
109: .getEntryUpdatedCount());
110: assertEquals(NB_GROUP_FLUSH, cacheEntryEventListener
111: .getGroupFlushedCount());
112: assertEquals(NB_PATTERN_FLUSH, cacheEntryEventListener
113: .getPatternFlushedCount());
114: assertEquals(NB_FLUSH, cacheEntryEventListener
115: .getEntryFlushedCount());
116: }
117:
118: /**
119: * Validate the CacheEntryEventListener's data
120: */
121: public void testCacheMapAccessEventListenerCounters() {
122: populate();
123:
124: int missCount = cacheMapAccessEventListener.getMissCount();
125:
126: if (NB_CACHE_MISSED != missCount) {
127: fail("We expected "
128: + NB_CACHE_MISSED
129: + " misses but got "
130: + missCount
131: + "."
132: + " This is probably due to existing disk cache, delete it and re-run"
133: + " the test");
134: }
135:
136: assertEquals(NB_CACHE_HITS, cacheMapAccessEventListener
137: .getHitCount());
138: assertEquals(NB_CACHE_STALE_HITS, cacheMapAccessEventListener
139: .getStaleHitCount());
140: }
141:
142: /**
143: * Ensure that item may be flushed by key pattern
144: */
145: public void testFlushPattern() {
146: // Put some content in cache
147: admin.putInCache(KEY, CONTENT);
148:
149: // Call flush pattern with parameters that must NOT flush our object
150: admin.flushPattern(WILL_NOT_FLUSH_PATTERN);
151: admin.flushPattern("");
152: admin.flushPattern(null);
153:
154: // Ensure that our object is not gone
155: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, false));
156:
157: // This time we flush it for real
158: admin.flushPattern(KEY.substring(1, 2));
159: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, true));
160: }
161:
162: /**
163: * Ensure that item may be flushed by the entry itself
164: */
165: public void testFlushEntry() {
166: // Put some content in cache
167: admin.putInCache(KEY, CONTENT);
168:
169: // Call flush pattern with parameters that must NOT flush our object
170: admin.flushEntry(WILL_NOT_FLUSH_PATTERN);
171:
172: // Ensure that our object is not gone
173: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, false));
174:
175: // This time we flush it for real
176: admin.flushEntry(KEY);
177: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, true));
178: }
179:
180: /**
181: * Ensure that item may be flushed by flush all
182: */
183: public void testFlushAll() {
184: // Put some content in cache
185: admin.putInCache(KEY, CONTENT);
186:
187: // Ensure that our object is not gone
188: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, false));
189:
190: // This time we flush it for real
191: admin.flushAll();
192: assertNotNull(checkObj(KEY, NO_REFRESH_NEEDED, true));
193: }
194:
195: /**
196: * Ensure that the cache groupings work correctly
197: */
198: public void testGroups() {
199: // Flush a non-existent group - should be OK and will still fire a GROUP_FLUSHED event
200: admin.flushGroup(GROUP1);
201:
202: // Add some items to various group combinations
203: admin.putInCache("1", "item 1"); // No groups
204: admin.putInCache("2", "item 2", new String[] { GROUP1 }); // Just group 1
205: admin.putInCache("3", "item 3", new String[] { GROUP2 }); // Just group 2
206: admin
207: .putInCache("4", "item 4", new String[] { GROUP1,
208: GROUP2 }); // groups 1 & 2
209: admin.putInCache("5", "item 5", new String[] { GROUP1, GROUP2,
210: GROUP3 }); // groups 1,2 & 3
211:
212: admin.flushGroup(GROUP3); // This should flush item 5 only
213: assertNotNull(checkObj("5", NO_REFRESH_NEEDED, true));
214: assertNotNull(checkObj("4", NO_REFRESH_NEEDED, false));
215:
216: admin.flushGroup(GROUP2); // This should flush items 3 and 4
217: assertNotNull(checkObj("1", NO_REFRESH_NEEDED, false));
218: assertNotNull(checkObj("2", NO_REFRESH_NEEDED, false));
219: assertNotNull(checkObj("3", NO_REFRESH_NEEDED, true));
220: assertNotNull(checkObj("4", NO_REFRESH_NEEDED, true));
221:
222: admin.flushGroup(GROUP1); // Flushes item 2
223: assertNotNull(checkObj("1", NO_REFRESH_NEEDED, false));
224: assertNotNull(checkObj("2", NO_REFRESH_NEEDED, true));
225:
226: // Test if regrouping a cache entry works
227: admin.putInCache("A", "ABC", new String[] { "A" });
228: admin.putInCache("A", "ABC", new String[] { "A", "B" });
229: admin.putInCache("B", "DEF", new String[] { "B" });
230: admin.flushGroup("B");
231: assertNotNull(checkObj("A", NO_REFRESH_NEEDED, true));
232: }
233:
234: /**
235: * Test the main cache functionalities, which are storing and retrieving objects
236: * from it
237: */
238: public void testPutInCacheAndGetFromCache() {
239: // Put some item in cache and get it back right away. It should not need
240: // to be refreshed
241: admin.putInCache(KEY, CONTENT);
242:
243: String cacheContent = (String) checkObj(KEY, NO_REFRESH_NEEDED,
244: false);
245: assertTrue(CONTENT.equals(cacheContent));
246:
247: // Get the item back again and expect a refresh
248: cacheContent = (String) checkObj(KEY, REFRESH_NEEDED, true);
249: assertTrue(CONTENT.equals(cacheContent));
250:
251: // Call the put in cache with invalid values
252: invalidPutInCacheArgument(null, null);
253: admin.putInCache(KEY, null); // This will still update the cache - cached items can be null
254:
255: // Call the getFromCache with invalid values
256: invalidGetFromCacheArgument(null, 0);
257:
258: // Try to retrieve the values
259: assertNull(checkObj(KEY, NO_REFRESH_NEEDED, false));
260:
261: // Try to retrieve an item that is not in the cache
262: Object obj = checkObj("Not in cache", NO_REFRESH_NEEDED, true);
263: assertNull(obj);
264: }
265:
266: /**
267: * Test the main cache functionalities, which are storing and retrieving objects
268: * from it
269: */
270: public void testPutInCacheAndGetFromCacheWithPolicy() {
271: String key = "policy";
272:
273: // We put content in the cache and get it back
274: admin.putInCache(key, CONTENT,
275: new DummyAlwayRefreshEntryPolicy());
276:
277: // Should get a refresh
278: try {
279: admin.getFromCache(key, -1);
280: fail("Should have got a refresh.");
281: } catch (NeedsRefreshException nre) {
282: admin.cancelUpdate(key);
283: }
284: }
285:
286: protected void tearDown() throws Exception {
287: if (admin != null) {
288: admin.getCache().removeCacheEventListener(
289: cacheEntryEventListener);
290: admin.getCache().removeCacheEventListener(
291: cacheMapAccessEventListener);
292: }
293: }
294:
295: /**
296: * Bug CACHE-241
297: */
298: public void testFlushDateTomorrow() {
299: GeneralCacheAdministrator cacheAdmin = new GeneralCacheAdministrator(
300: null);
301:
302: cacheAdmin.putInCache("key1", "key1value");
303:
304: try {
305: assertNotNull(cacheAdmin.getFromCache("key1"));
306: } catch (NeedsRefreshException e1) {
307: fail("Previous cache key1 doesn't exsits in GCA for the test!");
308: }
309:
310: cacheAdmin
311: .flushAll(new Date(System.currentTimeMillis() + 5000)); // flush in 5 sec.
312: try {
313: cacheAdmin.getFromCache("key1");
314: } catch (NeedsRefreshException e) {
315: cacheAdmin.cancelUpdate("key1");
316: fail("NRE is thrown, but key will expire in 5s."); // it fails here
317: }
318: }
319:
320: /**
321: * Utility method that tries to get an item from the cache and verify
322: * if all goes as expected
323: * <p>
324: * @param key The item key
325: * @param refresh The timestamp specifiying if the item needs refresh
326: * @param exceptionExpected Specify if we expect a NeedsRefreshException
327: */
328: private Object checkObj(String key, int refresh,
329: boolean exceptionExpected) {
330: // Cache content
331: Object content = null;
332:
333: try {
334: // try to find an object
335: content = admin.getFromCache(key, refresh);
336:
337: if (exceptionExpected) {
338: fail("Expected NeedsRefreshException!");
339: }
340: } catch (NeedsRefreshException nre) {
341: admin.cancelUpdate(key);
342:
343: if (!exceptionExpected) {
344: fail("Did not expected NeedsRefreshException!");
345: }
346:
347: // Return the cache content from the exception
348: content = nre.getCacheContent();
349: }
350:
351: return content;
352: }
353:
354: /**
355: * Method that try to retrieve data from the cache but specify wrong arguments
356: * <p>
357: * @param key The cache item key
358: * @param refresh The timestamp specifiying if the item needs refresh
359: */
360: private void invalidGetFromCacheArgument(String key, int refresh) {
361: try {
362: // Try to get the data from the cache
363: admin.getFromCache(key, refresh);
364: fail("getFromCache did NOT throw an IllegalArgumentException");
365: } catch (IllegalArgumentException ipe) {
366: // This is what we expect
367: } catch (NeedsRefreshException nre) {
368: admin.cancelUpdate(key);
369:
370: // Ignore this one
371: }
372: }
373:
374: /**
375: * Method that try to insert data in the cache but specify wrong arguments
376: * <p>
377: * @param key The cache item key
378: * @param content The content of the cache item
379: */
380: private void invalidPutInCacheArgument(String key, Object content) {
381: try {
382: // Try to put this data in the cache
383: admin.putInCache(key, content);
384: fail("putInCache did NOT throw an IllegalArgumentException");
385: } catch (IllegalArgumentException ipe) {
386: // This is what we expect
387: }
388: }
389:
390: private void populate() {
391: for (int i = 0; i < 7; i++) {
392: String[] groups = ((i & 1) == 0) ? new String[] { GROUP1,
393: GROUP2 } : new String[] { GROUP3 };
394: admin.putInCache(KEY + i, CONTENT + i, groups);
395: }
396:
397: //register one miss.
398: checkObj("Not in cache", NO_REFRESH_NEEDED, true);
399:
400: //register 7 hits
401: for (int i = 0; i < 7; i++) {
402: try {
403: admin.getFromCache(KEY + i, NO_REFRESH_NEEDED);
404: } catch (NeedsRefreshException e) {
405: admin.cancelUpdate(KEY + i);
406: }
407: }
408:
409: for (int i = 0; i < 7; i++) {
410: try {
411: admin.getFromCache(KEY + i, 0);
412: } catch (NeedsRefreshException e) {
413: admin.cancelUpdate(KEY + i);
414: }
415: }
416:
417: admin.putInCache(KEY + 1, CONTENT);
418: admin.putInCache(KEY + 2, CONTENT);
419: admin.flushPattern("blahblah");
420: admin.flushGroup(GROUP1);
421: admin.flushGroup(GROUP2);
422: }
423: }
|