/** @author Symphorien Wanko */ public class PopupMessageHandlerSLick extends TestSuite implements BundleActivator { /** Logger for this class */ private static Logger logger = Logger.getLogger(PopupMessageHandlerSLick.class); /** our bundle context */ protected static BundleContext bundleContext = null; /** implements BundleActivator.start() */ public void start(BundleContext bc) throws Exception { logger.info("starting popup message test "); bundleContext = bc; setName("PopupMessageHandlerSLick"); Hashtable<String, String> properties = new Hashtable<String, String>(); properties.put("service.pid", getName()); // we maybe are running on machine without WM and systray // (test server machine), skip tests if (ServiceUtils.getService(bc, SystrayService.class) != null) { addTest(TestPopupMessageHandler.suite()); } bundleContext.registerService(getClass().getName(), this, properties); } /** implements BundleActivator.stop() */ public void stop(BundleContext bc) throws Exception {} }
/** * Tests in this class verify whether a precreated contact list is still there and whether it * creating contact groups works as expected. * * @author Emil Ivov */ public class TestOperationSetPersistentPresence extends TestCase { private static final Logger logger = Logger.getLogger(TestOperationSetPersistentPresence.class); private GibberishSlickFixture fixture = new GibberishSlickFixture(); private OperationSetPersistentPresence opSetPersPresence1 = null; private OperationSetPersistentPresence opSetPersPresence2 = null; private static final String testGroupName = "NewGroup"; private static final String testGroupName2 = "Renamed"; public TestOperationSetPersistentPresence(String name) { super(name); } /** * Creates a test suite containing all tests of this class followed by test methods that we want * executed in a specified order. * * @return the Test suite to run */ public static Test suite() { TestSuite suite = new TestSuite(); // the following 2 need to be run in the specified order. // (postTestRemoveGroup() needs the group created from // postTestCreateGroup() ) suite.addTest(new TestOperationSetPersistentPresence("postTestCreateGroup")); // rename suite.addTest(new TestOperationSetPersistentPresence("postTestRenameGroup")); suite.addTest(new TestOperationSetPersistentPresence("postTestRemoveGroup")); // create the contact list suite.addTest(new TestOperationSetPersistentPresence("prepareContactList")); suite.addTestSuite(TestOperationSetPersistentPresence.class); return suite; } @Override protected void setUp() throws Exception { super.setUp(); fixture.setUp(); Map<String, OperationSet> supportedOperationSets1 = fixture.provider1.getSupportedOperationSets(); if (supportedOperationSets1 == null || supportedOperationSets1.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this Gibberish implementation. "); // get the operation set presence here. opSetPersPresence1 = (OperationSetPersistentPresence) supportedOperationSets1.get(OperationSetPersistentPresence.class.getName()); // if still null then the implementation doesn't offer a presence // operation set which is unacceptable for gibberish. if (opSetPersPresence1 == null) throw new NullPointerException( "An implementation of the gibberish service must provide an " + "implementation of at least the one of the Presence " + "Operation Sets"); // lets do it once again for the second provider Map<String, OperationSet> supportedOperationSets2 = fixture.provider2.getSupportedOperationSets(); if (supportedOperationSets2 == null || supportedOperationSets2.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this Gibberish implementation. "); // get the operation set presence here. opSetPersPresence2 = (OperationSetPersistentPresence) supportedOperationSets2.get(OperationSetPersistentPresence.class.getName()); // if still null then the implementation doesn't offer a presence // operation set which is unacceptable for Gibberish. if (opSetPersPresence2 == null) throw new NullPointerException( "An implementation of the Gibberish service must provide an " + "implementation of at least the one of the Presence " + "Operation Sets"); } @Override protected void tearDown() throws Exception { fixture.tearDown(); super.tearDown(); } /** * Retrieves a server stored contact list and checks whether it contains all contacts that have * been added there during the initialization phase by the testerAgent. */ public void testRetrievingServerStoredContactList() { ContactGroup rootGroup = opSetPersPresence1.getServerStoredContactListRoot(); logger.debug("=========== Server Stored Contact List ================="); logger.debug( "rootGroup=" + rootGroup.getGroupName() + " rootGroup.childContacts=" + rootGroup.countContacts() + "rootGroup.childGroups=" + rootGroup.countSubgroups() + "Printing rootGroupContents=\n" + rootGroup.toString()); Hashtable<String, List<String>> expectedContactList = GibberishSlickFixture.preInstalledBuddyList; logger.debug("============== Expected Contact List ==================="); logger.debug(expectedContactList); // Go through the contact list retrieved by the persistence presence set // and remove the name of every contact and group that we find there from // the expected contct list hashtable. Iterator<ContactGroup> groups = rootGroup.subgroups(); while (groups.hasNext()) { ContactGroup group = groups.next(); List<String> expectedContactsInGroup = expectedContactList.get(group.getGroupName()); // When sending the offline message // the sever creates a group NotInContactList, // because the buddy we are sending message to is not in // the contactlist. So this group must be ignored if (!group.getGroupName().equals("NotInContactList")) { assertNotNull( "Group " + group.getGroupName() + " was returned by " + "the server but was not in the expected contact list.", expectedContactsInGroup); Iterator<Contact> contactsIter = group.contacts(); while (contactsIter.hasNext()) { String contactID = contactsIter.next().getAddress(); expectedContactsInGroup.remove(contactID); } // If we've removed all the sub contacts, remove the group too. if (expectedContactsInGroup.size() == 0) expectedContactList.remove(group.getGroupName()); } } // whatever we now have in the expected contact list snapshot are groups, // that have been added by the testerAgent but that were not retrieved // by the persistent presence operation set. assertTrue( "The following contacts were on the server sidec contact " + "list, but were not returned by the pers. pres. op. set" + expectedContactList.toString(), expectedContactList.isEmpty()); } /** * Creates a group in the server stored contact list, makes sure that the corresponding event has * been generated and verifies that the group is in the list. * * @throws java.lang.Exception */ public void postTestCreateGroup() throws Exception { // first clear the list fixture.clearProvidersLists(); Object o = new Object(); synchronized (o) { o.wait(3000); } logger.trace("testing creation of server stored groups"); // first add a listener GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); opSetPersPresence1.addServerStoredGroupChangeListener(groupChangeCollector); // create the group opSetPersPresence1.createServerStoredContactGroup( opSetPersPresence1.getServerStoredContactListRoot(), testGroupName); groupChangeCollector.waitForEvent(10000); opSetPersPresence1.removeServerStoredGroupChangeListener(groupChangeCollector); // check whether we got group created event assertEquals("Collected Group Change events: ", 1, groupChangeCollector.collectedEvents.size()); assertEquals( "Group name.", testGroupName, ((ServerStoredGroupEvent) groupChangeCollector.collectedEvents.get(0)) .getSourceGroup() .getGroupName()); // check whether the group is retrievable ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName); assertNotNull("A newly created group was not in the contact list.", group); assertEquals("New group name", testGroupName, group.getGroupName()); // when opearting with groups . the group must have entries // so changes to take effect. Otherwise group will be lost after loggingout try { opSetPersPresence1.subscribe(group, fixture.userID2); synchronized (o) { o.wait(1500); } } catch (Exception ex) { fail("error adding entry to group : " + group.getGroupName() + " " + ex.getMessage()); } } /** * Removes the group created in the server stored contact list by the create group test, makes * sure that the corresponding event has been generated and verifies that the group is not in the * list any more. */ public void postTestRemoveGroup() { logger.trace("testing removal of server stored groups"); // first add a listener GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); opSetPersPresence1.addServerStoredGroupChangeListener(groupChangeCollector); try { // remove the group opSetPersPresence1.removeServerStoredContactGroup( opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName2)); } catch (OperationFailedException ex) { logger.error("error removing group", ex); } groupChangeCollector.waitForEvent(10000); opSetPersPresence1.removeServerStoredGroupChangeListener(groupChangeCollector); // check whether we got group created event assertEquals("Collected Group Change event", 1, groupChangeCollector.collectedEvents.size()); assertEquals( "Group name.", testGroupName2, ((ServerStoredGroupEvent) groupChangeCollector.collectedEvents.get(0)) .getSourceGroup() .getGroupName()); // check whether the group is still on the contact list ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName2); assertNull("A freshly removed group was still on the contact list.", group); } /** * Renames our test group and checks whether corresponding events are triggered. Verifies whether * the group has really changed its name and whether it is findable by its new name. Also makes * sure that it does not exist under its previous name any more. */ public void postTestRenameGroup() { logger.trace("Testing renaming groups."); ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName); // first add a listener GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); opSetPersPresence1.addServerStoredGroupChangeListener(groupChangeCollector); // change the name and wait for a confirmation event opSetPersPresence1.renameServerStoredContactGroup(group, testGroupName2); groupChangeCollector.waitForEvent(10000); opSetPersPresence1.removeServerStoredGroupChangeListener(groupChangeCollector); // examine the event assertEquals("Collected Group Change event", 1, groupChangeCollector.collectedEvents.size()); assertEquals( "Group name.", testGroupName2, ((ServerStoredGroupEvent) groupChangeCollector.collectedEvents.get(0)) .getSourceGroup() .getGroupName()); // check whether the group is still on the contact list ContactGroup oldGroup = opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName); assertNull("A group was still findable by its old name after renaming.", oldGroup); // make sure that we could find the group by its new name. ContactGroup newGroup = opSetPersPresence1.getServerStoredContactListRoot().getGroup(testGroupName2); assertNotNull("Could not find a renamed group by its new name.", newGroup); } /** * Create the contact list. Later will be test to be sure that creating is ok * * @throws Exception */ public void prepareContactList() throws Exception { fixture.clearProvidersLists(); Object o = new Object(); synchronized (o) { o.wait(3000); } String contactList = System.getProperty(GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME, null); logger.debug( "The " + GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME + " property is set to=" + contactList); if (contactList == null || contactList.trim().length() < 6) // at least 4 for a UIN, 1 for the // dot and 1 for the grp name throw new IllegalArgumentException( "The " + GibberishProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME + " property did not contain a contact list."); StringTokenizer tokenizer = new StringTokenizer(contactList, " \n\t"); logger.debug("tokens contained by the CL tokenized=" + tokenizer.countTokens()); Hashtable<String, List<String>> contactListToCreate = new Hashtable<String, List<String>>(); // go over all group.uin tokens while (tokenizer.hasMoreTokens()) { String groupUinToken = tokenizer.nextToken(); int dotIndex = groupUinToken.indexOf("."); if (dotIndex == -1) { throw new IllegalArgumentException(groupUinToken + " is not a valid Group.UIN token"); } String groupName = groupUinToken.substring(0, dotIndex); String uin = groupUinToken.substring(dotIndex + 1); if (groupName.trim().length() < 1 || uin.trim().length() < 4) { throw new IllegalArgumentException( groupName + " or " + uin + " are not a valid group name or Gibberish user id."); } // check if we've already seen this group and if not - add it List<String> uinInThisGroup = contactListToCreate.get(groupName); if (uinInThisGroup == null) { uinInThisGroup = new ArrayList<String>(); contactListToCreate.put(groupName, uinInThisGroup); } uinInThisGroup.add(uin); } // now init the list Enumeration<String> newGroupsEnum = contactListToCreate.keys(); // go over all groups in the contactsToAdd table while (newGroupsEnum.hasMoreElements()) { String groupName = newGroupsEnum.nextElement(); logger.debug("Will add group " + groupName); opSetPersPresence1.createServerStoredContactGroup( opSetPersPresence1.getServerStoredContactListRoot(), groupName); ContactGroup newlyCreatedGroup = opSetPersPresence1.getServerStoredContactListRoot().getGroup(groupName); Iterator<String> contactsToAddToThisGroup = contactListToCreate.get(groupName).iterator(); while (contactsToAddToThisGroup.hasNext()) { String id = contactsToAddToThisGroup.next(); logger.debug("Will add buddy " + id); opSetPersPresence1.subscribe(newlyCreatedGroup, id); } } // store the created contact list for later reference GibberishSlickFixture.preInstalledBuddyList = contactListToCreate; } /** * The class would listen for and store received events delivered to * <tt>ServerStoredGroupListener</tt>s. */ private class GroupChangeCollector implements ServerStoredGroupListener { public ArrayList<EventObject> collectedEvents = new ArrayList<EventObject>(); /** * Blocks until at least one event is received or until waitFor miliseconds pass (whicever * happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedEvents.size() > 0) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } /** * Called whnever an indication is received that a new server stored group is created. * * @param evt a ServerStoredGroupChangeEvent containing a reference to the newly created group. */ public void groupCreated(ServerStoredGroupEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Called when an indication is received that the name of a server stored contact group has * changed. * * @param evt a ServerStoredGroupChangeEvent containing the details of the name change. */ public void groupNameChanged(ServerStoredGroupEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Called whnever an indication is received that an existing server stored group has been * removed. * * @param evt a ServerStoredGroupChangeEvent containing a reference to the newly created group. */ public void groupRemoved(ServerStoredGroupEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Called whnever an indication is received that an existing server stored group has been * resolved. * * @param evt a ServerStoredGroupChangeEvent containing a reference to the resolved group. */ public void groupResolved(ServerStoredGroupEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } } /** The class would listen for and store received subscription modification events. */ private class SubscriptionEventCollector implements SubscriptionListener { public ArrayList<EventObject> collectedEvents = new ArrayList<EventObject>(); /** * Blocks until at least one event is received or until waitFor milliseconds pass (whichever * happens first). * * @param waitFor the number of milliseconds that we should be waiting for an event before * simply bailing out. */ public void waitForEvent(long waitFor) { logger.trace("Waiting for a persistent subscription event"); synchronized (this) { if (collectedEvents.size() > 0) { logger.trace("SubEvt already received. " + collectedEvents); return; } try { wait(waitFor); if (collectedEvents.size() > 0) logger.trace("Received a SubEvt in provider status."); else logger.trace("No SubEvt received for " + waitFor + "ms."); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionCreated(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionRemoved(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionFailed(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionResolved(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionMoved(SubscriptionMovedEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subsctiption and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void contactModified(ContactPropertyChangeEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } } }
/** * Performs testing on protocol provider methods. * * @todo add more detailed docs once the tests are written. * @author Emil Ivov * @author Valentin Martinet */ public class TestProtocolProviderServiceJabberImpl extends TestCase { private static final Logger logger = Logger.getLogger(TestProtocolProviderServiceJabberImpl.class); private JabberSlickFixture fixture = new JabberSlickFixture(); /** An event adapter that would collec registation state change events */ public RegistrationEventCollector regEvtCollector1 = new RegistrationEventCollector(); /** An event adapter that would collec registation state change events */ public RegistrationEventCollector regEvtCollector2 = new RegistrationEventCollector(); /** An event adapter that would collec registation state change events */ public RegistrationEventCollector regEvtCollector3 = new RegistrationEventCollector(); /** * Creates a test encapsulator for the method with the specified name. * * @param name the name of the method this test should run. */ public TestProtocolProviderServiceJabberImpl(String name) { super(name); } /** * Initializes the fixture. * * @throws Exception if super.setUp() throws one. */ @Override protected void setUp() throws Exception { super.setUp(); fixture.setUp(); } /** * Tears the fixture down. * * @throws Exception if fixture.tearDown() fails. */ @Override protected void tearDown() throws Exception { fixture.tearDown(); super.tearDown(); } /** * Makes sure that the instance of the Jabber protocol provider that we're going to use for * testing is properly initialized and registered with a Jabber registrar. This MUST be called * before any other online testing of the Jabber provider so that we won't have to reregister for * every single test. * * <p>The method also verifies that a registration event is fired upon succesful registration and * collected by our event collector. * * @throws OperationFailedException if provider.register() fails. */ public void testRegister() throws OperationFailedException { // add an event collector that will collect all events during the // registration and allow us to later inspect them and make sure // they were properly dispatched. fixture.provider1.addRegistrationStateChangeListener(regEvtCollector1); fixture.provider2.addRegistrationStateChangeListener(regEvtCollector2); fixture.provider3.addRegistrationStateChangeListener(regEvtCollector3); // register our three providers fixture.provider1.register( new SecurityAuthorityImpl( System.getProperty( JabberProtocolProviderServiceLick.ACCOUNT_1_PREFIX + ProtocolProviderFactory.PASSWORD) .toCharArray())); fixture.provider2.register( new SecurityAuthorityImpl( System.getProperty( JabberProtocolProviderServiceLick.ACCOUNT_2_PREFIX + ProtocolProviderFactory.PASSWORD) .toCharArray())); fixture.provider3.register( new SecurityAuthorityImpl( System.getProperty( JabberProtocolProviderServiceLick.ACCOUNT_3_PREFIX + ProtocolProviderFactory.PASSWORD) .toCharArray())); // give it enough time to register. We won't really have to wait all this // time since the registration event collector would notify us the moment // we get signed on. logger.debug("Waiting for registration to complete ..."); regEvtCollector1.waitForEvent(15000); regEvtCollector2.waitForEvent(40000); regEvtCollector3.waitForEvent(60000); // make sure that the registration process trigerred the corresponding // events. assertTrue( "No events were dispatched during the registration process.", regEvtCollector1.collectedNewStates.size() > 0); assertTrue( "No registration event notifying of registration was dispatched. " + "All events were: " + regEvtCollector1.collectedNewStates, regEvtCollector1.collectedNewStates.contains(RegistrationState.REGISTERED)); // now the same for provider 2 assertTrue( "No events were dispatched during the registration process " + "of provider2.", regEvtCollector2.collectedNewStates.size() > 0); assertTrue( "No registration event notifying of registration was dispatched. " + "All events were: " + regEvtCollector2.collectedNewStates, regEvtCollector2.collectedNewStates.contains(RegistrationState.REGISTERED)); // now the same for provider 3 assertTrue( "No events were dispatched during the registration process " + "of provider3.", regEvtCollector3.collectedNewStates.size() > 0); assertTrue( "No registration event notifying of registration was dispatched. " + "All events were: " + regEvtCollector3.collectedNewStates, regEvtCollector3.collectedNewStates.contains(RegistrationState.REGISTERED)); fixture.provider1.removeRegistrationStateChangeListener(regEvtCollector1); fixture.provider2.removeRegistrationStateChangeListener(regEvtCollector2); fixture.provider3.removeRegistrationStateChangeListener(regEvtCollector3); } /** * Verifies that all operation sets have the type they are declarded to have. * * @throws java.lang.Exception if a class indicated in one of the keys could not be forName()ed. */ public void testOperationSetTypes() throws Exception { Map<String, OperationSet> supportedOperationSets = fixture.provider1.getSupportedOperationSets(); // make sure that keys (which are supposed to be class names) correspond // what the class of the values recorded against them. for (Map.Entry<String, OperationSet> entry : supportedOperationSets.entrySet()) { String setName = entry.getKey(); Object opSet = entry.getValue(); assertTrue( opSet + " was not an instance of " + setName + " as declared", Class.forName(setName).isInstance(opSet)); } } /** * A class that would plugin as a registration listener to a protocol provider and simply record * all events that it sees and notifyAll() if it sees an event that notifies us of a completed * registration. */ public class RegistrationEventCollector implements RegistrationStateChangeListener { public List<RegistrationState> collectedNewStates = new LinkedList<RegistrationState>(); /** * The method would simply register all received events so that they could be available for * later inspection by the unit tests. In the case where a registration event notifying us of a * completed registration is seen, the method would call notifyAll(). * * @param evt ProviderStatusChangeEvent the event describing the status change. */ public void registrationStateChanged(RegistrationStateChangeEvent evt) { logger.debug("Received a RegistrationStateChangeEvent: " + evt); collectedNewStates.add(evt.getNewState()); if (evt.getNewState().equals(RegistrationState.REGISTERED)) { logger.debug("We're registered and will notify those who wait"); synchronized (this) { notifyAll(); } } } /** * Blocks until an event notifying us of the awaited state change is received or until waitFor * miliseconds pass (whichever happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { logger.trace("Waiting for a RegistrationStateChangeEvent "); synchronized (this) { if (collectedNewStates.contains(RegistrationState.REGISTERED)) { logger.trace("Event already received. " + collectedNewStates); return; } try { wait(waitFor); if (collectedNewStates.size() > 0) logger.trace("Received a RegistrationStateChangeEvent."); else logger.trace("No RegistrationStateChangeEvent received for " + waitFor + "ms."); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a " + "RegistrationStateChangeEvent", ex); } } } } }
/** * Tests ICQ implementations of a Presence Operation Set. Tests in this class verify functionality * such as: Changing local (our own) status and corresponding event dispatching; Querying status of * contacts, Subscribing for presence notifications upong status changes of specific contacts. * * <p>Using a custom suite() method, we make sure that apart from standard test methods (those with * a <tt>test</tt> prefix) we also execute those that we want run in a specific order like for * example - postTestSubscribe() and postTestUnsubscribe(). * * <p> * * @author Emil Ivov * @author Damian Minkov */ public class TestOperationSetPresence extends TestCase { private static final Logger logger = Logger.getLogger(TestOperationSetPresence.class); private IcqSlickFixture fixture = new IcqSlickFixture(); private OperationSetPresence operationSetPresence = null; private String statusMessageRoot = new String("Our status is now: "); // be sure its only one private static AuthEventCollector authEventCollector = new AuthEventCollector(); public TestOperationSetPresence(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); fixture.setUp(); Map<String, OperationSet> supportedOperationSets = fixture.provider.getSupportedOperationSets(); if (supportedOperationSets == null || supportedOperationSets.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this ICQ implementation. "); // get the operation set presence here. operationSetPresence = (OperationSetPresence) supportedOperationSets.get(OperationSetPresence.class.getName()); // if the op set is null then the implementation doesn't offer a presence // operation set which is unacceptable for icq. if (operationSetPresence == null) { throw new NullPointerException( "An implementation of the ICQ service must provide an " + "implementation of at least the one of the Presence " + "Operation Sets"); } } protected void tearDown() throws Exception { super.tearDown(); fixture.tearDown(); } /** * Creates a test suite containing all tests of this class followed by test methods that we want * executed in a specified order. * * @return Test */ public static Test suite() { // return an (almost) empty suite if we're running in offline mode. if (IcqSlickFixture.onlineTestingDisabled) { TestSuite suite = new TestSuite(); // the only test around here that we could run without net // connectivity suite.addTest(new TestOperationSetPresence("testSupportedStatusSetForCompleteness")); return suite; } TestSuite suite = new TestSuite(TestOperationSetPresence.class); // the following 2 need to be run in the specified order. // (postTestUnsubscribe() needs the subscription created from // postTestSubscribe() ) suite.addTest(new TestOperationSetPresence("postTestSubscribe")); suite.addTest(new TestOperationSetPresence("postTestUnsubscribe")); // execute this test after postTestSubscribe // to be sure that AuthorizationHandler is installed suite.addTest(new TestOperationSetPresence("postTestReceiveAuthorizatinonRequest")); return suite; } /** Verifies that all necessary ICQ test states are supported by the implementation. */ public void testSupportedStatusSetForCompleteness() { // first create a local list containing the presence status instances // supported by the underlying implementation. Iterator<PresenceStatus> supportedStatusSetIter = operationSetPresence.getSupportedStatusSet(); List<PresenceStatus> supportedStatusSet = new LinkedList<PresenceStatus>(); while (supportedStatusSetIter.hasNext()) { supportedStatusSet.add(supportedStatusSetIter.next()); } // create a copy of the MUST status set and remove any matching status // that is also present in the supported set. List<?> requiredStatusSetCopy = (List<?>) IcqStatusEnum.icqStatusSet.clone(); requiredStatusSetCopy.removeAll(supportedStatusSet); // if we have anything left then the implementation is wrong. int unsupported = requiredStatusSetCopy.size(); assertTrue( "There are " + unsupported + " statuses as follows:" + requiredStatusSetCopy, unsupported == 0); } /** * Verify that changing state to AWAY works as supposed to and that it generates the corresponding * event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToAway() throws Exception { subtestStateTransition(IcqStatusEnum.AWAY); } /** * Verify that changing state to NOT_AVAILABLE works as supposed to and that it generates the * corresponding event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToNotAvailable() throws Exception { subtestStateTransition(IcqStatusEnum.NOT_AVAILABLE); } /** * Verify that changing state to DND works as supposed to and that it generates the corresponding * event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToDnd() throws Exception { subtestStateTransition(IcqStatusEnum.DO_NOT_DISTURB); } /** * Verify that changing state to INVISIBLE works as supposed to and that it generates the * corresponding event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToInvisible() throws Exception { subtestStateTransition(IcqStatusEnum.INVISIBLE); } /** * Verify that changing state to OCCUPIED works as supposed to and that it generates the * corresponding event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToOccupied() throws Exception { subtestStateTransition(IcqStatusEnum.OCCUPIED); } /** * Verify that changing state to FREE_FOR_CHAT works as supposed to and that it generates the * corresponding event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToFreeForChat() throws Exception { subtestStateTransition(IcqStatusEnum.FREE_FOR_CHAT); } /** * Verify that changing state to ONLINE works as supposed to and that it generates the * corresponding event. * * @throws Exception in case a failure occurs while the operation set is switching to the new * state. */ public void testChangingStateToOnline() throws Exception { // // java.util.logging.Logger.getLogger("net.kano").setLevel(java.util.logging.Level.FINEST); subtestStateTransition(IcqStatusEnum.ONLINE); // // java.util.logging.Logger.getLogger("net.kano").setLevel(java.util.logging.Level.WARNING); } /** * Used by methods testing state transiotions * * @param newStatus the IcqStatusEnum field corresponding to the status that we'd like the * opeation set to enter. * @throws Exception in case changing the state causes an exception */ public void subtestStateTransition(IcqStatusEnum newStatus) throws Exception { logger.trace(" --=== beginning state transition test ===--"); PresenceStatus oldStatus = operationSetPresence.getPresenceStatus(); String oldStatusMessage = operationSetPresence.getCurrentStatusMessage(); String newStatusMessage = statusMessageRoot + newStatus; logger.debug( "old status is=" + oldStatus.getStatusName() + " new status=" + newStatus.getStatusName()); // First register a listener to make sure that all corresponding // events have been generated. PresenceStatusEventCollector statusEventCollector = new PresenceStatusEventCollector(); operationSetPresence.addProviderPresenceStatusListener(statusEventCollector); // change the status operationSetPresence.publishPresenceStatus(newStatus, newStatusMessage); // test event notification. statusEventCollector.waitForPresEvent(10000); statusEventCollector.waitForStatMsgEvent(10000); // sometimes we don't get response from the server for the // changed status. we will query it once again. // and wait for the response if (statusEventCollector.collectedPresEvents.size() == 0) { logger.trace("Will query again status as we haven't received one"); operationSetPresence.queryContactStatus(fixture.icqAccountID.getUserID()); statusEventCollector.waitForPresEvent(10000); } operationSetPresence.removeProviderPresenceStatusListener(statusEventCollector); assertEquals( "Events dispatched during an event transition.", 1, statusEventCollector.collectedPresEvents.size()); assertEquals( "A status changed event contained wrong old status.", oldStatus, ((ProviderPresenceStatusChangeEvent) statusEventCollector.collectedPresEvents.get(0)) .getOldStatus()); assertEquals( "A status changed event contained wrong new status.", newStatus, ((ProviderPresenceStatusChangeEvent) statusEventCollector.collectedPresEvents.get(0)) .getNewStatus()); // verify that the operation set itself is aware of the status change assertEquals( "opSet.getPresenceStatus() did not return properly.", newStatus, operationSetPresence.getPresenceStatus()); IcqStatusEnum actualStatus = fixture.testerAgent.getBuddyStatus(fixture.icqAccountID.getUserID()); assertEquals( "The underlying implementation did not switch to the " + "requested presence status.", newStatus, actualStatus); // check whether the server returned the status message that we've set. assertEquals( "No status message events.", 1, statusEventCollector.collectedStatMsgEvents.size()); assertEquals( "A status message event contained wrong old value.", oldStatusMessage, ((PropertyChangeEvent) statusEventCollector.collectedStatMsgEvents.get(0)).getOldValue()); assertEquals( "A status message event contained wrong new value.", newStatusMessage, ((PropertyChangeEvent) statusEventCollector.collectedStatMsgEvents.get(0)).getNewValue()); // verify that the operation set itself is aware of the new status msg. assertEquals( "opSet.getCurrentStatusMessage() did not return properly.", newStatusMessage, operationSetPresence.getCurrentStatusMessage()); logger.trace(" --=== finished test ===--"); // make it sleep a bit cause the aol server gets mad otherwise. pauseBetweenStateChanges(); } /** * The AIM server doesn't like it if we change states too often and we use this method to slow * things down. */ private void pauseBetweenStateChanges() { try { Thread.sleep(5000); } catch (InterruptedException ex) { logger.debug("Pausing between state changes was interrupted", ex); } } /** * Verifies that querying status works fine. The ICQ tester agent would change status and the * operation set would have to return the right status after every change. * * @throws java.lang.Exception if one of the transitions fails */ public void testQueryContactStatus() throws Exception { // --- AWAY --- logger.debug("Will Query an AWAY contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_AWAY, IcqStatusEnum.AWAY); pauseBetweenStateChanges(); // --- NA --- logger.debug("Will Query an NA contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_NA, IcqStatusEnum.NOT_AVAILABLE); pauseBetweenStateChanges(); // --- DND --- logger.debug("Will Query a DND contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_DND, IcqStatusEnum.DO_NOT_DISTURB); pauseBetweenStateChanges(); // --- FFC --- logger.debug("Will Query a Free For Chat contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_FFC, IcqStatusEnum.FREE_FOR_CHAT); pauseBetweenStateChanges(); // --- INVISIBLE --- logger.debug("Will Query an Invisible contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_INVISIBLE, IcqStatusEnum.INVISIBLE); pauseBetweenStateChanges(); // --- Occupied --- logger.debug("Will Query an Occupied contact."); subtestQueryContactStatus(FullUserInfo.ICQSTATUS_OCCUPIED, IcqStatusEnum.OCCUPIED); pauseBetweenStateChanges(); // --- Online --- logger.debug("Will Query an Online contact."); subtestQueryContactStatus(IcqTesterAgent.ICQ_ONLINE_MASK, IcqStatusEnum.ONLINE); pauseBetweenStateChanges(); } /** * Used by functions testing the queryContactStatus method of the presence operation set. * * @param taStatusLong the icq status as specified by FullUserInfo, that the tester agent should * switch to. * @param expectedReturn the PresenceStatus that the presence operation set should see the tester * agent in once it has switched to taStatusLong. * @throws java.lang.Exception if querying the status causes some exception. */ public void subtestQueryContactStatus(long taStatusLong, PresenceStatus expectedReturn) throws Exception { if (!fixture.testerAgent.enterStatus(taStatusLong)) { throw new RuntimeException( "Tester UserAgent Failed to switch to the " + expectedReturn.getStatusName() + " state."); } PresenceStatus actualReturn = operationSetPresence.queryContactStatus(fixture.testerAgent.getIcqUIN()); assertEquals( "Querying a " + expectedReturn.getStatusName() + " state did not return as expected", expectedReturn, actualReturn); } /** * The method would add a subscription for a contact, wait for a subscription event confirming the * subscription, then change the status of the newly added contact (which is actually the * IcqTesterAgent) and make sure that the corresponding notification events have been generated. * * @throws java.lang.Exception if an exception occurs during testing. */ public void postTestSubscribe() throws Exception { logger.debug("Testing Subscription and Subscription Event Dispatch."); // First create a subscription and verify that it really gets created. SubscriptionEventCollector subEvtCollector = new SubscriptionEventCollector(); logger.trace("set Auth Handler"); operationSetPresence.setAuthorizationHandler(authEventCollector); synchronized (authEventCollector) { authEventCollector.authorizationRequestReason = "Please deny my request!"; fixture.testerAgent.getAuthCmdFactory().responseReasonStr = "First authorization I will Deny!!!"; fixture.testerAgent.getAuthCmdFactory().ACCEPT = false; operationSetPresence.subscribe(fixture.testerAgent.getIcqUIN()); // this one collects event that the buddy has been added // to the list as awaiting SubscriptionEventCollector moveEvtCollector = new SubscriptionEventCollector(); operationSetPresence.addSubscriptionListener(moveEvtCollector); logger.debug("Waiting for authorization error and authorization response..."); authEventCollector.waitForAuthResponse(15000); assertTrue( "Error adding buddy not recieved or the buddy(" + fixture.testerAgent.getIcqUIN() + ") doesn't require authorization", authEventCollector.isAuthorizationRequestSent); assertNotNull( "Agent haven't received any reason for authorization", fixture.testerAgent.getAuthCmdFactory().requestReasonStr); assertEquals( "Error sent request reason is not as the received one", authEventCollector.authorizationRequestReason, fixture.testerAgent.getAuthCmdFactory().requestReasonStr); logger.debug( "authEventCollector.isAuthorizationResponseReceived " + authEventCollector.isAuthorizationResponseReceived); assertTrue("Response not received!", authEventCollector.isAuthorizationResponseReceived); boolean isAcceptedAuthReuest = authEventCollector.response.getResponseCode().equals(AuthorizationResponse.ACCEPT); assertEquals( "Response is not as the sent one", fixture.testerAgent.getAuthCmdFactory().ACCEPT, isAcceptedAuthReuest); assertNotNull( "We didn't receive any reason! ", authEventCollector.authorizationResponseString); assertEquals( "The sent response reason is not as the received one", fixture.testerAgent.getAuthCmdFactory().responseReasonStr, authEventCollector.authorizationResponseString); // here we must wait for server to move the awaiting buddy // to the first specified group synchronized (moveEvtCollector) { moveEvtCollector.waitForEvent(20000); // don't want any more events operationSetPresence.removeSubscriptionListener(moveEvtCollector); } Contact c = operationSetPresence.findContactByID(fixture.testerAgent.getIcqUIN()); logger.debug("I will remove " + c + " from group : " + c.getParentContactGroup()); UnsubscribeWait unsubscribeEvtCollector = new UnsubscribeWait(); operationSetPresence.addSubscriptionListener(unsubscribeEvtCollector); synchronized (unsubscribeEvtCollector) { operationSetPresence.unsubscribe(c); logger.debug("Waiting to be removed..."); unsubscribeEvtCollector.waitForUnsubscribre(20000); logger.debug("Received unsubscribed ok or we lost patients!"); // don't want any more events operationSetPresence.removeSubscriptionListener(unsubscribeEvtCollector); } // so we haven't asserted so everithing is fine lets try to be authorized authEventCollector.authorizationRequestReason = "Please accept my request!"; fixture.testerAgent.getAuthCmdFactory().responseReasonStr = "Second authorization I will Accept!!!"; fixture.testerAgent.getAuthCmdFactory().ACCEPT = true; // clear some things authEventCollector.isAuthorizationRequestSent = false; authEventCollector.isAuthorizationResponseReceived = false; authEventCollector.authorizationResponseString = null; logger.debug( "I will add buddy does it exists ? " + (operationSetPresence.findContactByID(fixture.testerAgent.getIcqUIN()) != null)); // add the listener beacuse now our authorization will be accepted // and so the buddy will be finally added to the list operationSetPresence.addSubscriptionListener(subEvtCollector); // subscribe again so we can trigger again the authorization procedure operationSetPresence.subscribe(fixture.testerAgent.getIcqUIN()); logger.debug( "Waiting ... Subscribe must fail and the authorization process " + "to be trigered again so waiting for auth response ..."); authEventCollector.waitForAuthResponse(15000); assertTrue( "Error adding buddy not recieved or the buddy(" + fixture.testerAgent.getIcqUIN() + ") doesn't require authorization", authEventCollector.isAuthorizationRequestSent); assertNotNull( "Agent haven't received any reason for authorization", fixture.testerAgent.getAuthCmdFactory().requestReasonStr); // not working for now assertEquals( "Error sent request reason", authEventCollector.authorizationRequestReason, fixture.testerAgent.getAuthCmdFactory().requestReasonStr); // wait for authorization process to be finnished // the modification of buddy (server will inform us // that he removed - awaiting authorization flag) Object obj = new Object(); synchronized (obj) { logger.debug("wait for authorization process to be finnished"); obj.wait(10000); logger.debug("Stop waiting!"); } subEvtCollector.waitForEvent(10000); // don't want any more events operationSetPresence.removeSubscriptionListener(subEvtCollector); } // after adding awaitingAuthorization group here are catched 3 events // 1 - creating unresolved contact // 2 - move of the contact to awaitingAuthorization group // 3 - move of the contact from awaitingAuthorization group to original group assertTrue( "Subscription event dispatching failed.", subEvtCollector.collectedEvents.size() > 0); EventObject evt = null; Iterator<EventObject> events = subEvtCollector.collectedEvents.iterator(); while (events.hasNext()) { EventObject elem = events.next(); if (elem instanceof SubscriptionEvent) { if (((SubscriptionEvent) elem).getEventID() == SubscriptionEvent.SUBSCRIPTION_CREATED) evt = (SubscriptionEvent) elem; } } Object source = null; Contact srcContact = null; ProtocolProviderService srcProvider = null; // the event can be SubscriptionEvent and the new added one // SubscriptionMovedEvent if (evt instanceof SubscriptionEvent) { SubscriptionEvent subEvt = (SubscriptionEvent) evt; source = subEvt.getSource(); srcContact = subEvt.getSourceContact(); srcProvider = subEvt.getSourceProvider(); } assertEquals( "SubscriptionEvent Source:", fixture.testerAgent.getIcqUIN(), ((Contact) source).getAddress()); assertEquals( "SubscriptionEvent Source Contact:", fixture.testerAgent.getIcqUIN(), srcContact.getAddress()); assertSame("SubscriptionEvent Source Provider:", fixture.provider, srcProvider); subEvtCollector.collectedEvents.clear(); // make the user agent tester change its states and make sure we are // notified logger.debug("Testing presence notifications."); IcqStatusEnum testerAgentOldStatus = fixture.testerAgent.getPresneceStatus(); IcqStatusEnum testerAgentNewStatus = IcqStatusEnum.FREE_FOR_CHAT; long testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_FFC; // in case we are by any chance already in a FREE_FOR_CHAT status, we'll // be changing to something else if (testerAgentOldStatus.equals(testerAgentNewStatus)) { testerAgentNewStatus = IcqStatusEnum.DO_NOT_DISTURB; testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_DND; } // now do the actual status notification testing ContactPresenceEventCollector contactPresEvtCollector = new ContactPresenceEventCollector(fixture.testerAgent.getIcqUIN(), testerAgentNewStatus); operationSetPresence.addContactPresenceStatusListener(contactPresEvtCollector); synchronized (contactPresEvtCollector) { if (!fixture.testerAgent.enterStatus(testerAgentNewStatusLong)) { throw new RuntimeException( "Tester UserAgent Failed to switch to the " + testerAgentNewStatus.getStatusName() + " state."); } // we may already have the event, but it won't hurt to check. contactPresEvtCollector.waitForEvent(12000); operationSetPresence.removeContactPresenceStatusListener(contactPresEvtCollector); } if (contactPresEvtCollector.collectedEvents.size() == 0) { logger.info( "PROBLEM. Authorisation process doesn't have finnished " + "Server doesn't report us for changing authorization flag! Will try to authorize once again"); fixture.testerAgent.sendAuthorizationReplay( fixture.icqAccountID.getUserID(), fixture.testerAgent.getAuthCmdFactory().responseReasonStr, fixture.testerAgent.getAuthCmdFactory().ACCEPT); Object obj = new Object(); synchronized (obj) { logger.debug("wait for authorization process to be finnished for second time"); obj.wait(10000); logger.debug("Stop waiting!"); } testerAgentOldStatus = fixture.testerAgent.getPresneceStatus(); testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_FFC; // in case we are by any chance already in a FREE_FOR_CHAT status, we'll // be changing to something else if (testerAgentOldStatus.equals(testerAgentNewStatus)) { testerAgentNewStatus = IcqStatusEnum.OCCUPIED; testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_OCCUPIED; } contactPresEvtCollector = new ContactPresenceEventCollector(fixture.testerAgent.getIcqUIN(), testerAgentNewStatus); operationSetPresence.addContactPresenceStatusListener(contactPresEvtCollector); synchronized (contactPresEvtCollector) { if (!fixture.testerAgent.enterStatus(testerAgentNewStatusLong)) { throw new RuntimeException( "Tester UserAgent Failed to switch to the " + testerAgentNewStatus.getStatusName() + " state."); } // we may already have the event, but it won't hurt to check. contactPresEvtCollector.waitForEvent(12000); operationSetPresence.removeContactPresenceStatusListener(contactPresEvtCollector); } } assertEquals( "Presence Notif. event dispatching failed.", 1, contactPresEvtCollector.collectedEvents.size()); ContactPresenceStatusChangeEvent presEvt = (ContactPresenceStatusChangeEvent) contactPresEvtCollector.collectedEvents.get(0); assertEquals( "Presence Notif. event Source:", fixture.testerAgent.getIcqUIN(), ((Contact) presEvt.getSource()).getAddress()); assertEquals( "Presence Notif. event Source Contact:", fixture.testerAgent.getIcqUIN(), presEvt.getSourceContact().getAddress()); assertSame( "Presence Notif. event Source Provider:", fixture.provider, presEvt.getSourceProvider()); PresenceStatus reportedNewStatus = presEvt.getNewStatus(); PresenceStatus reportedOldStatus = presEvt.getOldStatus(); assertEquals("Reported new PresenceStatus: ", testerAgentNewStatus, reportedNewStatus); // don't require equality between the reported old PresenceStatus and // the actual presence status of the tester agent because a first // notification is not supposed to have the old status as it really was. assertNotNull("Reported old PresenceStatus: ", reportedOldStatus); /** @todo tester agent changes status message we see the new message */ /** @todo we should see the alias of the tester agent. */ Object obj = new Object(); synchronized (obj) { logger.debug("wait a moment. give time to server"); obj.wait(4000); } } /** * We unsubscribe from presence notification deliveries concerning IcqTesterAgent's presence * status and verify that we receive the subscription removed event. We then make the tester agent * change status and make sure that no notifications are delivered. * * @throws java.lang.Exception in case unsubscribing fails. */ public void postTestUnsubscribe() throws Exception { logger.debug("Testing Unsubscribe and unsubscription event dispatch."); // First create a subscription and verify that it really gets created. SubscriptionEventCollector subEvtCollector = new SubscriptionEventCollector(); operationSetPresence.addSubscriptionListener(subEvtCollector); Contact icqTesterAgentContact = operationSetPresence.findContactByID(fixture.testerAgent.getIcqUIN()); assertNotNull( "Failed to find an existing subscription for the tester agent", icqTesterAgentContact); synchronized (subEvtCollector) { operationSetPresence.unsubscribe(icqTesterAgentContact); subEvtCollector.waitForEvent(40000); // don't want any more events operationSetPresence.removeSubscriptionListener(subEvtCollector); } assertEquals( "Subscription event dispatching failed.", 1, subEvtCollector.collectedEvents.size()); SubscriptionEvent subEvt = (SubscriptionEvent) subEvtCollector.collectedEvents.get(0); assertEquals("SubscriptionEvent Source:", icqTesterAgentContact, subEvt.getSource()); assertEquals( "SubscriptionEvent Source Contact:", icqTesterAgentContact, subEvt.getSourceContact()); assertSame("SubscriptionEvent Source Provider:", fixture.provider, subEvt.getSourceProvider()); subEvtCollector.collectedEvents.clear(); // make the user agent tester change its states and make sure we don't // get notifications as we're now unsubscribed. logger.debug("Testing (lack of) presence notifications."); IcqStatusEnum testerAgentOldStatus = fixture.testerAgent.getPresneceStatus(); IcqStatusEnum testerAgentNewStatus = IcqStatusEnum.FREE_FOR_CHAT; long testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_FFC; // in case we are by any chance already in a FREE_FOR_CHAT status, we'll // be changing to something else if (testerAgentOldStatus.equals(testerAgentNewStatus)) { testerAgentNewStatus = IcqStatusEnum.DO_NOT_DISTURB; testerAgentNewStatusLong = FullUserInfo.ICQSTATUS_DND; } // now do the actual status notification testing ContactPresenceEventCollector contactPresEvtCollector = new ContactPresenceEventCollector(fixture.testerAgent.getIcqUIN(), null); operationSetPresence.addContactPresenceStatusListener(contactPresEvtCollector); synchronized (contactPresEvtCollector) { if (!fixture.testerAgent.enterStatus(testerAgentNewStatusLong)) { throw new RuntimeException( "Tester UserAgent Failed to switch to the " + testerAgentNewStatus.getStatusName() + " state."); } // we may already have the event, but it won't hurt to check. contactPresEvtCollector.waitForEvent(10000); operationSetPresence.removeContactPresenceStatusListener(contactPresEvtCollector); } assertEquals( "Presence Notifications were received after unsubscibing.", 0, contactPresEvtCollector.collectedEvents.size()); } /** * An event collector that would collect all events generated by a provider after a status change. * The collector would also do a notidyAll every time it receives an event. */ private class PresenceStatusEventCollector implements ProviderPresenceStatusListener { public ArrayList<EventObject> collectedPresEvents = new ArrayList<EventObject>(); public ArrayList<EventObject> collectedStatMsgEvents = new ArrayList<EventObject>(); public void providerStatusChanged(ProviderPresenceStatusChangeEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedPresEvents.size() + ")= " + evt); collectedPresEvents.add(evt); notifyAll(); } } public void providerStatusMessageChanged(PropertyChangeEvent evt) { synchronized (this) { logger.debug("Collected stat.msg. evt(" + collectedPresEvents.size() + ")= " + evt); collectedStatMsgEvents.add(evt); notifyAll(); } } /** * Blocks until at least one event is received or until waitFor milliseconds pass (whichever * happens first). * * @param waitFor the number of milliseconds that we should be waiting for an event before * simply bailing out. */ public void waitForPresEvent(long waitFor) { logger.trace("Waiting for a change in provider status."); synchronized (this) { if (collectedPresEvents.size() > 0) { logger.trace("Change already received. " + collectedPresEvents); return; } try { wait(waitFor); if (collectedPresEvents.size() > 0) logger.trace("Received a change in provider status."); else logger.trace("No change received for " + waitFor + "ms."); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a provider evt", ex); } } } /** * Blocks until at least one status message event is received or until waitFor milliseconds pass * (whichever happens first). * * @param waitFor the number of milliseconds that we should be waiting for a status message * event before simply bailing out. */ public void waitForStatMsgEvent(long waitFor) { logger.trace("Waiting for a provider status message event."); synchronized (this) { if (collectedStatMsgEvents.size() > 0) { logger.trace("Stat msg. evt already received. " + collectedStatMsgEvents); return; } try { wait(waitFor); if (collectedStatMsgEvents.size() > 0) logger.trace("Received a prov. stat. msg. evt."); else logger.trace("No prov. stat msg. received for " + waitFor + "ms."); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a status msg evt", ex); } } } } /** The class would listen for and store received subscription modification events. */ private class SubscriptionEventCollector implements SubscriptionListener { public ArrayList<EventObject> collectedEvents = new ArrayList<EventObject>(); /** * Blocks until at least one event is received or until waitFor milliseconds pass (whichever * happens first). * * @param waitFor the number of milliseconds that we should be waiting for an event before * simply bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedEvents.size() > 0) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionCreated(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionRemoved(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void contactModified(ContactPropertyChangeEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionMoved(SubscriptionMovedEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionFailed(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } /** * Stores the received subscription and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void subscriptionResolved(SubscriptionEvent evt) { synchronized (this) { logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } } /** * The class would listen for and store received events caused by changes in contact presence * states. */ private class ContactPresenceEventCollector implements ContactPresenceStatusListener { public ArrayList<EventObject> collectedEvents = new ArrayList<EventObject>(); private String trackedScreenName = null; private IcqStatusEnum status = null; ContactPresenceEventCollector(String screenname, IcqStatusEnum wantedStatus) { this.trackedScreenName = screenname; this.status = wantedStatus; } /** * Blocks until at least one event is received or until waitFor milliseconds pass (whichever * happens first). * * @param waitFor the number of milliseconds that we should be waiting for an event before * simply bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedEvents.size() > 0) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } /** * Stores the received status change event and notifies all waiting on this object * * @param evt the SubscriptionEvent containing the corresponding contact */ public void contactPresenceStatusChanged(ContactPresenceStatusChangeEvent evt) { synchronized (this) { // if the user has specified event details and the received // event does not match - then ignore it. if (this.trackedScreenName != null && !evt.getSourceContact().getAddress().equals(trackedScreenName)) return; if (status != null && status != evt.getNewStatus()) return; logger.debug("Collected evt(" + collectedEvents.size() + ")= " + evt); collectedEvents.add(evt); notifyAll(); } } } /** * Authorization handler for the implementation tests * * <p>1. when authorization request is received we answer with the already set Authorization * response, but before that wait some time as a normal user * * <p>2. When authorization request is required for adding buddy the request is made with already * set authorization reason * * <p>3. When authorization replay is received - we store that it is received and the reason that * was received */ private static class AuthEventCollector implements AuthorizationHandler { boolean isAuthorizationRequestSent = false; String authorizationRequestReason = null; boolean isAuthorizationResponseReceived = false; AuthorizationResponse response = null; String authorizationResponseString = null; // receiving auth request AuthorizationResponse responseToRequest = null; boolean isAuthorizationRequestReceived = false; public AuthorizationResponse processAuthorisationRequest( AuthorizationRequest req, Contact sourceContact) { logger.debug("Processing in " + this); synchronized (this) { logger.trace("processAuthorisationRequest " + req + " " + sourceContact); isAuthorizationRequestReceived = true; authorizationRequestReason = req.getReason(); notifyAll(); // will wait as a normal user Object lock = new Object(); synchronized (lock) { try { lock.wait(2000); } catch (Exception ex) { } } return responseToRequest; } } public AuthorizationRequest createAuthorizationRequest(Contact contact) { logger.trace("createAuthorizationRequest " + contact); AuthorizationRequest authReq = new AuthorizationRequest(); authReq.setReason(authorizationRequestReason); isAuthorizationRequestSent = true; return authReq; } public void processAuthorizationResponse( AuthorizationResponse response, Contact sourceContact) { synchronized (this) { isAuthorizationResponseReceived = true; this.response = response; authorizationResponseString = response.getReason(); logger.trace( "processAuthorizationResponse '" + authorizationResponseString + "' " + response.getResponseCode() + " " + sourceContact); notifyAll(); } } public void waitForAuthResponse(long waitFor) { synchronized (this) { if (isAuthorizationResponseReceived) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } public void waitForAuthRequest(long waitFor) { synchronized (this) { if (isAuthorizationRequestReceived) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } } /** * Used to wait till buddy is removed from our contact list. Used in the authorization process * tests */ private static class UnsubscribeWait extends SubscriptionAdapter { public void waitForUnsubscribre(long waitFor) { synchronized (this) { try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } public void subscriptionRemoved(SubscriptionEvent evt) { synchronized (this) { logger.debug("Got subscriptionRemoved " + evt); notifyAll(); } } } /** Tests for receiving authorization requests */ public void postTestReceiveAuthorizatinonRequest() { logger.debug("Testing receive of authorization request!"); // set first response isAccepted and responseString // the first authorization process is negative // the agent try to add us to his contact list and ask us for // authorization but we deny him String firstRequestResponse = "First Request will be denied!!!"; authEventCollector.responseToRequest = new AuthorizationResponse(AuthorizationResponse.REJECT, firstRequestResponse); logger.debug("authEventCollector " + authEventCollector); authEventCollector.isAuthorizationRequestReceived = false; authEventCollector.authorizationRequestReason = null; fixture.testerAgent.getAuthCmdFactory().requestReasonStr = "Deny my first request!"; fixture.testerAgent.getAuthCmdFactory().isErrorAddingReceived = false; fixture.testerAgent.getAuthCmdFactory().responseReasonStr = null; fixture.testerAgent.getAuthCmdFactory().isRequestAccepted = false; // be sure buddy is not already in the list fixture.testerAgent.deleteBuddy(fixture.ourUserID); fixture.testerAgent.addBuddy(fixture.ourUserID); // wait agent to receive error and to request us for our authorization authEventCollector.waitForAuthRequest(25000); // check have we received authorization request? assertTrue( "Error adding buddy not recieved or the buddy(" + fixture.ourUserID + ") doesn't require authorization 1", fixture.testerAgent.getAuthCmdFactory().isErrorAddingReceived); assertTrue( "We haven't received any authorization request ", authEventCollector.isAuthorizationRequestReceived); assertNotNull( "We haven't received any reason for authorization", authEventCollector.authorizationRequestReason); assertEquals( "Error sent request reason is not as the received one", fixture.testerAgent.getAuthCmdFactory().requestReasonStr, authEventCollector.authorizationRequestReason); // wait agent to receive our response Object lock = new Object(); synchronized (lock) { try { lock.wait(5000); } catch (Exception ex) { } } // check is correct - the received response from the agent assertNotNull( "Agent haven't received any reason from authorization reply", authEventCollector.authorizationRequestReason); assertEquals( "Received auth response from agent is not as the sent one", fixture.testerAgent.getAuthCmdFactory().responseReasonStr, firstRequestResponse); boolean isAcceptedAuthReuest = authEventCollector.responseToRequest.getResponseCode().equals(AuthorizationResponse.ACCEPT); assertEquals( "Agent received Response is not as the sent one", fixture.testerAgent.getAuthCmdFactory().isRequestAccepted, isAcceptedAuthReuest); // delete us from his list // be sure buddy is not already in the list fixture.testerAgent.deleteBuddy(fixture.ourUserID); // set second response isAccepted and responseString // the second test is the same as first, but this time we accept // the request and check that everything is OK. String secondRequestResponse = "Second Request will be accepted!!!"; authEventCollector.responseToRequest = new AuthorizationResponse(AuthorizationResponse.ACCEPT, secondRequestResponse); authEventCollector.isAuthorizationRequestReceived = false; authEventCollector.authorizationRequestReason = null; fixture.testerAgent.getAuthCmdFactory().requestReasonStr = "Accept my second request!"; fixture.testerAgent.getAuthCmdFactory().isErrorAddingReceived = false; fixture.testerAgent.getAuthCmdFactory().responseReasonStr = null; fixture.testerAgent.getAuthCmdFactory().isRequestAccepted = false; // add us to his list again fixture.testerAgent.addBuddy(fixture.ourUserID); // wait agent to receive error and to request us for our authorization authEventCollector.waitForAuthRequest(25000); // check have we received authorization request? assertTrue( "Error adding buddy not recieved or the buddy(" + fixture.ourUserID + ") doesn't require authorization 2", fixture.testerAgent.getAuthCmdFactory().isErrorAddingReceived); assertTrue( "We haven't received any authorization request ", authEventCollector.isAuthorizationRequestReceived); assertNotNull( "We haven't received any reason for authorization", authEventCollector.authorizationRequestReason); assertEquals( "Error sent request reason is not as the received one", fixture.testerAgent.getAuthCmdFactory().requestReasonStr, authEventCollector.authorizationRequestReason); // wait agent to receive our response synchronized (lock) { try { lock.wait(5000); } catch (Exception ex) { } } // check is correct the received response from the agent assertNotNull( "Agent haven't received any reason from authorization reply", authEventCollector.authorizationRequestReason); assertEquals( "Received auth response from agent is not as the sent one", fixture.testerAgent.getAuthCmdFactory().responseReasonStr, secondRequestResponse); isAcceptedAuthReuest = authEventCollector.responseToRequest.getResponseCode().equals(AuthorizationResponse.ACCEPT); assertEquals( "Agent received Response is not as the sent one", fixture.testerAgent.getAuthCmdFactory().isRequestAccepted, isAcceptedAuthReuest); } }
/** * Tests whether accaounts are uninstalled properly. It is important that tests from this class be * called last since they will install the accounts that have been used to test the implementations. * Apart from uninstallation tests the class also contains tests that remove and reinstall the * protocol provider bundle in order to verify that accounts are persistent. * * @author Emil Ivov */ public class TestAccountUninstallation extends TestCase { private static final Logger logger = Logger.getLogger(TestAccountUninstallation.class); private SipSlickFixture fixture = new SipSlickFixture(); /** * Constructs a test instance * * @param name The name of the test. */ public TestAccountUninstallation(String name) { super(name); } /** * JUnit setup method. * * @throws Exception in case anything goes wrong. */ protected void setUp() throws Exception { super.setUp(); fixture.setUp(); } /** * JUnit teardown method. * * @throws Exception in case anything goes wrong. */ protected void tearDown() throws Exception { fixture.tearDown(); super.tearDown(); } /** * Returns a suite containing tests in this class in the order that we'd like them executed. * * @return a Test suite containing tests in this class in the order that we'd like them executed. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new TestAccountUninstallation("testProviderUnregister")); suite.addTest(new TestAccountUninstallation("testInstallationPersistency")); suite.addTest(new TestAccountUninstallation("testUninstallAccount")); return suite; } /** * Unregisters both providers and verifies whether they have changed state accordingly. * * @throws OperationFailedException if unregister fails with an error. */ public void testProviderUnregister() throws OperationFailedException { // make sure providers are still registered assertEquals(fixture.provider1.getRegistrationState(), RegistrationState.REGISTERED); assertEquals(fixture.provider2.getRegistrationState(), RegistrationState.REGISTERED); UnregistrationEventCollector collector1 = new UnregistrationEventCollector(); UnregistrationEventCollector collector2 = new UnregistrationEventCollector(); fixture.provider1.addRegistrationStateChangeListener(collector1); fixture.provider2.addRegistrationStateChangeListener(collector2); // unregister both providers fixture.provider1.unregister(); fixture.provider2.unregister(); collector1.waitForEvent(10000); collector2.waitForEvent(10000); assertTrue( "Provider did not distribute unregister events", 2 <= collector1.collectedNewStates.size()); assertTrue( "Provider did not distribute unregister events", 2 <= collector2.collectedNewStates.size()); // make sure both providers are now unregistered. assertEquals( "Provider state after calling unregister().", RegistrationState.UNREGISTERED, fixture.provider1.getRegistrationState()); assertEquals( "Provider state after calling unregister().", RegistrationState.UNREGISTERED, fixture.provider2.getRegistrationState()); } /** * Stops and removes the tested bundle, verifies that it has unregistered its provider, then * reloads and restarts the bundle and verifies that the protocol provider is reRegistered in the * bundle context. * * @throws java.lang.Exception if an exception occurs during testing. */ public void testInstallationPersistency() throws Exception { Bundle providerBundle = fixture.findProtocolProviderBundle(fixture.provider1); // set the global providerBundle reference that we will be using // in the last series of tests (Account uninstallation persistency) SipSlickFixture.providerBundle = providerBundle; assertNotNull("Couldn't find a bundle for the tested provider", providerBundle); providerBundle.stop(); assertTrue( "Couldn't stop the protocol provider bundle. State was " + providerBundle.getState(), Bundle.ACTIVE != providerBundle.getState() && Bundle.STOPPING != providerBundle.getState()); providerBundle.uninstall(); assertEquals( "Couldn't stop the protocol provider bundle.", Bundle.UNINSTALLED, providerBundle.getState()); // verify that the provider is no longer available ServiceReference[] sipProviderRefs = null; try { sipProviderRefs = fixture.bc.getServiceReferences( ProtocolProviderService.class.getName(), "(&" + "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")" + "(" + ProtocolProviderFactory.USER_ID + "=" + fixture.userID1 + ")" + ")"); } catch (InvalidSyntaxException ex) { fail("We apparently got our filter wrong: " + ex.getMessage()); } // make sure we didn't see a service assertTrue( "A Protocol Provider Service was still regged as an osgi service " + "for SIP URI:" + fixture.userID1 + "After it was explicitly uninstalled", sipProviderRefs == null || sipProviderRefs.length == 0); // verify that the provider factory knows that we have uninstalled the // provider. assertTrue( "The SIP provider factory kept a reference to the provider we just " + "uninstalled (uri=" + fixture.userID1 + ")", fixture.providerFactory.getRegisteredAccounts().isEmpty() && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID()) == null); // Now reinstall the bundle providerBundle = fixture.bc.installBundle(providerBundle.getLocation()); // set the global providerBundle reference that we will be using // in the last series of tests (Account uninstallation persistency) SipSlickFixture.providerBundle = providerBundle; assertEquals( "Couldn't re-install protocol provider bundle.", Bundle.INSTALLED, providerBundle.getState()); AccountManagerUtils.startBundleAndWaitStoredAccountsLoaded( fixture.bc, providerBundle, ProtocolNames.SIP); assertEquals( "Couldn't re-start protocol provider bundle.", Bundle.ACTIVE, providerBundle.getState()); // Make sure that the provider is there again. // verify that the provider is no longer available try { sipProviderRefs = fixture.bc.getServiceReferences( ProtocolProviderService.class.getName(), "(&" + "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")" + "(" + ProtocolProviderFactory.USER_ID + "=" + fixture.userID1 + ")" + ")"); } catch (InvalidSyntaxException ex) { fail("We apparently got our filter wrong " + ex.getMessage()); } // make sure we didn't see a service assertTrue( "A Protocol Provider Service was not restored after being" + "reinstalled. SIP URI:" + fixture.userID1, sipProviderRefs != null && sipProviderRefs.length > 0); ServiceReference[] sipFactoryRefs = null; try { sipFactoryRefs = fixture.bc.getServiceReferences( ProtocolProviderFactory.class.getName(), "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")"); } catch (InvalidSyntaxException ex) { fail("We apparently got our filter wrong " + ex.getMessage()); } // we're the ones who've reinstalled the factory so it's our // responsibility to update the fixture. fixture.providerFactory = (ProtocolProviderFactory) fixture.bc.getService(sipFactoryRefs[0]); fixture.provider1 = (ProtocolProviderService) fixture.bc.getService(sipProviderRefs[0]); // verify that the provider is also restored in the provider factory // itself assertTrue( "The SIP provider did not restore its own reference to the provider " + "that we just reinstalled (URI=" + fixture.userID1 + ")", !fixture.providerFactory.getRegisteredAccounts().isEmpty() && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID()) != null); } /** Uinstalls our test account and makes sure it really has been removed. */ public void testUninstallAccount() { assertFalse( "No installed accounts found", fixture.providerFactory.getRegisteredAccounts().isEmpty()); assertNotNull( "Found no provider corresponding to URI " + fixture.userID1, fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID())); assertTrue( "Failed to remove a provider corresponding to URI " + fixture.userID1, fixture.providerFactory.uninstallAccount(fixture.provider1.getAccountID())); assertTrue( "Failed to remove a provider corresponding to URI " + fixture.userID1, fixture.providerFactory.uninstallAccount(fixture.provider2.getAccountID())); // make sure no providers have remained installed. ServiceReference[] sipProviderRefs = null; try { sipProviderRefs = fixture.bc.getServiceReferences( ProtocolProviderService.class.getName(), "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")"); } catch (InvalidSyntaxException ex) { fail("We apparently got our filter wrong " + ex.getMessage()); } // make sure we didn't see a service assertTrue( "A Protocol Provider Service was still regged as an osgi " + "service for SIP URI:" + fixture.userID1 + "After it was explicitly uninstalled", sipProviderRefs == null || sipProviderRefs.length == 0); // verify that the provider factory knows that we have uninstalled the // provider. assertTrue( "The SIP provider factory kept a reference to the provider we just " + "uninstalled (uri=" + fixture.userID1 + ")", fixture.providerFactory.getRegisteredAccounts().isEmpty() && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID()) == null); } /** * A class that would plugin as a registration listener to a protocol provider and simply record * all events that it sees and notifyAll() if it sees an event that notifies us of a completed * registration. */ public class UnregistrationEventCollector implements RegistrationStateChangeListener { public List<RegistrationState> collectedNewStates = new LinkedList<RegistrationState>(); /** * The method would simply register all received events so that they could be available for * later inspection by the unit tests. In the case where a registraiton event notifying us of a * completed registration is seen, the method would call notifyAll(). * * @param evt ProviderStatusChangeEvent the event describing the status change. */ public void registrationStateChanged(RegistrationStateChangeEvent evt) { logger.debug("Received a RegistrationStateChangeEvent: " + evt); collectedNewStates.add(evt.getNewState()); if (evt.getNewState().equals(RegistrationState.UNREGISTERED)) { logger.debug("We're registered and will notify those who wait"); synchronized (this) { notifyAll(); } } } /** * Blocks until an event notifying us of the awaited state change is received or until waitFor * miliseconds pass (whichever happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { logger.trace("Waiting for a RegistrationStateChangeEvent"); synchronized (this) { if (collectedNewStates.contains(RegistrationState.UNREGISTERED)) { logger.trace("Event already received. " + collectedNewStates); return; } try { wait(waitFor); if (collectedNewStates.size() > 0) logger.trace("Received a RegistrationStateChangeEvent."); else logger.trace("No RegistrationStateChangeEvent received for " + waitFor + "ms."); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a " + "RegistrationStateChangeEvent", ex); } } } } }
/** * Performs testing of the basic instant messaging operation set. Tests include going over basic * functionality such as sending a message from the tested implementation and asserting reception by * the tester agent and vice versa. * * @author Emil Ivov */ public class TestOperationSetBasicInstantMessaging extends TestCase { private static final Logger logger = Logger.getLogger(TestOperationSetBasicInstantMessaging.class); private GibberishSlickFixture fixture = new GibberishSlickFixture(); private OperationSetBasicInstantMessaging opSetBasicIM1 = null; private OperationSetBasicInstantMessaging opSetBasicIM2 = null; private OperationSetPresence opSetPresence1 = null; private OperationSetPresence opSetPresence2 = null; public TestOperationSetBasicInstantMessaging(String name) { super(name); } /** * Get a reference to the basic IM operation set. * * @throws Exception if this is not a good day. */ protected void setUp() throws Exception { super.setUp(); fixture.setUp(); Map<String, OperationSet> supportedOperationSets1 = fixture.provider1.getSupportedOperationSets(); if (supportedOperationSets1 == null || supportedOperationSets1.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this implementation. "); // get the operation set presence here. opSetBasicIM1 = (OperationSetBasicInstantMessaging) supportedOperationSets1.get(OperationSetBasicInstantMessaging.class.getName()); if (opSetBasicIM1 == null) { throw new NullPointerException("No implementation for basic IM was found"); } // we also need the presence op set in order to retrieve contacts. opSetPresence1 = (OperationSetPresence) supportedOperationSets1.get(OperationSetPresence.class.getName()); // if the op set is null show that we're not happy. if (opSetPresence1 == null) { throw new NullPointerException( "An implementation of the service must provide an " + "implementation of at least one of the PresenceOperationSets"); } Map<String, OperationSet> supportedOperationSets2 = fixture.provider2.getSupportedOperationSets(); if (supportedOperationSets2 == null || supportedOperationSets2.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this implementation. "); // get the operation set presence here. opSetBasicIM2 = (OperationSetBasicInstantMessaging) supportedOperationSets2.get(OperationSetBasicInstantMessaging.class.getName()); if (opSetBasicIM2 == null) { throw new NullPointerException("No implementation for basic IM was found"); } opSetPresence2 = (OperationSetPresence) supportedOperationSets2.get(OperationSetPresence.class.getName()); // if the op set is null show that we're not happy. if (opSetPresence2 == null) { throw new NullPointerException( "An implementation of the service must provide an " + "implementation of at least one of the PresenceOperationSets"); } } protected void tearDown() throws Exception { super.tearDown(); fixture.tearDown(); } /** * Creates a test suite containing tests of this class in a specific order. We'll first execute * tests beginning with the "test" prefix and then go to ordered tests.We first execture tests for * receiving messagese, so that a volatile contact is created for the sender. we'll then be able * to retrieve this volatile contact and send them a message on our turn. We need to do things * this way as the contact corresponding to the tester agent has been removed in the previous test * and we no longer have it in our contact list. * * @return Test a testsuite containing all tests to execute. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new TestOperationSetBasicInstantMessaging("prepareContactList")); suite.addTestSuite(TestOperationSetBasicInstantMessaging.class); // the following 2 need to be run in the specified order. suite.addTest(new TestOperationSetBasicInstantMessaging("firstTestReceiveMessage")); suite.addTest(new TestOperationSetBasicInstantMessaging("thenTestSendMessage")); return suite; } /** * Create the list to be sure that contacts exchanging messages exists in each other lists * * @throws Exception */ public void prepareContactList() throws Exception { fixture.clearProvidersLists(); Object o = new Object(); synchronized (o) { o.wait(2000); } try { opSetPresence1.subscribe(fixture.userID2); } catch (OperationFailedException ex) { // the contact already exist its OK } try { opSetPresence2.subscribe(fixture.userID1); } catch (OperationFailedException ex1) { // the contact already exist its OK } synchronized (o) { o.wait(2000); } } /** * Send an instant message from the tested operation set and assert reception by the tester agent. */ public void firstTestReceiveMessage() { String body = "This is an IM coming from the tester agent" + " on " + new Date().toString(); ImEventCollector evtCollector = new ImEventCollector(); // add a msg listener and register to the op set and send an instant // msg from the tester agent. opSetBasicIM1.addMessageListener(evtCollector); Contact testerAgentContact = opSetPresence2.findContactByID(fixture.userID1); logger.debug("Will send message " + body + " to: " + testerAgentContact); opSetBasicIM2.sendInstantMessage(testerAgentContact, opSetBasicIM2.createMessage(body)); evtCollector.waitForEvent(10000); opSetBasicIM1.removeMessageListener(evtCollector); // assert reception of a message event assertTrue( "No events delivered upon a received message", evtCollector.collectedEvents.size() > 0); // assert event instance of Message Received Evt assertTrue( "Received evt was not an instance of " + MessageReceivedEvent.class.getName(), evtCollector.collectedEvents.get(0) instanceof MessageReceivedEvent); // assert source contact == testAgent.uin MessageReceivedEvent evt = (MessageReceivedEvent) evtCollector.collectedEvents.get(0); assertEquals("message sender ", evt.getSourceContact().getAddress(), fixture.userID2); // assert messageBody == body assertEquals("message body", body, evt.getSourceMessage().getContent()); } /** * Send an instant message from the tester agent and assert reception by the tested implementation */ public void thenTestSendMessage() { logger.debug( "Printing Server Stored list to see if message fails are contacts in each other lists"); ContactGroup rootGroup1 = ((OperationSetPersistentPresence) opSetPresence1).getServerStoredContactListRoot(); logger.debug("=========== Server Stored Contact List 1 ================="); logger.debug( "rootGroup=" + rootGroup1.getGroupName() + " rootGroup.childContacts=" + rootGroup1.countContacts() + "rootGroup.childGroups=" + rootGroup1.countSubgroups() + "Printing rootGroupContents=\n" + rootGroup1.toString()); ContactGroup rootGroup2 = ((OperationSetPersistentPresence) opSetPresence2).getServerStoredContactListRoot(); logger.debug("=========== Server Stored Contact List 2 ================="); logger.debug( "rootGroup=" + rootGroup2.getGroupName() + " rootGroup.childContacts=" + rootGroup2.countContacts() + "rootGroup.childGroups=" + rootGroup2.countSubgroups() + "Printing rootGroupContents=\n" + rootGroup2.toString()); String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); // create the message net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body); // register a listener in the op set ImEventCollector imEvtCollector1 = new ImEventCollector(); opSetBasicIM1.addMessageListener(imEvtCollector1); // register a listener in the tester agent ImEventCollector imEvtCollector2 = new ImEventCollector(); opSetBasicIM2.addMessageListener(imEvtCollector2); Contact testerAgentContact = opSetPresence1.findContactByID(fixture.userID2); opSetBasicIM1.sendInstantMessage(testerAgentContact, msg); imEvtCollector1.waitForEvent(10000); imEvtCollector2.waitForEvent(10000); opSetBasicIM1.removeMessageListener(imEvtCollector1); opSetBasicIM2.removeMessageListener(imEvtCollector2); // verify that the message delivered event was dispatched assertTrue( "No events delivered when sending a message", imEvtCollector1.collectedEvents.size() > 0); assertTrue( "Received evt was not an instance of " + MessageDeliveredEvent.class.getName(), imEvtCollector1.collectedEvents.get(0) instanceof MessageDeliveredEvent); MessageDeliveredEvent evt = (MessageDeliveredEvent) imEvtCollector1.collectedEvents.get(0); assertEquals("message destination ", evt.getDestinationContact().getAddress(), fixture.userID2); assertSame("source message", msg, evt.getSourceMessage()); // verify that the message has successfully arived at the destination assertTrue( "No messages received by the tester agent", imEvtCollector2.collectedEvents.size() > 0); assertFalse( "Message was unable to deliver !", imEvtCollector2.collectedEvents.get(0) instanceof MessageDeliveryFailedEvent); String receivedBody = ((MessageReceivedEvent) imEvtCollector2.collectedEvents.get(0)) .getSourceMessage() .getContent(); assertEquals("received message body", msg.getContent(), receivedBody); } /** Creates an Message through the simple createMessage() method and inspects its parameters. */ public void testCreateMessage1() { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes", Arrays.equals(body.getBytes(), msg.getRawData())); assertEquals("message length", body.length(), msg.getSize()); assertEquals( "message content type", OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, msg.getContentType()); assertEquals( "message encoding", OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); // a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM1.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals(msg2.getMessageUID())); } /** Creates an Message through the advance createMessage() method and inspects its parameters. */ public void testCreateMessage2() throws UnsupportedEncodingException { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); String contentType = "text/html"; String encoding = "UTF-16"; String subject = "test message"; net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM1.createMessage(body, contentType, encoding, subject); byte[] bodyBytes = body.getBytes(encoding); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes", Arrays.equals(bodyBytes, msg.getRawData())); assertEquals("message length", bodyBytes.length, msg.getSize()); assertEquals("message content type", contentType, msg.getContentType()); assertEquals("message encoding", encoding, msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); // a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM1.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals(msg2.getMessageUID())); } /** Collects instant messaging events. */ private class ImEventCollector implements MessageListener { private List<EventObject> collectedEvents = new LinkedList<EventObject>(); /** * Called when a new incoming <tt>Message</tt> has been received. * * @param evt the <tt>MessageReceivedEvent</tt> containing the newly received message, its * sender and other details. */ public void messageReceived(MessageReceivedEvent evt) { logger.debug("Received a MessageReceivedEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Called to indicated that delivery of a message sent earlier has failed. Reason code and * phrase are contained by the <tt>MessageFailedEvent</tt> * * @param evt the <tt>MessageFailedEvent</tt> containing the ID of the message whose delivery * has failed. */ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) { logger.debug("Received a MessageDeliveryFailedEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Called when the underlying implementation has received an indication that a message, sent * earlier has been successfully received by the destination. * * @param evt the MessageDeliveredEvent containing the id of the message that has caused the * event. */ public void messageDelivered(MessageDeliveredEvent evt) { logger.debug("Received a MessageDeliveredEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Blocks until at least one event is received or until waitFor miliseconds pass (whichever * happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedEvents.size() > 0) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a message evt", ex); } } } } }
/** Functional tests on the simulated content generator. */ public class FuncSimulatedContent extends LockssTestCase { static final Logger log = Logger.getLogger("FuncSimulatedContent"); private PluginManager pluginMgr; private Plugin simPlugin; private SimulatedArchivalUnit sau1; private SimulatedContentGenerator scgen = null; private MockLockssDaemon theDaemon; String tempDirPath; String tempDirPath2; private static String DAMAGED_CACHED_URL = "/branch2/branch2/002file.txt"; public FuncSimulatedContent(String msg) { super(msg); } public void setUp() throws Exception { super.setUp(); tempDirPath = getTempDir().getAbsolutePath() + File.separator; theDaemon = getMockLockssDaemon(); theDaemon.getAlertManager(); theDaemon.getPluginManager().setLoadablePluginsReady(true); theDaemon.getHashService(); MockSystemMetrics metrics = new MyMockSystemMetrics(); metrics.initService(theDaemon); theDaemon.setSystemMetrics(metrics); theDaemon.setDaemonInited(true); Properties props = new Properties(); props.setProperty(SystemMetrics.PARAM_HASH_TEST_DURATION, "1000"); props.setProperty(SystemMetrics.PARAM_HASH_TEST_BYTE_STEP, "1024"); props.setProperty(ConfigManager.PARAM_PLATFORM_DISK_SPACE_LIST, tempDirPath); ConfigurationUtil.setCurrentConfigFromProps(props); pluginMgr = theDaemon.getPluginManager(); pluginMgr.startService(); theDaemon.getHashService().startService(); metrics.startService(); metrics.setHashSpeed(100); simPlugin = PluginTestUtil.findPlugin(SimulatedPlugin.class); } public void tearDown() throws Exception { theDaemon.getLockssRepository(sau1).stopService(); theDaemon.getNodeManager(sau1).stopService(); theDaemon.getPluginManager().stopService(); theDaemon.getHashService().stopService(); theDaemon.getSystemMetrics().stopService(); theDaemon.stopDaemon(); super.tearDown(); } SimulatedArchivalUnit setupSimAu(Configuration auConfig) throws ArchivalUnit.ConfigurationException { ArchivalUnit au = PluginTestUtil.createAndStartAu(simPlugin, auConfig); return (SimulatedArchivalUnit) au; } Configuration simAuConfig(String rootPath) { Configuration conf = ConfigManager.newConfiguration(); conf.put("root", rootPath); conf.put("depth", "2"); conf.put("branch", "2"); conf.put("numFiles", "2"); conf.put("badCachedFileLoc", "2,2"); conf.put("badCachedFileNum", "2"); return conf; } void enableFilter(SimulatedArchivalUnit sau, boolean enable) throws ArchivalUnit.ConfigurationException { Configuration auConfig = sau.getConfiguration().copy(); // no bad file when playing with filtering auConfig.remove("badCachedFileLoc"); auConfig.remove("badCachedFileNum"); if (enable) { auConfig.put(SimulatedPlugin.AU_PARAM_HASH_FILTER_SPEC, "true"); } else { auConfig.remove(SimulatedPlugin.AU_PARAM_HASH_FILTER_SPEC); } sau.setConfiguration(auConfig); } public void testSimulatedContent() throws Exception { sau1 = setupSimAu(simAuConfig(tempDirPath)); createContent(sau1); crawlContent(sau1); checkContent(sau1); doDamageRemoveTest(sau1); // must be before content read again checkFilter(sau1); hashContent(sau1); // this resets AU's config, do last to avoid messing up toBeDamaged set } public void testDualContentHash() throws Exception { sau1 = setupSimAu(simAuConfig(tempDirPath)); createContent(sau1); crawlContent(sau1); CachedUrlSet set = sau1.getAuCachedUrlSet(); byte[] nameH = getHash(set, true); byte[] contentH = getHash(set, false); tempDirPath2 = getTempDir().getAbsolutePath() + File.separator; SimulatedArchivalUnit sau2 = setupSimAu(simAuConfig(tempDirPath2)); createContent(sau2); crawlContent(sau2); set = sau2.getAuCachedUrlSet(); byte[] nameH2 = getHash(set, true); byte[] contentH2 = getHash(set, false); assertEquals(nameH, nameH2); assertEquals(contentH, contentH2); } public void testBaseUrl() throws Exception { sau1 = setupSimAu(simAuConfig(tempDirPath)); createContent(sau1); crawlContent(sau1); CachedUrlSet cus1 = sau1.getAuCachedUrlSet(); tempDirPath2 = getTempDir().getAbsolutePath() + File.separator; Configuration config2 = simAuConfig(tempDirPath2); config2.put("base_url", "http://anotherhost.org/"); SimulatedArchivalUnit sau2 = setupSimAu(config2); createContent(sau2); crawlContent(sau2); CachedUrlSet cus2 = sau1.getAuCachedUrlSet(); List urls1 = auUrls(sau1); List urls2 = auUrls(sau2); Pattern pat = Pattern.compile("http://([^/]+)(/.*)$"); List<String> l1 = auUrls(sau1); List<String> l2 = auUrls(sau2); assertEquals(l1.size(), l2.size()); for (int ix = 0; ix < l1.size(); ix++) { Matcher m1 = pat.matcher(l1.get(ix)); assertTrue(m1.matches()); Matcher m2 = pat.matcher(l2.get(ix)); assertTrue(m2.matches()); assertEquals("www.example.com", m1.group(1)); assertEquals("anotherhost.org", m2.group(1)); assertEquals(m1.group(2), m2.group(2)); } } public void testBaseUrlPath() throws Exception { sau1 = setupSimAu(simAuConfig(tempDirPath)); createContent(sau1); crawlContent(sau1); CachedUrlSet cus1 = sau1.getAuCachedUrlSet(); tempDirPath2 = getTempDir().getAbsolutePath() + File.separator; Configuration config2 = simAuConfig(tempDirPath2); config2.put("base_url", "http://anotherhost.org/some/path/"); SimulatedArchivalUnit sau2 = setupSimAu(config2); createContent(sau2); crawlContent(sau2); CachedUrlSet cus2 = sau1.getAuCachedUrlSet(); List urls1 = auUrls(sau1); List urls2 = auUrls(sau2); Pattern pat1 = Pattern.compile("http://www\\.example\\.com(/.*)$"); Pattern pat2 = Pattern.compile("http://anotherhost\\.org/some/path(/.*)$"); List<String> l1 = auUrls(sau1); List<String> l2 = auUrls(sau2); assertEquals(l1.size(), l2.size()); for (int ix = 0; ix < l1.size(); ix++) { Matcher m1 = pat1.matcher(l1.get(ix)); assertTrue(m1.matches()); Matcher m2 = pat2.matcher(l2.get(ix)); assertTrue(m2.matches()); assertEquals(m1.group(1), m2.group(1)); } } List<String> auUrls(ArchivalUnit au) { List<String> res = new ArrayList<String>(); for (Iterator iter = au.getAuCachedUrlSet().contentHashIterator(); iter.hasNext(); ) { CachedUrlSetNode cusn = (CachedUrlSetNode) iter.next(); if (cusn.hasContent()) { res.add(cusn.getUrl()); } } return res; } protected void createContent(SimulatedArchivalUnit sau) { log.debug("createContent()"); scgen = sau.getContentGenerator(); scgen.setFileTypes( SimulatedContentGenerator.FILE_TYPE_HTML + SimulatedContentGenerator.FILE_TYPE_TXT); scgen.setAbnormalFile("1,1", 1); scgen.setOddBranchesHaveContent(true); sau.deleteContentTree(); sau.generateContentTree(); assertTrue(scgen.isContentTree()); } protected void crawlContent(SimulatedArchivalUnit sau) { log.debug("crawlContent()"); CrawlSpec spec = new SpiderCrawlSpec(sau.getNewContentCrawlUrls(), null); Crawler crawler = new NoCrawlEndActionsNewContentCrawler(sau, spec, new MockAuState()); crawler.doCrawl(); } protected void checkContent(SimulatedArchivalUnit sau) throws IOException { log.debug("checkContent()"); checkRoot(sau); checkLeaf(sau); checkStoredContent(sau); checkDepth(sau); } protected void checkFilter(SimulatedArchivalUnit sau) throws Exception { log.debug("checkFilter()"); CachedUrl cu = sau.makeCachedUrl(sau.getUrlRoot() + "/001file.html"); enableFilter(sau, true); InputStream is = cu.openForHashing(); String expected = "001file.html This is file 1, depth 0, branch 0. foobar "; assertEquals(expected, StringUtil.fromInputStream(is)); is.close(); enableFilter(sau, false); cu = sau.makeCachedUrl(sau.getUrlRoot() + "/001file.html"); is = cu.openForHashing(); expected = "<HTML><HEAD><TITLE>001file.html</TITLE></HEAD><BODY>\n" + "This is file 1, depth 0, branch 0.<br><!-- comment --> " + "Citation String foobar<br><script>" + "(defun fact (n) (cond ((= n 0) 1) (t (fact (sub1 n)))))</script>\n" + "</BODY></HTML>"; assertEquals(expected, StringUtil.fromInputStream(is)); is.close(); } private byte[] fromHex(String hex) { return ByteArray.fromHexString(hex); } protected void hashContent(SimulatedArchivalUnit sau) throws Exception { log.debug("hashContent()"); measureHashSpeed(sau); // If any changes are made to the contents or shape of the simulated // content tree, these hash values will have to be changed checkHashSet(sau, true, false, fromHex("6AB258B4E1FFD9F9B45316B4F54111FF5E5948D2")); checkHashSet(sau, true, true, fromHex("6AB258B4E1FFD9F9B45316B4F54111FF5E5948D2")); checkHashSet(sau, false, false, fromHex("409893F1A603F4C276632694DB1621B639BD5164")); checkHashSet(sau, false, true, fromHex("85E6213C3771BEAC5A4602CAF7982C6C222800D5")); } protected void checkDepth(SimulatedArchivalUnit sau) { log.debug("checkDepth()"); String URL_ROOT = sau.getUrlRoot(); assertEquals(0, sau.getLinkDepth(URL_ROOT + "/index.html")); assertEquals(0, sau.getLinkDepth(URL_ROOT + "/")); assertEquals(1, sau.getLinkDepth(URL_ROOT + "/001file.html")); assertEquals(1, sau.getLinkDepth(URL_ROOT + "/branch1/index.html")); assertEquals(1, sau.getLinkDepth(URL_ROOT + "/branch1/")); assertEquals(2, sau.getLinkDepth(URL_ROOT + "/branch1/001file.html")); } protected void checkRoot(SimulatedArchivalUnit sau) { log.debug("checkRoot()"); CachedUrlSet set = sau.getAuCachedUrlSet(); Iterator setIt = set.flatSetIterator(); ArrayList childL = new ArrayList(1); CachedUrlSet cus = null; while (setIt.hasNext()) { cus = (CachedUrlSet) setIt.next(); childL.add(cus.getUrl()); } String urlRoot = sau.getUrlRoot(); String[] expectedA = new String[1]; expectedA[0] = urlRoot; assertIsomorphic(expectedA, childL); setIt = cus.flatSetIterator(); childL = new ArrayList(7); while (setIt.hasNext()) { childL.add(((CachedUrlSetNode) setIt.next()).getUrl()); } expectedA = new String[] { urlRoot + "/001file.html", urlRoot + "/001file.txt", urlRoot + "/002file.html", urlRoot + "/002file.txt", urlRoot + "/branch1", urlRoot + "/branch2", urlRoot + "/index.html" }; assertIsomorphic(expectedA, childL); } protected void checkLeaf(SimulatedArchivalUnit sau) { log.debug("checkLeaf()"); String parent = sau.getUrlRoot() + "/branch1"; CachedUrlSetSpec spec = new RangeCachedUrlSetSpec(parent); CachedUrlSet set = sau.makeCachedUrlSet(spec); Iterator setIt = set.contentHashIterator(); ArrayList childL = new ArrayList(16); while (setIt.hasNext()) { childL.add(((CachedUrlSetNode) setIt.next()).getUrl()); } String[] expectedA = new String[] { parent, parent + "/001file.html", parent + "/001file.txt", parent + "/002file.html", parent + "/002file.txt", parent + "/branch1", parent + "/branch1/001file.html", parent + "/branch1/001file.txt", parent + "/branch1/002file.html", parent + "/branch1/002file.txt", parent + "/branch1/index.html", parent + "/branch2", parent + "/branch2/001file.html", parent + "/branch2/001file.txt", parent + "/branch2/002file.html", parent + "/branch2/002file.txt", parent + "/branch2/index.html", parent + "/index.html", }; assertIsomorphic(expectedA, childL); } protected void checkUrlContent( SimulatedArchivalUnit sau, String path, int fileNum, int depth, int branchNum, boolean isAbnormal, boolean isDamaged) throws IOException { String file = sau.getUrlRoot() + path; CachedUrl url = sau.makeCachedUrl(file); String content = getUrlContent(url); String expectedContent; if (path.endsWith(".html")) { String fn = path.substring(path.lastIndexOf("/") + 1); expectedContent = scgen.getHtmlFileContent(fn, fileNum, depth, branchNum, isAbnormal); } else { expectedContent = scgen.getTxtContent(fileNum, depth, branchNum, isAbnormal); } if (isDamaged) { assertNotEquals(expectedContent, content); } else { assertEquals(expectedContent, content); } } protected void checkStoredContent(SimulatedArchivalUnit sau) throws IOException { checkUrlContent(sau, "/001file.txt", 1, 0, 0, false, false); checkUrlContent(sau, "/branch1/branch1/001file.txt", 1, 2, 1, true, false); checkUrlContent(sau, DAMAGED_CACHED_URL, 2, 2, 2, false, true); } protected void doDamageRemoveTest(SimulatedArchivalUnit sau) throws Exception { /* Cache the file again; this time the damage should be gone */ String file = sau.getUrlRoot() + DAMAGED_CACHED_URL; UrlCacher uc = sau.makeUrlCacher(file); BitSet fetchFlags = new BitSet(); fetchFlags.set(UrlCacher.REFETCH_FLAG); uc.setFetchFlags(fetchFlags); uc.cache(); checkUrlContent(sau, DAMAGED_CACHED_URL, 2, 2, 2, false, false); } private void measureHashSpeed(SimulatedArchivalUnit sau) throws Exception { MessageDigest dig = null; try { dig = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException ex) { fail("No algorithm."); } CachedUrlSet set = sau.getAuCachedUrlSet(); CachedUrlSetHasher hasher = set.getContentHasher(dig); SystemMetrics metrics = theDaemon.getSystemMetrics(); int estimate = metrics.getBytesPerMsHashEstimate(hasher, dig); // should be protected against this being zero by MyMockSystemMetrics, // but otherwise use the proper calculation. This avoids test failure // due to really slow machines assertTrue(estimate > 0); long estimatedTime = set.estimatedHashDuration(); long size = ((Long) PrivilegedAccessor.getValue(set, "totalNodeSize")).longValue(); assertTrue(size > 0); System.out.println("b/ms: " + estimate); System.out.println("size: " + size); System.out.println("estimate: " + estimatedTime); assertEquals(estimatedTime, theDaemon.getHashService().padHashEstimate(size / estimate)); } private void checkHashSet( SimulatedArchivalUnit sau, boolean namesOnly, boolean filter, byte[] expected) throws Exception { enableFilter(sau, filter); CachedUrlSet set = sau.getAuCachedUrlSet(); byte[] hash = getHash(set, namesOnly); assertEquals(expected, hash); String parent = sau.getUrlRoot() + "/branch1"; CachedUrlSetSpec spec = new RangeCachedUrlSetSpec(parent); set = sau.makeCachedUrlSet(spec); byte[] hash2 = getHash(set, namesOnly); assertFalse(Arrays.equals(hash, hash2)); } private byte[] getHash(CachedUrlSet set, boolean namesOnly) throws IOException { MessageDigest dig = null; try { dig = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException ex) { fail("No algorithm."); } hash(set, dig, namesOnly); return dig.digest(); } private void hash(CachedUrlSet set, MessageDigest dig, boolean namesOnly) throws IOException { CachedUrlSetHasher hasher = null; if (namesOnly) { hasher = set.getNameHasher(dig); } else { hasher = set.getContentHasher(dig); } int bytesHashed = 0; long timeTaken = System.currentTimeMillis(); while (!hasher.finished()) { bytesHashed += hasher.hashStep(256); } timeTaken = System.currentTimeMillis() - timeTaken; if ((timeTaken > 0) && (bytesHashed > 500)) { System.out.println("Bytes hashed: " + bytesHashed); System.out.println("Time taken: " + timeTaken + "ms"); System.out.println("Bytes/sec: " + (bytesHashed * 1000 / timeTaken)); } else { System.out.println("No time taken, or insufficient bytes hashed."); System.out.println("Bytes hashed: " + bytesHashed); System.out.println("Time taken: " + timeTaken + "ms"); } } private String getUrlContent(CachedUrl url) throws IOException { InputStream content = url.getUnfilteredInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); StreamUtil.copy(content, baos); content.close(); String contentStr = new String(baos.toByteArray()); baos.close(); return contentStr; } // this version doesn't fully override the 'measureHashSpeed()' function, but // protects against it returning '0' by returning the set speed private class MyMockSystemMetrics extends MockSystemMetrics { public int measureHashSpeed(CachedUrlSetHasher hasher, MessageDigest digest) throws IOException { int speed = super.measureHashSpeed(hasher, digest); if (speed == 0) { speed = getHashSpeed(); if (speed <= 0) { throw new RuntimeException("No hash speed set."); } } return speed; } } public static void main(String[] argv) { String[] testCaseList = {FuncSimulatedContent.class.getName()}; junit.swingui.TestRunner.main(testCaseList); } public static Test suite() { return new TestSuite(FuncSimulatedContent.class); } }
public void testStatelessSearch() throws org.jzkit.configuration.api.ConfigurationException, org.jzkit.search.SearchException, org.jzkit.search.util.ResultSet.IRResultSetException, org.jzkit.search.util.QueryModel.InvalidQueryException { Logger log = Logger.getLogger(TestService.class.getName()); log.info("Starting jzkit2 server..."); RecordFormatSpecification request_spec = new ArchetypeRecordFormatSpecification("F"); ExplicitRecordFormatSpecification display_spec = new ExplicitRecordFormatSpecification("text:html:F"); ApplicationContext app_context = new ClassPathXmlApplicationContext("TestApplicationContext.xml"); log.info("JZKit server startup completed"); Vector collection_ids = new Vector(); collection_ids.add("LC/BOOKS"); QueryModel qm = new PrefixString("@attrset bib-1 @attr 1=4 Science"); System.err.println("Processing search......"); try { Map additional_properties = new HashMap(); additional_properties.put("base_dir", "/a/b/c/d"); StatelessQueryService stateless_query_service = (StatelessQueryService) app_context.getBean("StatelessQueryService"); org.jzkit.search.landscape.SimpleLandscapeSpecification landscape = new org.jzkit.search.landscape.SimpleLandscapeSpecification(collection_ids); // Test 1 - Kick off a search StatelessSearchResultsPageDTO rp = stateless_query_service.getResultsPageFor( null, qm, landscape, 1, 5, request_spec, display_spec, additional_properties); if (rp != null) { System.err.println( "Result Set Size....." + rp.total_hit_count + " records - result contains " + rp.number_of_records + " records"); System.err.println("Result Set ID : " + rp.result_set_id); } else { System.err.println("Results page was null"); } if (rp.records != null) { for (int i = 0; ((i < rp.records.length) && (i < 25)); i++) { System.err.println( "Getting next record (" + i + " out of " + rp.number_of_records + ")....."); InformationFragment frag = rp.records[i]; System.err.println(frag); } } // Test 2 - use the result set ID to get a page of requests rp = stateless_query_service.getResultsPageFor( rp.result_set_id, qm, landscape, 6, 5, request_spec, display_spec, additional_properties); if (rp.records != null) { for (int i = 0; ((i < rp.records.length) && (i < 25)); i++) { System.err.println( "Getting next record (" + i + " out of " + rp.number_of_records + ")....."); InformationFragment frag = rp.records[i]; System.err.println(frag); } } // Test 3 - Use the query to get a cache hit rp = stateless_query_service.getResultsPageFor( null, qm, landscape, 6, 5, request_spec, display_spec, additional_properties); if (rp.records != null) { for (int i = 0; ((i < rp.records.length) && (i < 25)); i++) { System.err.println( "Getting next record (" + i + " out of " + rp.number_of_records + ")....."); InformationFragment frag = rp.records[i]; System.err.println(frag); } } } catch (Exception e) { e.printStackTrace(); } }
/** * Performs testing of the basic instant messaging operation set. Tests include going over basic * functionality such as sending a message from the tested implementation and asserting reception by * the tester agent and vice versa. * * @author Emil Ivov */ public class TestOperationSetBasicInstantMessaging extends TestCase { private static final Logger logger = Logger.getLogger(TestOperationSetBasicInstantMessaging.class); private IcqSlickFixture fixture = new IcqSlickFixture(); private OperationSetBasicInstantMessaging opSetBasicIM = null; private OperationSetPresence opSetPresence = null; public TestOperationSetBasicInstantMessaging(String name) { super(name); } /** * Get a reference to the basic IM operation set. * * @throws Exception if this is not a good day. */ protected void setUp() throws Exception { super.setUp(); fixture.setUp(); Map supportedOperationSets = fixture.provider.getSupportedOperationSets(); if (supportedOperationSets == null || supportedOperationSets.size() < 1) throw new NullPointerException( "No OperationSet implementations are supported by " + "this ICQ implementation. "); // get the operation set presence here. opSetBasicIM = (OperationSetBasicInstantMessaging) supportedOperationSets.get(OperationSetBasicInstantMessaging.class.getName()); // if the op set is null then the implementation doesn't offer a typing. // operation set which is unacceptable for icq. if (opSetBasicIM == null) { throw new NullPointerException("No implementation for basic IM was found"); } // we also need the presence op set in order to retrieve contacts. opSetPresence = (OperationSetPresence) supportedOperationSets.get(OperationSetPresence.class.getName()); // if the op set is null show that we're not happy. if (opSetPresence == null) { throw new NullPointerException( "An implementation of the ICQ service must provide an " + "implementation of at least one of the PresenceOperationSets"); } } protected void tearDown() throws Exception { super.tearDown(); fixture.tearDown(); } /** * Creates a test suite containing tests of this class in a specific order. We'll first execute * tests beginning with the "test" prefix and then go to ordered tests.We first execture tests for * receiving messagese, so that a volatile contact is created for the sender. we'll then be able * to retrieve this volatile contact and send them a message on our turn. We need to do things * this way as the contact corresponding to the tester agent has been removed in the previous test * and we no longer have it in our contact list. * * @return Test a testsuite containing all tests to execute. */ public static Test suite() { TestSuite suite = new TestSuite(TestOperationSetBasicInstantMessaging.class); // the following 2 need to be run in the specified order. suite.addTest(new TestOperationSetBasicInstantMessaging("firstTestReceiveMessage")); suite.addTest(new TestOperationSetBasicInstantMessaging("thenTestSendMessage")); return suite; } /** * Send an instant message from the tested operation set and assert reception by the icq tester * agent. */ public void firstTestReceiveMessage() { String body = "This is an IM coming from the tester agent" + " on " + new Date().toString(); ImEventCollector evtCollector = new ImEventCollector(); // add a msg listener and register to the op set and send an instant // msg from the tester agent. opSetBasicIM.addMessageListener(evtCollector); fixture.testerAgent.sendMessage(fixture.ourUserID, body); evtCollector.waitForEvent(10000); opSetBasicIM.removeMessageListener(evtCollector); // assert reception of a message event assertTrue( "No events delivered upon a received message", evtCollector.collectedEvents.size() > 0); // assert event instance of Message Received Evt assertTrue( "Received evt was not an instance of " + MessageReceivedEvent.class.getName(), evtCollector.collectedEvents.get(0) instanceof MessageReceivedEvent); // assert source contact == testAgent.uin MessageReceivedEvent evt = (MessageReceivedEvent) evtCollector.collectedEvents.get(0); assertEquals( "message sender ", evt.getSourceContact().getAddress(), fixture.testerAgent.getIcqUIN()); // assert messageBody == body assertEquals("message body", body, evt.getSourceMessage().getContent()); } /** * Send an instant message from the tester agent and assert reception by the tested implementation */ public void thenTestSendMessage() { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); // create the message net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM.createMessage(body); // register a listener in the op set ImEventCollector imEvtCollector = new ImEventCollector(); opSetBasicIM.addMessageListener(imEvtCollector); // register a listener in the tester agent JoustSimMessageEventCollector jsEvtCollector = new JoustSimMessageEventCollector(); fixture.testerAgent.addConversationListener(fixture.ourUserID, jsEvtCollector); Contact testerAgentContact = opSetPresence.findContactByID(fixture.testerAgent.getIcqUIN()); opSetBasicIM.sendInstantMessage(testerAgentContact, msg); imEvtCollector.waitForEvent(10000); jsEvtCollector.waitForEvent(10000); fixture.testerAgent.removeConversationListener(fixture.ourUserID, jsEvtCollector); opSetBasicIM.removeMessageListener(imEvtCollector); // verify that the message delivered event was dispatched assertTrue( "No events delivered when sending a message", imEvtCollector.collectedEvents.size() > 0); assertTrue( "Received evt was not an instance of " + MessageDeliveredEvent.class.getName(), imEvtCollector.collectedEvents.get(0) instanceof MessageDeliveredEvent); MessageDeliveredEvent evt = (MessageDeliveredEvent) imEvtCollector.collectedEvents.get(0); assertEquals( "message destination ", evt.getDestinationContact().getAddress(), fixture.testerAgent.getIcqUIN()); assertSame("source message", msg, evt.getSourceMessage()); // verify that the message has successfully arived at the destination assertTrue( "No messages received by the tester agent", jsEvtCollector.collectedMessageInfo.size() > 0); String receivedBody = ((MessageInfo) jsEvtCollector.collectedMessageInfo.get(0)).getMessage().getMessageBody(); assertEquals("received message body", msg.getContent(), receivedBody); } /** Creates an Message through the simple createMessage() method and inspects its parameters. */ public void testCreateMessage1() { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM.createMessage(body); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes", Arrays.equals(body.getBytes(), msg.getRawData())); assertEquals("message length", body.length(), msg.getSize()); assertEquals( "message content type", OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, msg.getContentType()); assertEquals( "message encoding", OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); // a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals(msg2.getMessageUID())); } /** Creates an Message through the advance createMessage() method and inspects its parameters. */ public void testCreateMessage2() { String body = "This is an IM coming from the tested implementation" + " on " + new Date().toString(); String contentType = "text/html"; String encoding = "UTF-16"; String subject = "test message"; net.java.sip.communicator.service.protocol.Message msg = opSetBasicIM.createMessage(body.getBytes(), contentType, encoding, subject); assertEquals("message body", body, msg.getContent()); assertTrue("message body bytes", Arrays.equals(body.getBytes(), msg.getRawData())); assertEquals("message length", body.length(), msg.getSize()); assertEquals("message content type", contentType, msg.getContentType()); assertEquals("message encoding", encoding, msg.getEncoding()); assertNotNull("message uid", msg.getMessageUID()); // a further test on message uid. net.java.sip.communicator.service.protocol.Message msg2 = opSetBasicIM.createMessage(body); assertFalse("message uid", msg.getMessageUID().equals(msg2.getMessageUID())); } /** Collects instant messaging events. */ private class ImEventCollector implements MessageListener { private List collectedEvents = new LinkedList(); /** * Called when a new incoming <tt>Message</tt> has been received. * * @param evt the <tt>MessageReceivedEvent</tt> containing the newly received message, its * sender and other details. */ public void messageReceived(MessageReceivedEvent evt) { logger.debug("Received a MessageReceivedEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Called to indicated that delivery of a message sent earlier has failed. Reason code and * phrase are contained by the <tt>MessageFailedEvent</tt> * * @param evt the <tt>MessageFailedEvent</tt> containing the ID of the message whose delivery * has failed. */ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) { logger.debug("Received a MessageDeliveryFailedEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Called when the underlying implementation has received an indication that a message, sent * earlier has been successfully received by the destination. * * @param evt the MessageDeliveredEvent containing the id of the message that has caused the * event. */ public void messageDelivered(MessageDeliveredEvent evt) { logger.debug("Received a MessageDeliveredEvent: " + evt); synchronized (this) { collectedEvents.add(evt); notifyAll(); } } /** * Blocks until at least one event is received or until waitFor miliseconds pass (whichever * happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedEvents.size() > 0) return; try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a message evt", ex); } } } } /** The oscar.jar lib sends us typing events through this listener. */ private class JoustSimMessageEventCollector implements ConversationListener { private List collectedMessageInfo = new LinkedList(); /** * Adds <tt>minfo</tt> into the list of collected messages. * * @param c Conversation * @param minfo MessageInfo */ public void gotMessage(Conversation c, MessageInfo minfo) { logger.debug("Message: [" + minfo.getMessage() + "] received from: " + c.getBuddy()); synchronized (this) { collectedMessageInfo.add(minfo); notifyAll(); } } /** * Blocks until at least one event is received or until waitFor miliseconds pass (whicever * happens first). * * @param waitFor the number of miliseconds that we should be waiting for an event before simply * bailing out. */ public void waitForEvent(long waitFor) { synchronized (this) { if (collectedMessageInfo.size() > 0) { logger.trace("evt already received. " + collectedMessageInfo); return; } try { wait(waitFor); } catch (InterruptedException ex) { logger.debug("Interrupted while waiting for a subscription evt", ex); } } } // the follwoing methods only have dummy implementations here as they // do not interest us. complete implementatios are provider in the // basic instant messaging operation set. public void buddyInfoUpdated(IcbmService service, Screenname buddy, IcbmBuddyInfo info) {} public void conversationClosed(Conversation c) {} public void gotOtherEvent(Conversation conversation, ConversationEventInfo event) {} public void sentOtherEvent(Conversation conversation, ConversationEventInfo event) {} public void canSendMessageChanged(Conversation c, boolean canSend) {} public void conversationOpened(Conversation c) {} public void newConversation(IcbmService service, Conversation conv) {} public void sentMessage(Conversation c, MessageInfo minfo) {} } /** * A method that would simply send messages to a group of people so that they would get notified * that tests are being run. */ public void testSendFunMessages() { String hostname = ""; try { hostname = java.net.InetAddress.getLocalHost().getHostName() + ": "; } catch (UnknownHostException ex) { } String message = hostname + "Hello this is the SIP Communicator (version " + System.getProperty("sip-communicator.version") + ") build on: " + new Date().toString() + ". Have a very nice day!"; String list = System.getProperty("accounts.reporting.ICQ_REPORT_LIST"); logger.debug("Will send message " + message + " to: " + list); // if no property is specified - return if (list == null || list.trim().length() == 0) return; StringTokenizer tokenizer = new StringTokenizer(list, " "); while (tokenizer.hasMoreTokens()) { fixture.testerAgent.sendMessage(tokenizer.nextToken(), message); } } /** Tests whether there is a offline message received and whether is the one we have send */ public void testReceiveOfflineMessages() { String messageText = fixture.offlineMsgCollector.getMessageText(); Message receiveMessage = fixture.offlineMsgCollector.getReceivedMessage(); assertNotNull("No Offline messages have been received", receiveMessage); assertEquals("message body", messageText, receiveMessage.getContent()); } }
public class CodingTest extends TestCase { private static final Logger LOG = Logger.getLogger(CodingTest.class.getName()); /** * Constructor for this unit test. * * @param testName the name of the unit test */ public CodingTest(String testName) { super(testName); } /** * Allows unit tests to be run together in a suite. * * @return a test suite that contains a single test - this one */ public static Test suite() { return new TestSuite(CodingTest.class); } /** * Allows test to be run stand-alone from the command-line. * * <p>java -Djava.library.path=/opt/honeycomb/lib -classpath * test/lib/junit-3.8.1.jar:test/classes:classes com.sun.honeycomb.coding.CodingTest */ public static void main(String args[]) { junit.textui.TestRunner.run(suite()); } public void setUp() {} public void tearDown() {} public void testByteBufferCoder() { Persistent3 three = new Persistent3( 10, (float) 4.444, 555555555555L, true, "this is the fourth persistent string", new Date(), new byte[] {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, null); Persistent2 two = new Persistent2( 1, (float) 2.222, 333333333333L, false, "this is the first persistent string", new Date(), new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, three, 4, "this is the second persistent string", (ByteBuffer) ByteBuffer.allocateDirect(17).putInt(1234).rewind()); Persistent1 one = new Persistent1( 2, (float) 3.333, 4444444444444L, true, "this is the third persistent string", new Date(), new byte[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, two); ByteBuffer buffer = ByteBuffer.allocateDirect(8 * 1024); ByteBufferCoder encoder = new ByteBufferCoder(buffer, true); encoder.encodeCodable(one); buffer.rewind(); ByteBufferCoder decoder = new ByteBufferCoder(buffer, true, new Delegate()); Persistent1 anotherOne = (Persistent1) decoder.decodeCodable(); if (!one.equals(anotherOne)) { fail("unarchived object with type checking does not equal archived one"); } buffer.clear(); encoder = new ByteBufferCoder(buffer, false); encoder.encodeCodable(one); buffer.rewind(); decoder = new ByteBufferCoder(buffer, false, new Delegate()); anotherOne = (Persistent1) decoder.decodeCodable(); if (!one.equals(anotherOne)) { fail("unarchived object without type checking does not equal archived one"); } } public static class Persistent1 implements Codable, Serializable { private int int1; private float float1; private long long1; private boolean boolean1; private String string1; private Date date1; private byte[] bytes1; private Codable codable1; public Persistent1() {} public Persistent1( int newInt, float newFloat, long newLong, boolean newBoolean, String newString, Date newDate, byte[] newBytes, Codable newCodable) { int1 = newInt; float1 = newFloat; long1 = newLong; boolean1 = newBoolean; string1 = newString; date1 = newDate; bytes1 = newBytes; codable1 = newCodable; } public void encode(Encoder encoder) { encoder.encodeInt(int1); encoder.encodeFloat(float1); encoder.encodeLong(long1); encoder.encodeBoolean(boolean1); encoder.encodeString(string1); encoder.encodeDate(date1); encoder.encodeBytes(bytes1); encoder.encodeCodable(codable1); } public void decode(Decoder decoder) { int1 = decoder.decodeInt(); float1 = decoder.decodeFloat(); long1 = decoder.decodeLong(); boolean1 = decoder.decodeBoolean(); string1 = decoder.decodeString(); date1 = decoder.decodeDate(); bytes1 = decoder.decodeBytes(); codable1 = decoder.decodeCodable(); } public boolean equals(Object other) { Persistent1 otherPersistent1 = (Persistent1) other; if (int1 != otherPersistent1.int1) { System.out.println("int1 failed"); return false; } if (float1 != otherPersistent1.float1) { System.out.println("float1 failed"); return false; } if (long1 != otherPersistent1.long1) { System.out.println("long1 failed"); return false; } if (boolean1 != otherPersistent1.boolean1) { System.out.println("boolean1 failed"); return false; } if (string1 != otherPersistent1.string1 && (string1 != null && !string1.equals(otherPersistent1.string1) && otherPersistent1.string1 != null)) { System.out.println("string1 failed"); return false; } if (date1 != otherPersistent1.date1 && (date1 != null && !date1.equals(otherPersistent1.date1) && otherPersistent1.date1 != null)) { System.out.println("date1 failed"); return false; } if (bytes1 != otherPersistent1.bytes1 && (bytes1 != null && !Arrays.equals(bytes1, otherPersistent1.bytes1) && otherPersistent1.bytes1 != null)) { System.out.println("bytes1 failed"); return false; } if (codable1 != otherPersistent1.codable1 && (codable1 != null && !codable1.equals(otherPersistent1.codable1) && otherPersistent1.codable1 != null)) { System.out.println("codable1 failed"); return false; } return true; } } private static class Persistent2 extends Persistent1 { private int int2; private String string2; private ByteBuffer buffer2; public Persistent2() {} public Persistent2( int newInt, float newFloat, long newLong, boolean newBoolean, String newString, Date newDate, byte[] newBytes, Codable newCodable, int newInt2, String newString2, ByteBuffer newBuffer2) { super(newInt, newFloat, newLong, newBoolean, newString, newDate, newBytes, newCodable); int2 = newInt2; string2 = newString2; buffer2 = newBuffer2; } public void encode(Encoder encoder) { super.encode(encoder); encoder.encodeInt(int2); encoder.encodeString(string2); encoder.encodeInt(buffer2.remaining()); encoder.encodeKnownLengthBuffer(buffer2); } public void decode(Decoder decoder) { super.decode(decoder); int2 = decoder.decodeInt(); string2 = decoder.decodeString(); int length = decoder.decodeInt(); buffer2 = decoder.decodeKnownLengthBuffer(length, true); } public boolean equals(Object other) { if (!super.equals(other)) { return false; } Persistent2 otherPersistent2 = (Persistent2) other; if (int2 != otherPersistent2.int2) { System.out.println("int2 failed"); return false; } if (string2 != otherPersistent2.string2 && (string2 != null && !string2.equals(otherPersistent2.string2) && otherPersistent2.string2 != null)) { System.out.println("string2 failed"); return false; } if (buffer2 != otherPersistent2.buffer2 && (buffer2 != null && !buffer2.equals(otherPersistent2.buffer2) && otherPersistent2.buffer2 != null)) { System.out.println("buffer2 failed"); return false; } return true; } } static class Persistent3 extends Persistent1 { Persistent3() {} Persistent3( int newInt, float newFloat, long newLong, boolean newBoolean, String newString, Date newDate, byte[] newBytes, Codable newCodable) { super(newInt, newFloat, newLong, newBoolean, newString, newDate, newBytes, newCodable); } } static class Delegate implements Decoder.Delegate { public Codable newInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException { return (Codable) Class.forName(className).newInstance(); } } }