001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package test.javax.management.timer;
010:
011: import java.util.Date;
012: import java.util.Vector;
013: import javax.management.InstanceNotFoundException;
014: import javax.management.MBeanServer;
015: import javax.management.MBeanServerInvocationHandler;
016: import javax.management.Notification;
017: import javax.management.NotificationFilter;
018: import javax.management.NotificationListener;
019: import javax.management.ObjectName;
020: import javax.management.timer.Timer;
021: import javax.management.timer.TimerMBean;
022: import javax.management.timer.TimerNotification;
023:
024: import test.MX4JTestCase;
025: import test.MutableBoolean;
026: import test.MutableInteger;
027: import test.MutableLong;
028:
029: /**
030: * @version $Revision: 1.13 $
031: */
032: public class TimerTest extends MX4JTestCase {
033: private MBeanServer m_server;
034: private ObjectName m_timerName;
035: private TimerMBean m_timer;
036:
037: public TimerTest(String s) {
038: super (s);
039: }
040:
041: protected void setUp() throws Exception {
042: m_server = newMBeanServer();
043: m_timerName = new ObjectName("Service:type=Timer");
044: m_server.createMBean("javax.management.timer.Timer",
045: m_timerName, null);
046: m_timer = (TimerMBean) MBeanServerInvocationHandler
047: .newProxyInstance(m_server, m_timerName,
048: TimerMBean.class, false);
049: }
050:
051: protected void tearDown() throws Exception {
052: m_server.unregisterMBean(m_timerName);
053: }
054:
055: public void testStartStop() throws Exception {
056: m_timer.start();
057: assertTrue(m_timer.isActive());
058: m_timer.stop();
059: assertFalse(m_timer.isActive());
060: }
061:
062: public void testStartStopStart() throws Exception {
063: m_timer.start();
064: assertTrue(m_timer.isActive());
065: m_timer.stop();
066: assertFalse(m_timer.isActive());
067: m_timer.start();
068: assertTrue(m_timer.isActive());
069: // Will be stopped during unregistration
070: }
071:
072: public void testOneShotNotification() throws Exception {
073: m_timer.start();
074:
075: final long now = System.currentTimeMillis();
076: final MutableInteger mid = new MutableInteger(-1);
077: final MutableInteger occurrencesCount = new MutableInteger(0);
078:
079: final String notifType = "timer-test";
080: final long delay = 3 * Timer.ONE_SECOND;
081:
082: NotificationListener listener = new NotificationListener() {
083: public void handleNotification(Notification notification,
084: Object handback) {
085: // Test that the listener has been called at the specified time
086: long elapsed = System.currentTimeMillis() - now;
087: assertTrue(elapsed >= delay);
088: assertFalse(elapsed - delay > 50);
089:
090: assertTrue(notification instanceof TimerNotification);
091:
092: Integer id = ((TimerNotification) notification)
093: .getNotificationID();
094: assertEquals(mid.get(), id.intValue());
095:
096: occurrencesCount.set(occurrencesCount.get() + 1);
097: }
098: };
099:
100: m_server.addNotificationListener(m_timerName, listener,
101: new NotificationFilter() {
102: public boolean isNotificationEnabled(
103: Notification notification) {
104: return notification.getType().equals(notifType);
105: }
106: }, null);
107:
108: // Notify after a while
109: Date date = new Date(now + delay);
110: // One shot notification at the specified time
111: Integer id = m_timer.addNotification(notifType,
112: "timer-message", "user-data", date);
113: mid.set(id.intValue());
114:
115: // Sleep to wait for the notification to happen
116: sleep(delay * 2);
117:
118: // Check notification arrived
119: assertTrue(occurrencesCount.get() == 1);
120:
121: // Check that it won't be notified again
122: assertTrue(m_timer.getNbNotifications() == 0);
123: }
124:
125: public void testPeriodicNotification() throws Exception {
126: m_timer.start();
127:
128: final String notifType = "timer-test";
129: final String periodicNotifType = "timer-test-periodic";
130:
131: final MutableInteger occurrencesCount = new MutableInteger(0);
132:
133: NotificationListener listener = new NotificationListener() {
134: public void handleNotification(Notification notification,
135: Object handback) {
136: occurrencesCount.set(occurrencesCount.get() + 1);
137: }
138: };
139:
140: final MutableInteger periodicOccurrences = new MutableInteger(0);
141: NotificationListener periodicListener = new NotificationListener() {
142: public void handleNotification(Notification notification,
143: Object handback) {
144: periodicOccurrences.set(periodicOccurrences.get() + 1);
145: }
146: };
147:
148: m_server.addNotificationListener(m_timerName, listener,
149: new NotificationFilter() {
150: public boolean isNotificationEnabled(
151: Notification notification) {
152: return notification.getType().equals(notifType);
153: }
154: }, null);
155: m_server.addNotificationListener(m_timerName, periodicListener,
156: new NotificationFilter() {
157: public boolean isNotificationEnabled(
158: Notification notification) {
159: return notification.getType().equals(
160: periodicNotifType);
161: }
162: }, null);
163:
164: // Register to happen 3 times on the first listener
165: long now = System.currentTimeMillis();
166: // Notify in one second
167: Date date = new Date(now + Timer.ONE_SECOND);
168: String message = "timer-message";
169: Integer id = m_timer.addNotification(notifType, message,
170: "user-data", date, Timer.ONE_SECOND, 3L);
171:
172: // Register to happen periodically
173: // Notify in one second
174: date = new Date(now + Timer.ONE_SECOND);
175: String userDataPeriodic = "user-data-periodic";
176: Integer periodicID = m_timer.addNotification(periodicNotifType,
177: "timer-message-periodic", userDataPeriodic, date,
178: Timer.ONE_SECOND);
179:
180: // Sleep some time
181: sleep(Timer.ONE_SECOND);
182:
183: Vector v = m_timer.getAllNotificationIDs();
184: assertEquals(v.size(), 2);
185: assertTrue(v.contains(id));
186: assertTrue(v.contains(periodicID));
187:
188: v = m_timer.getNotificationIDs(periodicNotifType);
189: assertEquals(v.size(), 1);
190: assertTrue(v.contains(periodicID));
191:
192: assertEquals(m_timer.getNotificationMessage(id), message);
193:
194: assertEquals(m_timer.getNotificationUserData(periodicID),
195: userDataPeriodic);
196:
197: // Sleep till the end of the three-time notification
198: sleep(Timer.ONE_SECOND * 6);
199:
200: // Check that was called the right number of times
201: assertEquals(occurrencesCount.get(), 3);
202:
203: // The three-time notification is expired now
204: v = m_timer.getAllNotificationIDs();
205: assertEquals(v.size(), 1);
206: assertTrue(v.contains(periodicID));
207:
208: Long p = m_timer.getPeriod(periodicID);
209: assertEquals(p.longValue(), Timer.ONE_SECOND);
210:
211: assertEquals(m_timer.getNotificationType(periodicID),
212: periodicNotifType);
213:
214: // Removing non existing notification
215: try {
216: m_timer.removeNotifications("dummy");
217: fail("Removed non-existing notification");
218: } catch (InstanceNotFoundException ignored) {
219: }
220:
221: // Should have already been removed, was the three-shot notification
222: try {
223: m_timer.removeNotification(id);
224: fail("Removed non-existing notification");
225: } catch (InstanceNotFoundException ignored) {
226: }
227:
228: // Some more wait
229: sleep(Timer.ONE_SECOND * 3);
230:
231: // Removing existing notification
232: m_timer.removeNotification(periodicID);
233:
234: // Check that none are still present
235: assertTrue(m_timer.isEmpty());
236:
237: // Wait some more to be sure the periodic listener is not notified anymore
238: int periodTimes = periodicOccurrences.get();
239: assertTrue(periodTimes > 0);
240:
241: sleep(Timer.ONE_SECOND * 5);
242:
243: assertEquals(periodicOccurrences.get(), periodTimes);
244: }
245:
246: public void testTimerNotStarted() throws Exception {
247: // Don't start the Timer. Notification should not be emitted
248: // m_timer.start();
249:
250: final MutableBoolean bool = new MutableBoolean(false);
251: NotificationListener listener = new NotificationListener() {
252: public void handleNotification(Notification notification,
253: Object handback) {
254: bool.set(true);
255: }
256: };
257: m_server.addNotificationListener(m_timerName, listener, null,
258: null);
259:
260: long now = System.currentTimeMillis();
261: m_timer.addNotification("timer-notif", "Must not be emitted",
262: null, new Date(now + Timer.ONE_SECOND));
263:
264: // Sleep to wait for the notification to happen
265: sleep(Timer.ONE_SECOND * 2);
266:
267: assertFalse(bool.get());
268: }
269:
270: public void testAddStopRemoveNotification() throws Exception {
271: // Check that add + stop + remove behaves correctly
272:
273: final MutableInteger count = new MutableInteger(0);
274: NotificationListener listener = new NotificationListener() {
275: public void handleNotification(Notification notification,
276: Object handback) {
277: count.set(count.get() + 1);
278: }
279: };
280: m_server.addNotificationListener(m_timerName, listener, null,
281: null);
282:
283: long now = System.currentTimeMillis();
284: Date date = new Date(now + Timer.ONE_SECOND);
285:
286: // Periodic notification
287: Integer id = m_timer.addNotification("notif-type",
288: "notif-message", "notif-data", date, Timer.ONE_SECOND);
289: m_timer.start();
290:
291: // Wait for the notifications to arrive...
292: sleep(Timer.ONE_SECOND * 2);
293:
294: m_timer.stop();
295:
296: int counted = count.get();
297:
298: assertEquals(m_timer.getNbNotifications(), 1);
299:
300: m_timer.removeNotification(id);
301: assertTrue(m_timer.isEmpty());
302:
303: // Wait some more to be sure that there are no more notifications
304: Thread.sleep(Timer.ONE_SECOND * 5);
305:
306: assertEquals(counted, count.get());
307: }
308:
309: public void testSendPastNotifications1() throws Exception {
310: final MutableBoolean bool = new MutableBoolean(false);
311: NotificationListener listener = new NotificationListener() {
312: public void handleNotification(Notification notification,
313: Object handback) {
314: bool.set(true);
315: }
316: };
317: m_server.addNotificationListener(m_timerName, listener, null,
318: null);
319:
320: long now = System.currentTimeMillis();
321:
322: // This one-shot notification is already passed, sendPastNotifications is false
323: // so the notification must not be emitted
324: Date date = new Date(now - Timer.ONE_SECOND);
325: m_timer.setSendPastNotifications(false);
326: m_timer.addNotification("notif-type", "notif-message",
327: "notif-data", date);
328: m_timer.start();
329:
330: // Wait that the notification arrives
331: sleep(Timer.ONE_SECOND);
332:
333: assertFalse(bool.get());
334: assertTrue(m_timer.isEmpty());
335: }
336:
337: public void testNotificationsWithOldDate() throws Exception {
338: final MutableBoolean bool = new MutableBoolean(false);
339: NotificationListener listener = new NotificationListener() {
340: public void handleNotification(Notification notification,
341: Object handback) {
342: bool.set(true);
343: }
344: };
345: m_server.addNotificationListener(m_timerName, listener, null,
346: null);
347:
348: long now = System.currentTimeMillis();
349:
350: m_timer.start();
351: Date date = new Date(now - Timer.ONE_SECOND);
352: m_timer.addNotification("notif-type", "notif-message",
353: "notif-data", date);
354:
355: // Wait that the notification arrives
356: sleep(Timer.ONE_SECOND);
357:
358: assertTrue(bool.get());
359: assertTrue(m_timer.isEmpty());
360: }
361:
362: public void testSendPastNotifications2() throws Exception {
363: final MutableBoolean bool = new MutableBoolean(false);
364: NotificationListener listener = new NotificationListener() {
365: public void handleNotification(Notification notification,
366: Object handback) {
367: bool.set(true);
368: }
369: };
370: m_server.addNotificationListener(m_timerName, listener, null,
371: null);
372:
373: long now = System.currentTimeMillis();
374:
375: // This one-shot notification is already passed, sendPastNotifications is true
376: // so the notification must be emitted
377: Date date = new Date(now - Timer.ONE_SECOND);
378: m_timer.setSendPastNotifications(true);
379: m_timer.addNotification("notif-type", "notif-message",
380: "notif-data", date);
381: m_timer.start();
382:
383: // Wait that the notification arrives
384: sleep(Timer.ONE_SECOND);
385:
386: assertTrue(bool.get());
387: assertTrue(m_timer.isEmpty());
388: }
389:
390: public void testSendPastNotifications3() throws Exception {
391: final MutableInteger count = new MutableInteger(0);
392: NotificationListener listener = new NotificationListener() {
393: public void handleNotification(Notification notification,
394: Object handback) {
395: count.set(count.get() + 1);
396: }
397: };
398: m_server.addNotificationListener(m_timerName, listener, null,
399: null);
400:
401: long now = System.currentTimeMillis();
402:
403: // This periodic notification started in the past, sendPastNotifications is false
404: // so only some notification must be emitted
405: long occurrences = 10;
406: long skip = 4;
407: Date date = new Date(now - Timer.ONE_SECOND * skip);
408: m_timer.setSendPastNotifications(false);
409: m_timer.addNotification("notif-type", "notif-message",
410: "notif-data", date, Timer.ONE_SECOND, occurrences);
411: m_timer.start();
412:
413: // Wait for the notifications to happen
414: sleep(Timer.ONE_SECOND * (occurrences + 1));
415:
416: // Sometimes we loose one notification because we're not that fast, it's ok.
417: long expected = occurrences - skip;
418: if (count.get() != expected && count.get() != expected - 1)
419: fail("Expected notifications not emitted: expecting "
420: + expected + " got " + count.get());
421: assertTrue(m_timer.isEmpty());
422: }
423:
424: public void testSendPastNotifications4() throws Exception {
425: final MutableInteger count = new MutableInteger(0);
426: NotificationListener listener = new NotificationListener() {
427: public void handleNotification(Notification notification,
428: Object handback) {
429: count.set(count.get() + 1);
430: }
431: };
432: m_server.addNotificationListener(m_timerName, listener, null,
433: null);
434:
435: long now = System.currentTimeMillis();
436:
437: // This periodic notification started in the past, sendPastNotifications is true
438: // so all notifications must be emitted
439: long occurrences = 10;
440: long skip = 4;
441: Date date = new Date(now - Timer.ONE_SECOND * skip);
442: m_timer.setSendPastNotifications(true);
443: m_timer.addNotification("notif-type", "notif-message",
444: "notif-data", date, Timer.ONE_SECOND, occurrences);
445: m_timer.start();
446:
447: // Wait for the notifications to happen
448: sleep(Timer.ONE_SECOND * (occurrences + 1));
449:
450: assertEquals(count.get(), occurrences);
451: assertTrue(m_timer.isEmpty());
452: }
453:
454: public void testSendPastNotifications5() throws Exception {
455: final MutableInteger count = new MutableInteger(0);
456: NotificationListener listener = new NotificationListener() {
457: public void handleNotification(Notification notification,
458: Object handback) {
459: count.set(count.get() + 1);
460: }
461: };
462: m_server.addNotificationListener(m_timerName, listener, null,
463: null);
464:
465: long now = System.currentTimeMillis();
466:
467: // This periodic notification is started, sendPastNotifications is false
468: // the Timer is started, then stopped, then restarted
469: long occurrences = 10;
470: long pre = 2;
471: long skip = 4;
472: Date date = new Date(now + Timer.ONE_SECOND);
473: m_timer.setSendPastNotifications(false);
474: m_timer.addNotification("notif-type", "notif-message",
475: "notif-data", date, Timer.ONE_SECOND, occurrences);
476: m_timer.start();
477:
478: // Wait for the notifications to happen
479: sleep(Timer.ONE_SECOND * pre);
480: m_timer.stop();
481:
482: // Sometimes we loose one notification because we're not that fast, it's ok.
483: if (count.get() != pre && count.get() != pre - 1)
484: fail("Expected notifications not emitted: expecting " + pre
485: + " got " + count.get());
486: assertEquals(m_timer.getNbNotifications(), 1);
487:
488: // Wait to skip some notification
489: sleep(Timer.ONE_SECOND * skip);
490:
491: // Restart the Timer
492: m_timer.start();
493:
494: // Wait for the remaining notifications to happen
495: sleep(Timer.ONE_SECOND * (occurrences - pre - skip + 1));
496:
497: m_timer.stop();
498:
499: // Sometimes we loose one notification because we're not that fast, it's ok.
500: long expected = occurrences - skip;
501: if (count.get() != expected && count.get() != expected - 1)
502: fail("Expected notifications not emitted. Expected "
503: + expected + " or " + (expected - 1) + ". got "
504: + count.get());
505: assertTrue(m_timer.isEmpty());
506: }
507:
508: public void testSendPastNotifications6() throws Exception {
509: final MutableInteger count = new MutableInteger(0);
510: NotificationListener listener = new NotificationListener() {
511: public void handleNotification(Notification notification,
512: Object handback) {
513: count.set(count.get() + 1);
514: }
515: };
516: m_server.addNotificationListener(m_timerName, listener, null,
517: null);
518:
519: long now = System.currentTimeMillis();
520:
521: // This periodic notification is started, sendPastNotifications is true
522: // the Timer is started, then stopped, then restarted
523: long occurrences = 10;
524: long pre = 2;
525: long skip = 4;
526: Date date = new Date(now + Timer.ONE_SECOND);
527: m_timer.setSendPastNotifications(true);
528: m_timer
529: .addNotification("notif-type", "notif-message",
530: "notif-data", date, Timer.ONE_SECOND,
531: occurrences, true);
532: m_timer.start();
533:
534: // Wait for the notifications to happen
535: sleep(Timer.ONE_SECOND * pre);
536: m_timer.stop();
537:
538: // Sometimes we loose one notification because we're not that fast, it's ok.
539: if (count.get() != pre && count.get() != pre - 1)
540: fail("Expected notifications not emitted: expecting " + pre
541: + " got " + count.get());
542: assertFalse(m_timer.isEmpty());
543:
544: // Wait to skip some notification
545: sleep(Timer.ONE_SECOND * skip);
546:
547: // Restart the Timer
548: m_timer.start();
549:
550: // Wait for the remaining notifications to happen
551: sleep(Timer.ONE_SECOND * (occurrences - pre - skip + 1));
552:
553: m_timer.stop();
554: assertEquals(count.get(), occurrences);
555: assertTrue(m_timer.isEmpty());
556: }
557:
558: public void testFixedDelay() throws Exception {
559: m_timer.start();
560:
561: final int occurrences = 100;
562: final String fdNotifType = "timer-test-fixed-delay";
563: final String frNotifType = "timer-test-fixed-rate";
564:
565: final MutableInteger frOccurrences = new MutableInteger(0);
566: final MutableLong frElapsedTime = new MutableLong(0);
567: final MutableLong frLastTime = new MutableLong(System
568: .currentTimeMillis());
569:
570: NotificationListener frListener = new NotificationListener() {
571: public void handleNotification(Notification notification,
572: Object handback) {
573: if (frOccurrences.get() < occurrences) {
574: long now = System.currentTimeMillis();
575: frElapsedTime.set(frElapsedTime.get()
576: + (now - frLastTime.get()));
577: frLastTime.set(now);
578: frOccurrences.set(frOccurrences.get() + 1);
579: }
580: }
581: };
582:
583: final MutableInteger fdOccurrences = new MutableInteger(0);
584: final MutableLong fdElapsedTime = new MutableLong(0);
585: final MutableLong fdLastTime = new MutableLong(System
586: .currentTimeMillis());
587:
588: NotificationListener fdListener = new NotificationListener() {
589: public void handleNotification(Notification notification,
590: Object handback) {
591: if (fdOccurrences.get() < occurrences) {
592: long now = System.currentTimeMillis();
593: fdElapsedTime.set(fdElapsedTime.get()
594: + (now - fdLastTime.get()));
595: fdLastTime.set(now);
596: fdOccurrences.set(fdOccurrences.get() + 1);
597: }
598: }
599: };
600:
601: m_server.addNotificationListener(m_timerName, fdListener,
602: new NotificationFilter() {
603: public boolean isNotificationEnabled(
604: Notification notification) {
605: return notification.getType().equals(
606: fdNotifType);
607: }
608: }, null);
609:
610: m_server.addNotificationListener(m_timerName, frListener,
611: new NotificationFilter() {
612: public boolean isNotificationEnabled(
613: Notification notification) {
614: return notification.getType().equals(
615: frNotifType);
616: }
617: }, null);
618:
619: // Testing fixed delay/fixed rate
620: long now = System.currentTimeMillis();
621: // Notify in one second
622: Date date = new Date(now + Timer.ONE_SECOND);
623: // Register to happen 10 times
624: m_timer.addNotification(fdNotifType, "timer-message",
625: "user-data", date, 10, occurrences, false);
626: m_timer.addNotification(frNotifType, "timer-message",
627: "user-data", date, 10, occurrences, true);
628:
629: // Sleep some time
630: while (frOccurrences.get() < occurrences
631: || fdOccurrences.get() < occurrences) {
632: sleep(10);
633: System.gc();
634: }
635:
636: assertEquals(frOccurrences.get(), occurrences);
637: assertEquals(fdOccurrences.get(), occurrences);
638:
639: if (((1.0f * frElapsedTime.get()) / fdElapsedTime.get()) > 0.95)
640: fail("Fixed rate and fixed delay exhibit no execution rate differences");
641: }
642:
643: public void testRemoveNotifications() throws Exception {
644: m_timer.addNotification("mx4j.timer.test", "test notification",
645: null, new Date(System.currentTimeMillis()), 8);
646: m_timer.addNotification("mx4j.timer.ignore", "ignore me", null,
647: new Date(System.currentTimeMillis()), 4);
648: m_timer.addNotification("mx4j.timer.test", "another test",
649: null, new Date(System.currentTimeMillis()), 8);
650: assertEquals(m_timer.getNbNotifications(), 3);
651: m_timer.start();
652: m_timer.removeNotifications("mx4j.timer.ignore");
653: assertEquals(m_timer.getNbNotifications(), 2);
654: }
655:
656: public void testRemoveNonexistentNotifications() throws Exception {
657: m_timer.addNotification("mx4j.timer.test", "test notification",
658: null, new Date(System.currentTimeMillis()), 4);
659: m_timer.start();
660: try {
661: m_timer.removeNotifications("mx4j.timer.bogus");
662: fail("Expecting InstanceNotFoundException");
663: } catch (InstanceNotFoundException x) {
664: }
665: }
666: }
|