/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.slick.protocol.icq;
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.*;
/**
* @todo describe
*
* @todo testing here would probably be best done if we could first log in
* with one of the agents retrieve the contact list and then check that we
* have the same thing with the other agent
*
* @author Emil Ivov
* @author Damian Minkov
*/
public class TestOperationSetPersistentPresence
extends TestCase
{
private static final Logger logger =
Logger.getLogger(TestOperationSetPersistentPresence.class);
private IcqSlickFixture fixture = new IcqSlickFixture();
private OperationSetPersistentPresence opSetPersPresence = 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(TestOperationSetPersistentPresence.class);
//the following 2 need to be run in the specified order.
//(postTestRemoveGroup() needs the group created from
//postTestCreateGroup() )
suite.addTest(
new TestOperationSetPersistentPresence("postTestCreateGroup"));
// suite.addTest( new TestOperationSetPersistentPresence(
// "postTestPersistentSubscribe"));
// suite.addTest( new TestOperationSetPersistentPresence(
// "postTestPersistentUnsubscribe"));
//rename
suite.addTest( new TestOperationSetPersistentPresence(
"postTestRenameGroup"));
suite.addTest(
new TestOperationSetPersistentPresence("postTestRemoveGroup"));
return suite;
}
@Override
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.
opSetPersPresence =
(OperationSetPersistentPresence)supportedOperationSets.get(
OperationSetPersistentPresence.class.getName());
//if still null then the implementation doesn't offer a presence
//operation set which is unacceptable for icq.
if (opSetPersPresence == null)
throw new NullPointerException(
"An implementation of the ICQ 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 icqTesterAgent.
*/
public void testRetrievingServerStoredContactList()
{
ContactGroup rootGroup
= opSetPersPresence.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
= IcqSlickFixture.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,
// beacuse the buddy we are sending message to is not in
// the contactlist. So this group must be ignored
// all not persistent groups must be ignored
if(group.isPersistent())
{
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 IcqTesterAgent 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());
}
/**
* Adds the a contact to a group in our contact list. Verifies that event
* dispatching goes ok. Makes sure that the contact is where it is supposed
* to be.
* <p>
* Note that the method won't be testing presence event notifications since
* these are being tested in TestOperationSetPresence.
*
* @throws java.lang.Exception in case network operations fail.
*/
public void postTestPersistentSubscribe()
throws Exception
{
logger.trace("Testing persistent subscriptions.");
//find the group where we'll be adding the new contact
ContactGroup group = opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName);
//register a subscription event listener
SubscriptionEventCollector evtCollector
= new SubscriptionEventCollector();
opSetPersPresence.addSubscriptionListener(evtCollector);
//create the subscription and wait for a confirmation event.
opSetPersPresence.subscribe(group, "38687470");
evtCollector.waitForEvent(10000);
opSetPersPresence.removeSubscriptionListener(evtCollector);
//make sure the event delivery went as expected
assertEquals("Number of dispatched events",
1, evtCollector.collectedEvents.size());
assertEquals(
"The SubscriptionEvent had a wrong event id.",
SubscriptionEvent.SUBSCRIPTION_CREATED,
((SubscriptionEvent)evtCollector.collectedEvents.get(0)).getEventID());
assertEquals(
"The parent group in the subscription event did not match.",
group, ((SubscriptionEvent)evtCollector.collectedEvents.get(0))
.getParentGroup());
Contact contact = group.getContact(IcqSlickFixture.testerAgent.getIcqUIN());
//make sure that the contact appears in the new group.
assertNotNull("Couldn't find contact where we created it", contact);
}
/**
* Removes a contact from a group in our contact list. Verifies that event
* dispatching goes ok. Makes sure that the contact is not in the group
* any more.
* <p>
* Note that the method won't be testing presence event notifications since
* these are being tested in TestOperationSetPresence.
*
* @throws java.lang.Exception in case network operations fail.
*/
public void postTestPersistentUnsubscribe()
throws Exception
{
logger.trace("Testing removal of persistent subscriptions.");
//find the group where we'll be adding the new contact
ContactGroup group = opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName);
Contact contact = group.getContact(IcqSlickFixture.testerAgent.getIcqUIN());
//register a subscription event listener
SubscriptionEventCollector evtCollector
= new SubscriptionEventCollector();
opSetPersPresence.addSubscriptionListener(evtCollector);
//remove the subscription and wait for a confirmation event.
opSetPersPresence.unsubscribe(contact);
evtCollector.waitForEvent(10000);
opSetPersPresence.removeSubscriptionListener(evtCollector);
//make sure the event delivery went as expected
assertEquals("Number of dispatched events",
1, evtCollector.collectedEvents.size());
assertEquals(
"The SubscriptionEvent had a wrong event id.",
SubscriptionEvent.SUBSCRIPTION_REMOVED,
((SubscriptionEvent)evtCollector.collectedEvents.get(0)).getEventID());
assertEquals(
"The parent group in the subscription event did not match.",
group, ((SubscriptionEvent)evtCollector.collectedEvents.get(0))
.getParentGroup());
contact = group.getContact(IcqSlickFixture.testerAgent.getIcqUIN());
//make sure that the contact is not in the group any more.
assertNull("A contact was still present after removing its "
+"corresponding subscription", contact);
}
/**
* 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.
*/
public void postTestCreateGroup()
{
logger.trace("testing creation of server stored groups");
//first add a listener
GroupChangeCollector groupChangeCollector = new GroupChangeCollector();
opSetPersPresence
.addServerStoredGroupChangeListener(groupChangeCollector);
//create the group
try
{
opSetPersPresence.createServerStoredContactGroup(
opSetPersPresence.getServerStoredContactListRoot(),
testGroupName);
}
catch (OperationFailedException ex)
{
fail("Cannot create group " + ex.getMessage());
}
groupChangeCollector.waitForEvent(10000);
opSetPersPresence
.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 = opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName);
assertNotNull("A newly created group was not in the contact list.",
group);
assertEquals("New group name", testGroupName, group.getGroupName());
}
/**
* 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();
opSetPersPresence
.addServerStoredGroupChangeListener(groupChangeCollector);
try
{
// remove the group
opSetPersPresence.removeServerStoredContactGroup(
opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName2));
}
catch(OperationFailedException ex)
{
logger.error("error removing group", ex);
}
groupChangeCollector.waitForEvent(10000);
opSetPersPresence
.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 = opSetPersPresence.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 = opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName);
//first add a listener
GroupChangeCollector groupChangeCollector = new GroupChangeCollector();
opSetPersPresence
.addServerStoredGroupChangeListener(groupChangeCollector);
//change the name and wait for a confirmation event
opSetPersPresence.renameServerStoredContactGroup(group, testGroupName2);
groupChangeCollector.waitForEvent(10000);
opSetPersPresence
.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 = opSetPersPresence.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 = opSetPersPresence.getServerStoredContactListRoot()
.getGroup(testGroupName2);
assertNotNull("Could not find a renamed group by its new name.",
newGroup);
}
/**
* 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)
{
logger.trace("ServerStoredGroupEvent already received. " + collectedEvents);
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
* 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();
}
}
}
}