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.event;
18  
19  import junit.framework.TestCase;
20  import net.sf.ehcache.Cache;
21  import net.sf.ehcache.CacheException;
22  import net.sf.ehcache.CacheManager;
23  import net.sf.ehcache.Element;
24  import net.sf.ehcache.AbstractCacheTest;
25  
26  import java.io.IOException;
27  import java.io.Serializable;
28  import java.util.Date;
29  import java.util.List;
30  
31  /**
32   * Tests the cache listener functionality
33   *
34   * @author Greg Luck
35   * @version $Id: CacheEventListenerTest.java 44 2006-04-22 06:03:33Z gregluck $
36   */
37  public class CacheEventListenerTest extends TestCase {
38  
39      /**
40       * manager
41       */
42      protected CacheManager manager;
43      /**
44       * the cache name we wish to test
45       */
46      protected String cacheName = "sampleCache1";
47      /**
48       * the cache we wish to test
49       */
50      protected Cache cache;
51  
52      /**
53       * {@inheritDoc}
54       *
55       * @throws Exception
56       */
57      protected void setUp() throws Exception {
58          CountingCacheEventListener.resetCounters();
59          manager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache-countinglisteners.xml");
60          cache = manager.getCache(cacheName);
61          cache.removeAll();
62      }
63  
64  
65      /**
66       * {@inheritDoc}
67       *
68       * @throws Exception
69       */
70      protected void tearDown() throws Exception {
71          CountingCacheEventListener.resetCounters();
72          manager.shutdown();
73      }
74  
75      
76  
77  
78      /**
79       * Tests the put listener.
80       */
81      public void testPutNotifications() {
82  
83          Serializable key = new Date();
84          Serializable value = new Date();
85          Element element = new Element(key, value);
86  
87          //Put
88          cache.put(element);
89  
90          List notifications = CountingCacheEventListener.getCacheElementsPut(cache);
91  
92          assertTrue(notifications.size() == 1);
93          assertEquals(key, ((Element) notifications.get(0)).getObjectKey());
94          assertEquals(element.getObjectValue(), ((Element) notifications.get(0)).getObjectValue());
95  
96          //A put which updates records as one put, because the second one is an update
97          cache.put(element);
98          notifications = CountingCacheEventListener.getCacheElementsPut(cache);
99          assertTrue(notifications.size() == 1);
100 
101     }
102 
103     /**
104      * Tests the put and update listeners.
105      */
106     public void testUpdateNotifications() {
107 
108         //Put and update
109         for (int i = 0; i < 11; i++) {
110             cache.put(new Element("" + i, "" + i));
111             cache.put(new Element("" + i, "" + i));
112         }
113 
114         //Put with no update
115         cache.put(new Element("20", "20"));
116 
117 
118         //Should get 12 puts and 11 updates
119         List notifications = CountingCacheEventListener.getCacheElementsPut(cache);
120         assertTrue(notifications.size() == 12);
121         assertEquals("0", ((Element) notifications.get(0)).getObjectKey());
122         assertEquals("0", ((Element) notifications.get(0)).getObjectValue());
123 
124         notifications = CountingCacheEventListener.getCacheElementsUpdated(cache);
125         assertTrue(notifications.size() == 11);
126         assertEquals("0", ((Element) notifications.get(0)).getObjectKey());
127         assertEquals("0", ((Element) notifications.get(0)).getObjectValue());
128 
129 
130     }
131 
132     /**
133      * Tests the remove notifier
134      */
135     public void testRemoveNotifications() {
136 
137         Serializable key = "1";
138         Serializable value = new Date();
139         Element element = new Element(key, value);
140 
141         //Put
142         cache.put(element);
143 
144         //Check removal from MemoryStore
145         cache.remove(key);
146 
147 
148         List notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
149         assertEquals(element, notifications.get(0));
150 
151         //An unsuccessful remove should not notify
152         cache.remove(key);
153         notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
154         assertEquals(1, notifications.size());
155 
156         //check for NPE
157         cache.remove(null);
158 
159     }
160 
161     /**
162      * removeAll tests  - with listener
163      * 20 is enough to test this from Memory and Disk stores
164      */
165     public void testRemoveAllNotificationsWithListener() throws IOException {
166         for (int i = 0; i < 20; i++) {
167             cache.put(new Element("" + i, new Date()));
168         }
169 
170         cache.removeAll();
171         List notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
172         assertEquals(20, notifications.size());
173     }
174 
175     /**
176      * removeAll tests  - with listener. Time the elements out first.
177      * 20 is enough to test this from Memory and Disk stores
178      */
179     public void testRemoveAllNotificationsWithListenerExpiry() throws IOException, InterruptedException {
180         for (int i = 0; i < 20; i++) {
181             cache.put(new Element("" + i, new Date()));
182         }
183         Thread.sleep(1010);
184         cache.removeAll();
185         List notifications = CountingCacheEventListener.getCacheElementsExpired(cache);
186         assertEquals(20, notifications.size());
187         notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
188         assertEquals(0, notifications.size());
189     }
190 
191     /**
192      * removeAll tests - no listener. Checks no removal notifications
193      * 20 is enough to test this from Memory and Disk stores
194      */
195     public void testRemoveAllNotificationsNoListener() throws IOException {
196         for (int i = 0; i < 20; i++) {
197             cache.put(new Element("" + i, new Date()));
198         }
199 
200         Object[] cacheEventListeners = cache.getCacheEventNotificationService().getCacheEventListeners().toArray();
201         for (int i = 0; i < cacheEventListeners.length; i++) {
202             CacheEventListener cacheEventListener = (CacheEventListener) cacheEventListeners[i];
203             cache.getCacheEventNotificationService().unregisterListener(cacheEventListener);
204         }
205 
206         cache.removeAll();
207         List notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
208         assertEquals(0, notifications.size());
209     }
210 
211     /**
212      * removeAll tests - no listener. Checks
213      * 20 is enough to test this from Memory and Disk stores
214      */
215     public void testRemoveAllNotificationsNoListenerExpiry() throws IOException, InterruptedException {
216         for (int i = 0; i < 20; i++) {
217             cache.put(new Element("" + i, new Date()));
218         }
219 
220         Object[] cacheEventListeners = cache.getCacheEventNotificationService().getCacheEventListeners().toArray();
221         for (int i = 0; i < cacheEventListeners.length; i++) {
222             CacheEventListener cacheEventListener = (CacheEventListener) cacheEventListeners[i];
223             cache.getCacheEventNotificationService().unregisterListener(cacheEventListener);
224         }
225         Thread.sleep(1010);
226         cache.removeAll();
227         List notifications = CountingCacheEventListener.getCacheElementsExpired(cache);
228         assertEquals(0, notifications.size());
229         notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
230         assertEquals(0, notifications.size());
231     }
232 
233     /**
234      * When the <code>MemoryStore</code> overflows, and there is no disk
235      * store, then the element gets automatically removed. This should
236      * trigger a remove notification.
237      */
238     public void testEvictionFromLRUMemoryStoreNoExpiry() throws IOException, CacheException, InterruptedException {
239         String sampleCache2 = "sampleCache2";
240         cache = manager.getCache(sampleCache2);
241         cache.removeAll();
242         for (int i = 0; i < 10; i++) {
243             cache.put(new Element(i + "", new Date()));
244         }
245         cache.put(new Element(11 + "", new Date()));
246         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
247         assertEquals(1, removalNotifications.size());
248 
249         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
250         assertEquals(0, expiryNotifications.size());
251     }
252 
253     /**
254      * When the <code>MemoryStore</code> overflows, and there is no disk
255      * store, then the element gets automatically removed. This should
256      * trigger a remove notification.
257      */
258     public void testEvictionFromLRUMemoryStoreNotSerializable() throws IOException, CacheException, InterruptedException {
259         String sampleCache1 = "sampleCache1";
260         cache = manager.getCache(sampleCache1);
261         cache.removeAll();
262 
263         //should trigger a removal notification because it is not Serializable and will be evicted
264         cache.put(new Element(12 + "", new Object()));
265 
266         for (int i = 0; i < 10; i++) {
267             cache.put(new Element(i + "", new Date()));
268         }
269 
270         List removalNotifications2 = CountingCacheEventListener.getCacheElementsRemoved(cache);
271         assertEquals(1, removalNotifications2.size());
272 
273         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
274         assertEquals(0, expiryNotifications.size());
275     }
276 
277     /**
278      * When the <code>MemoryStore</code> overflows, and there is no disk
279      * store, then the element gets automatically removed. This should
280      * trigger a remove notification.
281      * <p/>
282      * If the element has expired, it should instead trigger an expiry notification.
283      */
284     public void testEvictionFromLRUMemoryStoreExpiry() throws IOException, CacheException, InterruptedException {
285         String sampleCache2 = "sampleCache2";
286         cache = manager.getCache(sampleCache2);
287         cache.removeAll();
288         for (int i = 0; i < 10; i++) {
289             cache.put(new Element(i + "", new Date()));
290         }
291 
292         Thread.sleep(1030);
293         cache.put(new Element(11 + "", new Date()));
294 
295         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
296         assertEquals(0, removalNotifications.size());
297 
298         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
299         assertEquals(1, expiryNotifications.size());
300     }
301 
302     /**
303      * When the <code>MemoryStore</code> overflows, and there is no disk
304      * store, then the element gets automatically removed. This should
305      * trigger a notification.
306      */
307     public void testEvictionFromFIFOMemoryStoreNoExpiry() throws IOException, CacheException {
308         String sampleCache3 = "sampleCache3";
309         cache = manager.getCache(sampleCache3);
310         cache.removeAll();
311         for (int i = 0; i < 10; i++) {
312             cache.put(new Element(i + "", new Date()));
313         }
314 
315         cache.put(new Element(11 + "", new Date()));
316 
317         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
318         assertEquals(1, removalNotifications.size());
319 
320         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
321         assertEquals(0, expiryNotifications.size());
322     }
323 
324     /**
325      * When the <code>MemoryStore</code> overflows, and there is no disk
326      * store, then the element gets automatically removed. This should
327      * trigger a notification.
328      * <p/>
329      * If the element has expired, it should instead trigger an expiry notification.
330      */
331     public void testEvictionFromFIFOMemoryStoreExpiry() throws IOException, CacheException, InterruptedException {
332         String sampleCache3 = "sampleCache3";
333         cache = manager.getCache(sampleCache3);
334         cache.removeAll();
335         for (int i = 0; i < 10; i++) {
336             cache.put(new Element(i + "", new Date()));
337         }
338 
339         Thread.sleep(1001);
340         cache.put(new Element(11 + "", new Date()));
341 
342         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
343         assertEquals(0, removalNotifications.size());
344 
345         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
346         assertEquals(1, expiryNotifications.size());
347     }
348 
349     /**
350      * When the <code>MemoryStore</code> overflows, and there is no disk
351      * store, then the element gets automatically removed. This should
352      * trigger a notification.
353      */
354     public void testEvictionFromLFUMemoryStoreNoExpiry() throws IOException, CacheException {
355         String sampleCache4 = "sampleCache4";
356         cache = manager.getCache(sampleCache4);
357         cache.removeAll();
358         for (int i = 0; i < 10; i++) {
359             cache.put(new Element(i + "", new Date()));
360         }
361 
362         cache.put(new Element(11 + "", new Date()));
363 
364         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
365         assertEquals(1, removalNotifications.size());
366 
367         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
368         assertEquals(0, expiryNotifications.size());
369     }
370 
371     /**
372      * When the <code>MemoryStore</code> overflows, and there is no disk
373      * store, then the element gets automatically removed. This should
374      * trigger a notification.
375      * <p/>
376      * If the element has expired, it should instead trigger an expiry notification.
377      */
378     public void testEvictionFromLFUMemoryStoreExpiry() throws IOException, CacheException, InterruptedException {
379         String sampleCache4 = "sampleCache4";
380         cache = manager.getCache(sampleCache4);
381         cache.removeAll();
382         for (int i = 0; i < 10; i++) {
383             cache.put(new Element(i + "", new Date()));
384         }
385 
386         Thread.sleep(1001);
387         cache.put(new Element(11 + "", new Date()));
388 
389         List removalNotifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
390         assertEquals(0, removalNotifications.size());
391 
392         List expiryNotifications = CountingCacheEventListener.getCacheElementsExpired(cache);
393         assertEquals(1, expiryNotifications.size());
394     }
395 
396 
397     /**
398      * Tests expiry notification is hooked up to searchInMemoryStore
399      *
400      * @throws InterruptedException
401      * @throws CacheException
402      */
403     public void testExpiryViaMemoryStoreCheckingOnGet() throws InterruptedException, CacheException, IOException {
404 
405         cache.removeAll();
406         CountingCacheEventListener.resetCounters();
407 
408         Serializable key = "1";
409         Serializable value = new Date();
410         Element element = new Element(key, value);
411 
412         //Check expiry from memory store in 1 second
413         cache.put(element);
414         Thread.sleep(1001);
415 
416         //Trigger expiry
417         cache.get(key);
418         List notifications = CountingCacheEventListener.getCacheElementsExpired(cache);
419         assertEquals(1, notifications.size());
420         assertEquals(element, notifications.get(0));
421     }
422 
423     /**
424      * Tests expiry notification is hooked up to searchInDiskStore.
425      * This test is not exact, because the expiry thread may also expire some.
426      *
427      * @throws InterruptedException
428      * @throws CacheException
429      */
430     public void testExpiryViaDiskStoreCheckingOnGet() throws InterruptedException, CacheException, IOException {
431         //Overflow 10 elements to disk store
432         for (int i = 0; i < 20; i++) {
433             Element element = new Element("" + i, new Date());
434             cache.put(element);
435         }
436 
437         //Wait for expiry
438         Thread.sleep(1001);
439 
440         //Trigger expiry
441         for (int i = 0; i < 20; i++) {
442             cache.get("" + i);
443         }
444 
445         List notifications = CountingCacheEventListener.getCacheElementsExpired(cache);
446         for (int i = 0; i < notifications.size(); i++) {
447             Element element = (Element) notifications.get(i);
448             element.getObjectKey();
449         }
450         assertTrue(notifications.size() >= 10);
451     }
452 
453 
454     /**
455      * Tests expiry thread expiry
456      *
457      * @throws InterruptedException
458      */
459     public void testExpiryViaDiskStoreExpiryThread() throws InterruptedException {
460         //Overflow 10 elements to disk store
461         for (int i = 0; i < 20; i++) {
462             Element element = new Element("" + i, new Date());
463             cache.put(element);
464         }
465 
466         //Wait for expiry and expiry thread
467         Thread.sleep(2050);
468 
469         List notifications = CountingCacheEventListener.getCacheElementsExpired(cache);
470         for (int i = 0; i < notifications.size(); i++) {
471             Element element = (Element) notifications.get(i);
472             element.getObjectKey();
473         }
474         assertEquals(10, notifications.size());
475 
476     }
477 
478 }