/*
* Copyright (C) The MX4J Contributors.
* All rights reserved.
*
* This software is distributed under the terms of the MX4J License version 1.0.
* See the terms of the MX4J License in the documentation provided with this software.
*/
package test.mx4j.remote;
import java.util.HashMap;
import java.util.Map;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.remote.NotificationResult;
import mx4j.remote.DefaultRemoteNotificationServerHandler;
import mx4j.remote.MX4JRemoteConstants;
import mx4j.remote.RemoteNotificationServerHandler;
import test.MX4JTestCase;
/**
* @version $Revision: 1.6 $
*/
public class RemoteNotificationServerHandlerTest extends MX4JTestCase
{
public RemoteNotificationServerHandlerTest(String s)
{
super(s);
}
public void testFirstFetch() throws Exception
{
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(null);
// First call is with sequence number negative; no notification waiting
NotificationResult result = handler.fetchNotifications(-1, 10, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), 0);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, 0);
}
public void testNotificationMissBetweenAddAndFetch() throws Exception
{
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(null);
// Add a notification
NotificationListener listener = handler.getServerNotificationListener();
Notification notification = new Notification("dummy", this, 0);
Integer listenerID = new Integer(1);
listener.handleNotification(notification, listenerID);
// Fetch notifications
NotificationResult result = handler.fetchNotifications(-1, 10, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), 1);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, 0);
// Add another notification
listener.handleNotification(notification, listenerID);
// Fetch again
result = handler.fetchNotifications(result.getNextSequenceNumber(), 10, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), 2);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, 1);
}
public void testBufferWithSmallCapacity() throws Exception
{
int bufferCapacity = 1;
Map environment = new HashMap();
environment.put(MX4JRemoteConstants.NOTIFICATION_BUFFER_CAPACITY, new Integer(bufferCapacity));
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(environment);
// Fill the buffer
NotificationListener listener = handler.getServerNotificationListener();
Notification notification = new Notification("dummy", this, 0);
Integer listenerID = new Integer(1);
for (int i = 0; i < bufferCapacity; ++i) listener.handleNotification(notification, listenerID);
// Fetch first time
NotificationResult result = handler.fetchNotifications(-1, bufferCapacity + 1, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), bufferCapacity);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, 0);
// Add another notification: the buffer is full, the earliest sequence number must change
listener.handleNotification(notification, listenerID);
// Fetch again
result = handler.fetchNotifications(result.getNextSequenceNumber(), bufferCapacity + 1, 100);
assertEquals(result.getEarliestSequenceNumber(), bufferCapacity);
assertEquals(result.getNextSequenceNumber(), bufferCapacity + 1);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, 1);
}
public void testPurgeNotifications() throws Exception
{
int distance = 2;
Map environment = new HashMap();
environment.put(MX4JRemoteConstants.NOTIFICATION_PURGE_DISTANCE, new Integer(distance));
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(environment);
// Fetch
NotificationResult result = handler.fetchNotifications(-1, 10, 100);
// Add notifications
NotificationListener listener = handler.getServerNotificationListener();
Notification notification = new Notification("dummy", this, 0);
Integer listenerID = new Integer(1);
int count = distance + 1;
for (int i = 0; i < count; ++i) listener.handleNotification(notification, listenerID);
// Fetch again
result = handler.fetchNotifications(result.getNextSequenceNumber(), count + 1, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), count);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, count);
// Fetch again: this call triggers purge of old notifications, which changes the earliest sequence number
result = handler.fetchNotifications(result.getNextSequenceNumber(), count + 1, 100);
// Check that the earliest sequence number has changed
long oldEarliest = result.getEarliestSequenceNumber();
result = handler.fetchNotifications(result.getNextSequenceNumber(), count + 1, 100);
if (oldEarliest >= result.getEarliestSequenceNumber()) fail();
}
public void testPurgeNotificationsWithInitialNotificationMiss() throws Exception
{
int distance = 2;
Map environment = new HashMap();
environment.put(MX4JRemoteConstants.NOTIFICATION_PURGE_DISTANCE, new Integer(distance));
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(environment);
// Add notifications (will be missed)
NotificationListener listener = handler.getServerNotificationListener();
Notification notification = new Notification("dummy", this, 0);
Integer listenerID = new Integer(1);
int count = distance + 1;
for (int i = 0; i < count; ++i) listener.handleNotification(notification, listenerID);
// First fetch
NotificationResult result = handler.fetchNotifications(-1, count + 1, 100);
// Add notifications
for (int i = 0; i < count; ++i) listener.handleNotification(notification, listenerID);
// Fetch again: this call triggers purge of old notifications, which changes the earliest sequence number
result = handler.fetchNotifications(result.getNextSequenceNumber(), count + 1, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), count + count);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, count);
// Check that the earliest sequence number has changed
long oldEarliest = result.getEarliestSequenceNumber();
result = handler.fetchNotifications(result.getNextSequenceNumber(), count + 1, 100);
if (oldEarliest >= result.getEarliestSequenceNumber()) fail();
}
public void testBufferOverflowWhileFetching() throws Exception
{
int bufferCapacity = 5;
Map environment = new HashMap();
environment.put(MX4JRemoteConstants.NOTIFICATION_BUFFER_CAPACITY, new Integer(bufferCapacity));
RemoteNotificationServerHandler handler = new DefaultRemoteNotificationServerHandler(environment);
// First Fetch
NotificationResult result = handler.fetchNotifications(-1, bufferCapacity + 1, 100);
// Add some notifications, but don't fill the buffer
long count = bufferCapacity - 2;
NotificationListener listener = handler.getServerNotificationListener();
Notification notification = new Notification("dummy", this, 0);
Integer listenerID = new Integer(1);
for (int i = 0; i < count; ++i) listener.handleNotification(notification, listenerID);
// Fetch again
result = handler.fetchNotifications(result.getNextSequenceNumber(), bufferCapacity + 1, 100);
assertEquals(result.getEarliestSequenceNumber(), 0);
assertEquals(result.getNextSequenceNumber(), count);
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, count);
// Add some notification overflowing the buffer by a number that will exceed the
// next sequence number sent by the client.
// The client will fetch with its own sequence number, but the server
// has discarded that number already (it overflew), be sure the system it does
// not screw up (IndexOutOfBoundsException)
int overflow = 7;
// Note that count == result.getNextSequenceNumber() always yield true at this point (see assertion above),
// so we actually overflew the buffer by a quantity q == count + overflow (see assertion below).
long overflowCount = (bufferCapacity - count) + result.getNextSequenceNumber() + overflow;
for (int i = 0; i < overflowCount; ++i) listener.handleNotification(notification, listenerID);
result = handler.fetchNotifications(result.getNextSequenceNumber(), bufferCapacity + 1, 100);
// After algebraic semplification, overflowCount == bufferCapacity + overflow, so
// the buffer is full, and we fetched all notifications
assertEquals(count + overflow, result.getEarliestSequenceNumber());
assertEquals(count + overflow + bufferCapacity, result.getNextSequenceNumber());
assertNotNull(result.getTargetedNotifications());
assertEquals(result.getTargetedNotifications().length, bufferCapacity);
}
}