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
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
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
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
115 cache.put(new Element("20", "20"));
116
117
118
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
142 cache.put(element);
143
144
145 cache.remove(key);
146
147
148 List notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
149 assertEquals(element, notifications.get(0));
150
151
152 cache.remove(key);
153 notifications = CountingCacheEventListener.getCacheElementsRemoved(cache);
154 assertEquals(1, notifications.size());
155
156
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
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
413 cache.put(element);
414 Thread.sleep(1001);
415
416
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
432 for (int i = 0; i < 20; i++) {
433 Element element = new Element("" + i, new Date());
434 cache.put(element);
435 }
436
437
438 Thread.sleep(1001);
439
440
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
461 for (int i = 0; i < 20; i++) {
462 Element element = new Element("" + i, new Date());
463 cache.put(element);
464 }
465
466
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 }