/*
* 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.contactlist;
import java.util.*;
import junit.framework.*;
import net.java.sip.communicator.impl.protocol.mock.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import org.osgi.framework.*;
/**
* Tests in this class verify whether storing and reloading the meta contact
* list after killing the meta contact list bundle work well.
* @author Emil Ivov
*/
public class TestMetaContactListPersistence extends TestCase
{
/**
* A reference to the SLICK fixture.
*/
private MclSlickFixture fixture = new MclSlickFixture(getClass().getName());
public TestMetaContactListPersistence(String name)
{
super(name);
}
@Override
protected void setUp() throws Exception
{
super.setUp();
fixture.setUp();
}
@Override
protected void tearDown() throws Exception
{
fixture.tearDown();
fixture = null;
super.tearDown();
}
/**
* Returns tests in this class in the order that they are supposed to be
* executed.
* @return a Test suite containing tests in this class in the order they are
* to be executed.
*/
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new TestMetaContactListPersistence(
"testCreateAndMoveMetaContact"));
suite.addTest(new TestMetaContactListPersistence(
"testReloadMetaContactListBundle"));
suite.addTest( new TestMetaContactListPersistence(
"testPartialContactListRestauration"));
suite.addTest( new TestMetaContactListPersistence(
"testCompleteContactListRestauration"));
suite.addTest( new TestMetaContactListPersistence(
"testPurgeLocalContactListCopy"));
return suite;
}
/**
* In this test we only create a meta contact and move it somewhere else.
* This is a delicate operation since any underlying storage method would
* have to not only move the meta contact itself but also make sure that all
* proto contacts have been moved to protogroups accordingly. We don't do
* any real testing inside this method. The testing would be happening
* during reload and it would fail if the contacts moved in this method
* were not properly moved in the underlying storage utilities.
*/
public void testCreateAndMoveMetaContact()
{
String newContactID ="testCreateAndMoveMetaContact.ContactID";
MetaContactGroup parentMetaGroup
= fixture.metaClService.getRoot().getMetaContactSubgroup(
MetaContactListServiceLick.topLevelGroupName);
//create a new metacontact and, hence mock contact, in the meta
//"SomePeople" non-toplevel group
fixture.metaClService.createMetaContact(MclSlickFixture.mockProvider
, parentMetaGroup
, newContactID);
//check that the contact has been successfully created in the meta cl
MetaContact newMetaContact
= parentMetaGroup.getMetaContact(
MclSlickFixture.mockProvider,
newContactID);
assertNotNull("create failed. couldn't find the new contact."
, newMetaContact);
//move the meta contact somewhere else
fixture.metaClService.moveMetaContact(
newMetaContact, fixture.metaClService.getRoot());
}
/**
* Uninstalls the meta contact list bundle so that it would be forced to
* persistently store its contents and load it again later.
*
* @throws java.lang.Exception in case stopping or uninstalling the bundle
* fails.
*/
public void testReloadMetaContactListBundle()
throws Exception
{
Object o = new Object();
synchronized(o){
// wait other operations to finish before reloading
o.wait(1000);
}
Bundle metaClBundle = findMetaClBundle();
//uninstall the meta contact list service
assertNotNull("Couldn't find the bundle that exports the meta "
+ "contact list servce implementation that we're "
+ "currently testing"
, metaClBundle);
metaClBundle.stop();
assertTrue("Couldn't stop the meta cl bundle. State was "
+ metaClBundle.getState()
, Bundle.ACTIVE != metaClBundle.getState()
&& Bundle.STOPPING != metaClBundle.getState());
metaClBundle.uninstall();
assertEquals("Couldn't stop the meta cl bundle."
, Bundle.UNINSTALLED, metaClBundle.getState());
//unregister all mock providers
MclSlickFixture.mockPrServiceRegistration.unregister();
MclSlickFixture.mockP1ServiceRegistration.unregister();
MclSlickFixture.mockP2ServiceRegistration.unregister();
//remove existing mock providers.
MclSlickFixture.replacementMockPr = new MockProvider(
MclSlickFixture.mockProvider.getAccountID().getUserID());
MclSlickFixture.replacementMockP1 = new MockProvider(
MclSlickFixture.mockP1.getAccountID().getUserID());
MclSlickFixture.replacementMockP2 = new MockProvider(
MclSlickFixture.mockP2.getAccountID().getUserID());
//reinstall only one of the existing mock providers
//we will reinstall the other mock providers later. our purpose is to
//verify that the contact list would only reload contacts for the
//re-registered mock provider upon startup and that it would later
//complete its list with the rest of the mock providers once we
//reregister them.
MclSlickFixture.mockPrServiceRegistration = MetaContactListServiceLick
.registerMockProviderService(MclSlickFixture.replacementMockPr);
//reinstall the metacontactlist bundle
metaClBundle = MclSlickFixture.bundleContext.installBundle(
metaClBundle.getLocation());
assertEquals("Couldn't re-install meta cl bundle."
, Bundle.INSTALLED, metaClBundle.getState());
metaClBundle.start();
assertEquals("Couldn't re-start meta cl bundle."
, Bundle.ACTIVE, metaClBundle.getState());
fixture.metaClService
= (MetaContactListService)
MclSlickFixture.bundleContext.getService(
MclSlickFixture.bundleContext.getServiceReference(
MetaContactListService.class.getName()));
assertNotNull("The meta contact list service was not re-registered "
+"after reinstalling its bundle."
, fixture.metaClService);
}
/**
* Tests whether the freshly reloaded meta contact list has properly
* reloaded contacts for the provider that was registered at the time of its
* re-installation
*/
public void testPartialContactListRestauration()
{
//verify that contents of the meta contact list matches contents of
//the mock provider we removed.
ContactGroup oldProtoRoot =
MclSlickFixture.mockProvider
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
MclSlickFixture.assertGroupEquals(
(MockContactGroup)oldProtoRoot
, fixture.metaClService.getRoot()
, true);//we might have trailing empty meta groups here remaining
//from previous testing so ignore them.
//verify that the new mock provider has created unresolved contacts
//for all contacts in the meta cl.
ContactGroup newProtoRoot =
MclSlickFixture.replacementMockPr
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
assertEquals("Newly loaded provider does not match the old one."
, oldProtoRoot
, newProtoRoot);
//verify that all contacts in the replacement provider are unresolved
//as otherwise this would mean that the meta contact list has not
//used the createUnresolvedContact() when creating them.
Iterator<ContactGroup> subgroups = newProtoRoot.subgroups();
while(subgroups.hasNext())
{
assertUnresolvedContents( subgroups.next() );
}
}
/**
* Register the remaining protocol providers and make sure that they too are
* properly loaded inside the contact list. We also need to verify that
* proto contacts that have been merged in a single meta contact are still
* merged.
*/
public void testCompleteContactListRestauration()
{
//reinstall remaining mock providers
//we will reinstall the other mock providers later. our purpose is to
MclSlickFixture.mockP1ServiceRegistration = MetaContactListServiceLick
.registerMockProviderService(MclSlickFixture.replacementMockP1);
MclSlickFixture.mockP2ServiceRegistration = MetaContactListServiceLick
.registerMockProviderService(MclSlickFixture.replacementMockP2);
//Get references to the root groups of the 2 providers we removed
ContactGroup oldProtoMockP1Root =
MclSlickFixture.mockP1
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
ContactGroup oldProtoMockP2Root =
MclSlickFixture.mockP2
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
//verify that contacts tnat unresolved contacts that have been created
//inside that the replacement mock providers match those in the
//providers we removed.
ContactGroup newProtoMockP1Root =
MclSlickFixture.replacementMockP1
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
assertEquals("Newly loaded provider does not match the old one."
, oldProtoMockP1Root
, newProtoMockP1Root);
ContactGroup newProtoMockP2Root =
MclSlickFixture.replacementMockP2
.getOperationSet(OperationSetPersistentPresence.class)
.getServerStoredContactListRoot();
assertEquals("Newly loaded provider does not match the old one."
, oldProtoMockP2Root
, newProtoMockP2Root);
//verify that all contacts in the replacement providers are unresolved
//as otherwise this would mean that the meta contact list has not
//used the createUnresolvedContact() when creating them.
Iterator<ContactGroup> subgroups = newProtoMockP1Root.subgroups();
while(subgroups.hasNext())
{
assertUnresolvedContents( subgroups.next() );
}
subgroups = newProtoMockP2Root.subgroups();
while(subgroups.hasNext())
{
assertUnresolvedContents( subgroups.next() );
}
}
/**
* Traverses all contacts and groups of <tt>root</tt> and throws a failure
* exception the moment if finds one of them not to be unresolved.
*
* @param root the contact group where the recursive assertion should begin
*/
private void assertUnresolvedContents(ContactGroup root)
{
assertEquals("isResolved for grp:" + root.getGroupName()
, false, root.isResolved());
// verify all contacts
Iterator<Contact> contacts = root.contacts();
while(contacts.hasNext())
{
Contact contact = contacts.next();
assertEquals("isResolved for contact:" + contact.getDisplayName()
, false, contact.isResolved());
}
//recurse all subgroups
Iterator<ContactGroup> subgroups = root.subgroups();
while(subgroups.hasNext()){
assertUnresolvedContents(subgroups.next());
}
}
/**
* Removes the locally stored contact list copy. The purpose of this is to
* leave the local list empty for a next round of testing.
*/
public void testPurgeLocalContactListCopy()
{
fixture.metaClService.purgeLocallyStoredContactListCopy();
}
/**
* Returns the bundle that has registered the meta contact list service
* implementation that we're currently testing. The method would go through
* all bundles currently installed in the framework and return the first
* one that exports the same meta cl instance as the one we use in this
* slick.
* @return the Bundle that has registered the meta contact list service
* we're using in the slick.
*/
private Bundle findMetaClBundle()
{
Bundle[] bundles = MclSlickFixture.bundleContext.getBundles();
for (int i = 0; i < bundles.length; i++)
{
ServiceReference[] registeredServices
= bundles[i].getRegisteredServices();
if(registeredServices == null)
continue;
for (int j = 0; j < registeredServices.length; j++)
{
Object service
= MclSlickFixture.bundleContext.getService(
registeredServices[j]);
if(service == fixture.metaClService)
return bundles[i];
}
}
return null;
}
}