From a479127e7334b77d0f0d5e75e1ecd24009d3f296 Mon Sep 17 00:00:00 2001 From: Emil Ivov Date: Fri, 2 Mar 2007 21:39:56 +0000 Subject: [PATCH] gibberish slck (Issue #241) and a better meta contact list ordering policy (Issue #316) tests for TestOperationSetPersistentPresenceGibberishImpl --- .../TestOperationSetPersistentPresence.java | 690 ++++++++++++++++++ 1 file changed, 690 insertions(+) create mode 100644 test/net/java/sip/communicator/slick/protocol/gibberish/TestOperationSetPersistentPresence.java diff --git a/test/net/java/sip/communicator/slick/protocol/gibberish/TestOperationSetPersistentPresence.java b/test/net/java/sip/communicator/slick/protocol/gibberish/TestOperationSetPersistentPresence.java new file mode 100644 index 000000000..e97f4ab37 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/gibberish/TestOperationSetPersistentPresence.java @@ -0,0 +1,690 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.slick.protocol.gibberish; + +import java.util.*; + +import junit.framework.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; + +/** + * 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; + } + + protected void setUp() throws Exception + { + super.setUp(); + fixture.setUp(); + + Map 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 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"); + } + + 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 expectedContactList = fixture.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 groups = rootGroup.subgroups(); + while (groups.hasNext() ) + { + ContactGroup group = (ContactGroup)groups.next(); + + List expectedContactsInGroup + = (List)expectedContactList.get(group.getGroupName()); + + // When sending the offline message + // the sever creates a group NotInContactList, + // beacuse 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 contactsIter = group.contacts(); + while(contactsIter.hasNext()) + { + String contactID = ((Contact)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); + + //create the group + opSetPersPresence1.removeServerStoredContactGroup( + opSetPersPresence1.getServerStoredContactListRoot() + .getGroup(testGroupName2)); + + 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 contactListToCreate = new Hashtable(); + + //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 uinInThisGroup = (List)contactListToCreate.get(groupName); + if (uinInThisGroup == null) + { + uinInThisGroup = new ArrayList(); + contactListToCreate.put(groupName, uinInThisGroup); + } + + uinInThisGroup.add(uin); + } + + // now init the list + Enumeration newGroupsEnum = contactListToCreate.keys(); + + //go over all groups in the contactsToAdd table + while (newGroupsEnum.hasMoreElements()) + { + String groupName = (String) newGroupsEnum.nextElement(); + logger.debug("Will add group " + groupName); + + opSetPersPresence1.createServerStoredContactGroup( + opSetPersPresence1.getServerStoredContactListRoot(), groupName); + + ContactGroup newlyCreatedGroup = + opSetPersPresence1.getServerStoredContactListRoot().getGroup(groupName); + + Iterator contactsToAddToThisGroup + = ( (List) contactListToCreate.get(groupName)).iterator(); + while (contactsToAddToThisGroup.hasNext()) + { + String id = (String) 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 + * ServerStoredGroupListeners. + */ + private class GroupChangeCollector implements ServerStoredGroupListener + { + public ArrayList collectedEvents = new ArrayList(); + + /** + * 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 collectedEvents = new ArrayList(); + + /** + * 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) + { + 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(); + } + } + + } +}