package test.compliance.timer;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Date;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.timer.TimerNotification;
public class TimerTest
extends TestCase
implements NotificationListener
{
public static final long PERIOD = 100;
public static final long WAIT = 10000;
public static final long REPEATS = 2;
ObjectName timerName;
MBeanServer server;
ArrayList receivedNotifications = new ArrayList();
public TimerTest(String s)
{
super(s);
}
public void testSingleNotification()
throws Exception
{
try
{
startTimerService();
Integer id = addNotification("test", "hello", "data", calcTime(PERIOD),
0, 1);
expectNotifications(1);
}
finally
{
stopTimerService();
}
}
public void testRepeatedNotification()
throws Exception
{
try
{
startTimerService();
Integer id = addNotification("test", "hello", "data", calcTime(PERIOD),
PERIOD, REPEATS);
expectNotifications(1);
expectNotifications(2);
}
finally
{
stopTimerService();
}
}
public void testInfiniteNotification()
throws Exception
{
try
{
startTimerService();
Integer id = addNotification("test", "hello", "data", calcTime(PERIOD),
PERIOD, 0);
expectNotifications(1);
expectNotifications(2);
if (getNotificationType(id) == null)
fail("Infinite notification not registered");
}
finally
{
stopTimerService();
}
}
public void testTwoNotificationProducers()
throws Exception
{
try
{
startTimerService();
long lTimeOne = 5 * 1000;
long lTimeTwo = 12 * 1000;
long lWait = 2 * lTimeTwo;
long lStart = calcTime( lTimeOne );
Integer lIdOne = addNotification( "test-2", "hello", "data", lStart + lTimeOne,
lTimeOne, 0);
Integer lIdTwo = addNotification( "test-2", "hello", "data", lStart + lTimeTwo,
lTimeTwo, 0);
expectNotifications( 1, lWait );
expectNotifications( 2, lWait );
TimerNotification lNotificationOne = (TimerNotification) receivedNotifications.get( 0 );
TimerNotification lNotificationTwo = (TimerNotification) receivedNotifications.get( 1 );
checkNotificationID( lNotificationOne, lIdOne );
checkNotificationID( lNotificationTwo, lIdOne );
checkTimeDifference( lNotificationOne, lNotificationTwo, lTimeOne );
expectNotifications( 3, lWait );
lNotificationOne = lNotificationTwo;
lNotificationTwo = (TimerNotification) receivedNotifications.get( 2 );
checkNotificationID( lNotificationTwo, lIdTwo );
checkTimeDifference( lNotificationOne, lNotificationTwo, ( lTimeTwo - ( 2 * lTimeOne ) ) );
expectNotifications( 4, lWait );
lNotificationOne = lNotificationTwo;
lNotificationTwo = (TimerNotification) receivedNotifications.get( 3 );
checkNotificationID( lNotificationTwo, lIdOne );
checkTimeDifference( lNotificationOne, lNotificationTwo, ( ( 3 * lTimeOne ) - lTimeTwo ) );
expectNotifications( 5, lWait );
lNotificationOne = lNotificationTwo;
lNotificationTwo = (TimerNotification) receivedNotifications.get( 4 );
checkNotificationID( lNotificationTwo, lIdOne );
checkTimeDifference( lNotificationOne, lNotificationTwo, lTimeOne );
expectNotifications( 6, lWait );
lNotificationOne = lNotificationTwo;
lNotificationTwo = (TimerNotification) receivedNotifications.get( 5 );
checkNotificationID( lNotificationTwo, lIdTwo );
checkTimeDifference( lNotificationOne, lNotificationTwo, ( ( 2 * lTimeTwo ) - ( 4 * lTimeOne ) ) );
}
finally
{
stopTimerService();
}
}
private void startTimerService()
throws Exception
{
server = MBeanServerFactory.createMBeanServer("Timer");
timerName = new ObjectName("Timer:type=TimerService");
server.createMBean("javax.management.timer.Timer", timerName,
new Object[0], new String[0]);
server.invoke(timerName, "start", new Object[0], new String[0]);
receivedNotifications.clear();
server.addNotificationListener(timerName, this, null, null);
}
private void stopTimerService()
{
try
{
server.invoke(timerName, "removeAllNotifications", new Object[0], new String[0]);
server.invoke(timerName, "stop", new Object[0], new String[0]);
server.unregisterMBean(timerName);
MBeanServerFactory.releaseMBeanServer(server);
}
catch (Exception ignored) {}
}
public void handleNotification(Notification notification, Object handback)
{
synchronized (receivedNotifications)
{
receivedNotifications.add(notification);
receivedNotifications.notifyAll();
}
}
public void expectNotifications(int expected)
throws Exception
{
expectNotifications( expected, WAIT );
}
public void expectNotifications(int expected, long wait)
throws Exception
{
synchronized (receivedNotifications)
{
if (receivedNotifications.size() > expected)
fail("too many notifications");
if (receivedNotifications.size() < expected)
{
receivedNotifications.wait( wait );
}
assertEquals(expected, receivedNotifications.size());
}
}
public void checkNotificationID( TimerNotification pNotification, Integer pNotificationID ) {
if( pNotification == null ) {
fail( "Notification is null" );
}
if( !pNotification.getNotificationID().equals( pNotificationID ) ) {
fail( "Wrong Notification ID received: " + pNotification.getNotificationID() +
", expected: " + pNotificationID );
}
}
public void checkTimeDifference(
TimerNotification pNotificationOne,
TimerNotification pNotificationTwo,
long pTimeDiffernce
) {
long lDiff = pNotificationTwo.getTimeStamp() - pNotificationOne.getTimeStamp();
if( lDiff < ( pTimeDiffernce - ( pTimeDiffernce / 10 ) ) ||
lDiff > ( pTimeDiffernce + ( pTimeDiffernce / 10 ) )
) {
fail( "Time between first two notification is too small or too big: " + pTimeDiffernce );
}
}
private Integer addNotification(String type, String message, String data,
long time, long period, long occurs)
throws Exception
{
return (Integer) server.invoke(timerName, "addNotification",
new Object[] { type, message, data, new Date(time), new Long(period),
new Long(occurs) },
new String[] { "java.lang.String", "java.lang.String", "java.lang.Object",
"java.util.Date", "long", "long" } );
}
private String getNotificationType(Integer id)
throws Exception
{
Thread.yield();
return (String) server.invoke(timerName, "getNotificationType",
new Object[] { id },
new String[] { "java.lang.Integer" });
}
private long calcTime(long offset)
{
return System.currentTimeMillis() + offset;
}
}