package org.limewire.xmpp.client.impl;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import org.limewire.friend.api.FileMetaData;
import org.limewire.friend.api.FriendConnection;
import org.limewire.friend.api.FriendConnectionConfiguration;
import org.limewire.friend.api.FriendException;
import org.limewire.friend.api.FriendPresence;
import org.limewire.friend.api.MessageWriter;
import org.limewire.friend.api.feature.AddressFeature;
import org.limewire.friend.api.feature.AuthTokenFeature;
import org.limewire.friend.api.feature.FeatureTransport;
import org.limewire.friend.api.feature.FileOfferFeature;
import org.limewire.friend.api.feature.LimewireFeature;
import org.limewire.friend.impl.FileMetaDataImpl;
import org.limewire.friend.impl.FileMetaDataImpl.Element;
import org.limewire.friend.impl.address.FriendAddress;
import org.limewire.friend.impl.address.FriendAddressRegistry;
import org.limewire.inject.AbstractModule;
import org.limewire.io.Connectable;
import org.limewire.io.ConnectableImpl;
import org.limewire.lifecycle.ServiceRegistry;
import org.limewire.net.address.AddressEvent;
import org.xmlpull.v1.XmlPullParserException;
import com.google.inject.Injector;
import com.google.inject.Module;
public class XMPPServiceTest extends XmppBaseTestCase {
private static final String USERNAME_1 = "automatedtestfriend1@gmail.com";
private static final String USERNAME_2 = "automatedtestfriend2@gmail.com";
private static final String PASSWORD_1 = "automatedtestfriend123";
private static final String PASSWORD_2 = "automatedtestfriend234";
private RosterListenerMock aliceRosterListener;
private RosterListenerMock bobRosterListener;
private FileOfferHandlerMock fileOfferHandler;
private FriendConnection friendConnectionAlice;
private FriendConnection friendConnectionBob;
public XMPPServiceTest(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
aliceRosterListener = new RosterListenerMock();
bobRosterListener = new RosterListenerMock();
FriendConnectionConfiguration alice = new FriendConnectionConfigurationMock(USERNAME_1, PASSWORD_1,
SERVICE, aliceRosterListener);
FriendConnectionConfiguration bob = new FriendConnectionConfigurationMock(USERNAME_2, PASSWORD_2,
SERVICE, bobRosterListener);
friendConnectionAlice = factories[0].login(alice).get();
friendConnectionBob = factories[1].login(bob).get();
// Allow login, roster, presence, library messages to be sent, received
Thread.sleep(SLEEP * 2); // TODO wait()/notify()
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
assertEquals(0, aliceRosterListener.getRosterSize());
assertEquals(0, bobRosterListener.getRosterSize());
}
@Override
protected List<Module> getServiceModules() {
List<Module> defaultServiceModules = super.getServiceModules();
List<Module> serviceModules = new ArrayList<Module>();
fileOfferHandler = new FileOfferHandlerMock();
serviceModules.add(new AbstractModule() {
@Override
protected void configure() {
bind(FileOfferHandlerMock.class).toInstance(fileOfferHandler);
}
});
serviceModules.addAll(defaultServiceModules);
return serviceModules;
}
/**
* Tests that two friends can see each other
*/
public void testRosterIsPopulated() throws InterruptedException, UnknownHostException {
assertEquals(1, aliceRosterListener.getRosterSize());
assertEquals(USERNAME_2, aliceRosterListener.getFirstRosterEntry());
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
assertEquals(1, bobRosterListener.getRosterSize());
assertEquals(USERNAME_1, bobRosterListener.getFirstRosterEntry());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
}
/**
* Tests that a friend can be renamed in the roster
*/
public void testSetName() throws InterruptedException {
// Reset the name first, in case a previous test left it as "foo"
aliceRosterListener.getUser(USERNAME_2).setName("buddy2");
Thread.sleep(SLEEP);
assertEquals("buddy2", aliceRosterListener.getUser(USERNAME_2).getName());
aliceRosterListener.getUser(USERNAME_2).setName("foo");
Thread.sleep(SLEEP);
assertEquals("foo", aliceRosterListener.getUser(USERNAME_2).getName());
aliceRosterListener.getUser(USERNAME_2).setName("buddy2");
}
/**
* Tests that friends logged in through LimeWire can detect each other
* and exchange addresses
*/
public void testAddresses() throws InterruptedException, UnknownHostException {
assertEquals(1, aliceRosterListener.getRosterSize());
assertEquals(USERNAME_2, aliceRosterListener.getFirstRosterEntry());
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
assertEquals(1, bobRosterListener.getRosterSize());
assertEquals(USERNAME_1, bobRosterListener.getFirstRosterEntry());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
// send address update of Bob's address
AddressEventTestBroadcaster addressEventBroadcaster = getAddressBroadcaster(injectors[1]);
addressEventBroadcaster.listeners.broadcast(new AddressEvent(new ConnectableImpl("199.199.199.199", 2048, true),
AddressEvent.Type.ADDRESS_CHANGED));
// send address update of Alices's address
addressEventBroadcaster = getAddressBroadcaster(injectors[0]);
addressEventBroadcaster.listeners.broadcast(new AddressEvent(new ConnectableImpl("199.199.199.199", 2048, true),
AddressEvent.Type.ADDRESS_CHANGED));
Thread.sleep(SLEEP);
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
FriendPresence buddy2 = aliceRosterListener.getFirstPresence(USERNAME_2);
LimewireFeature limewireFeature = (LimewireFeature)buddy2.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy2.getType());
assertEquals(FriendPresence.Mode.available, buddy2.getMode());
AddressFeature addressFeature = (AddressFeature)buddy2.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
FriendAddress friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy2.getPresenceId(), friendAddress.getFullId());
Connectable address = (Connectable)injectors[0].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("199.199.199.199", address.getAddress());
assertEquals(2048, address.getPort());
assertEquals(true, address.isTLSCapable());
AuthTokenFeature authTokenFeature = (AuthTokenFeature)buddy2.getFeature(AuthTokenFeature.ID);
assertNotNull(authTokenFeature);
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
FriendPresence buddy1 = bobRosterListener.getFirstPresence(USERNAME_1);
limewireFeature = (LimewireFeature)buddy1.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy1.getType());
assertEquals(FriendPresence.Mode.available, buddy2.getMode());
addressFeature = (AddressFeature)buddy1.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy1.getPresenceId(), friendAddress.getFullId());
address = (Connectable)injectors[1].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("199.199.199.199", address.getAddress());
assertEquals(2048, address.getPort());
assertEquals(true, address.isTLSCapable());
authTokenFeature = (AuthTokenFeature)buddy1.getFeature(AuthTokenFeature.ID);
assertNotNull(authTokenFeature);
}
/**
* Tests that logging out removes the connection from the service's
* list of connections
*/
public void testUserLogout() throws InterruptedException, ExecutionException {
assertTrue(friendConnectionAlice.isLoggedIn());
friendConnectionAlice.logout().get();
assertFalse(friendConnectionAlice.isLoggedIn());
}
/**
* Tests that friends receive one another's status updates
*/
public void testStatusChanges() throws InterruptedException, UnknownHostException, FriendException, ExecutionException {
assertEquals(1, aliceRosterListener.getRosterSize());
assertEquals(USERNAME_2, aliceRosterListener.getFirstRosterEntry());
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
assertEquals(1, bobRosterListener.getRosterSize());
assertEquals(USERNAME_1, bobRosterListener.getFirstRosterEntry());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
FriendPresence buddy2 = aliceRosterListener.getFirstPresence(USERNAME_2);
assertEquals(FriendPresence.Type.available, buddy2.getType());
assertEquals(FriendPresence.Mode.available, buddy2.getMode());
friendConnectionBob.setMode(FriendPresence.Mode.away).get();
Thread.sleep(SLEEP);
buddy2 = aliceRosterListener.getFirstPresence(USERNAME_2);
assertEquals(FriendPresence.Type.available, buddy2.getType());
assertEquals(FriendPresence.Mode.away, buddy2.getMode());
}
/**
* Tests that friends receive one another's chat messages
*/
public void testChat() throws InterruptedException, FriendException, IOException {
MessageReaderMock reader = new MessageReaderMock();
FriendPresence automatedtestfriend2 = aliceRosterListener.getFirstPresence(USERNAME_2);
MessageWriter writer = automatedtestfriend2.getFriend().createChat(reader);
writer.writeMessage("hello world");
Thread.sleep(SLEEP);
IncomingChatListenerMock incomingChatListener2 = bobRosterListener.listener;
MessageWriter writer2 = incomingChatListener2.writer;
writer2.writeMessage("goodbye world");
Thread.sleep(SLEEP);
assertEquals(1, incomingChatListener2.reader.messages.size());
assertEquals("hello world", incomingChatListener2.reader.messages.get(0));
assertEquals(1, reader.messages.size());
assertEquals("goodbye world", reader.messages.get(0));
}
/**
* Tests that friends receive one another's file offers
*/
public void testOfferFile() throws InterruptedException, IOException, XmlPullParserException, FriendException {
FriendPresence automatedtestfriend2 = aliceRosterListener.getFirstPresence(USERNAME_2);
Map<Element, String> data = new EnumMap<Element, String>(Element.class);
data.put(Element.id, new Random().nextInt() + "");
data.put(Element.name, "a_cool_file.txt");
data.put(Element.size, 1000 + "");
data.put(Element.createTime, Long.toString(new Date().getTime()));
data.put(Element.description, "cool file");
data.put(Element.urns, "urn:sha1:PLSTHIPQGSSZTS5FJUPAKUZWUGYQYPFB");
data.put(Element.index, "455");
FileMetaDataImpl metaData = new FileMetaDataImpl(data);
FileOfferFeature feature = (FileOfferFeature)automatedtestfriend2.getFeature(FileOfferFeature.ID);
assertNotNull(feature);
FeatureTransport<FileMetaData> fileOfferer = automatedtestfriend2.getTransport(FileOfferFeature.class);
fileOfferer.sendFeature(automatedtestfriend2, metaData);
Thread.sleep(SLEEP);
List<FileMetaData> offers = fileOfferHandler.offers;
assertEquals(1, offers.size());
assertEquals("a_cool_file.txt", offers.get(0).getName());
}
/**
* Tests that friends logged in through LimeWire receive one another's
* updated addresses
*/
public void testDetectAddressChanges() throws InterruptedException, UnknownHostException {
assertEquals(1, aliceRosterListener.getRosterSize());
assertEquals(USERNAME_2, aliceRosterListener.getFirstRosterEntry());
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
assertEquals(1, bobRosterListener.getRosterSize());
assertEquals(USERNAME_1, bobRosterListener.getFirstRosterEntry());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
getAddressBroadcaster(injectors[0]).listeners.broadcast(new AddressEvent(new ConnectableImpl("199.199.199.199", 2048, true),
AddressEvent.Type.ADDRESS_CHANGED));
getAddressBroadcaster(injectors[1]).listeners.broadcast(new AddressEvent(new ConnectableImpl("199.199.199.199", 2048, true),
AddressEvent.Type.ADDRESS_CHANGED));
Thread.sleep(SLEEP);
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
FriendPresence buddy2 = aliceRosterListener.getFirstPresence(USERNAME_2);
LimewireFeature limewireFeature = (LimewireFeature)buddy2.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy2.getType());
AddressFeature addressFeature = (AddressFeature)buddy2.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
FriendAddress friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy2.getPresenceId(), friendAddress.getFullId());
Connectable address = (Connectable)injectors[0].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("199.199.199.199", address.getAddress());
assertEquals(2048, address.getPort());
assertEquals(true, address.isTLSCapable());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
FriendPresence buddy1 = bobRosterListener.getFirstPresence(USERNAME_1);
limewireFeature = (LimewireFeature)buddy1.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy1.getType());
addressFeature = (AddressFeature)buddy1.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy1.getPresenceId(), friendAddress.getFullId());
address = (Connectable)injectors[1].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("199.199.199.199", address.getAddress());
assertEquals(2048, address.getPort());
assertEquals(true, address.isTLSCapable());
getAddressBroadcaster(injectors[0]).listeners.broadcast(new AddressEvent(new ConnectableImpl("200.200.200.200", 5000, false),
AddressEvent.Type.ADDRESS_CHANGED));
getAddressBroadcaster(injectors[1]).listeners.broadcast(new AddressEvent(new ConnectableImpl("200.200.200.200", 5000, false),
AddressEvent.Type.ADDRESS_CHANGED));
Thread.sleep(SLEEP);
assertEquals(1, aliceRosterListener.countPresences(USERNAME_2));
buddy2 = aliceRosterListener.getFirstPresence(USERNAME_2);
limewireFeature = (LimewireFeature)buddy2.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy2.getType());
addressFeature = (AddressFeature)buddy2.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy2.getPresenceId(), friendAddress.getFullId());
address = (Connectable)injectors[0].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("200.200.200.200", address.getAddress());
assertEquals(5000, address.getPort());
assertEquals(false, address.isTLSCapable());
assertEquals(1, bobRosterListener.countPresences(USERNAME_1));
buddy1 = bobRosterListener.getFirstPresence(USERNAME_1);
limewireFeature = (LimewireFeature)buddy1.getFeature(LimewireFeature.ID);
assertNotNull(limewireFeature);
assertEquals(FriendPresence.Type.available, buddy1.getType());
addressFeature = (AddressFeature)buddy1.getFeature(AddressFeature.ID);
assertNotNull(addressFeature);
friendAddress = (FriendAddress)addressFeature.getFeature();
assertEquals(buddy1.getPresenceId(), friendAddress.getFullId());
address = (Connectable)injectors[1].getInstance(FriendAddressRegistry.class).get(friendAddress);
assertEquals("200.200.200.200", address.getAddress());
assertEquals(5000, address.getPort());
assertEquals(false, address.isTLSCapable());
}
/**
* Tests that when a user is logged in more than once, chat messages
* are received by all the user's presences until one of them replies,
* after which they're received by whichever presence replied most recently
*/
public void testChatWithMultiplePresencesOfSameUser()
throws InterruptedException, FriendException, UnknownHostException, ExecutionException {
Injector injector = createInjector(getModules());
ServiceRegistry registry = injector.getInstance(ServiceRegistry.class);
registry.start();
XMPPConnectionFactoryImpl factory = injector.getInstance(XMPPConnectionFactoryImpl.class);
try {
// Create a second presence for Bob
RosterListenerMock bob2RosterListener = new RosterListenerMock();
FriendConnectionConfiguration bob2 =
new FriendConnectionConfigurationMock(USERNAME_2, PASSWORD_2,
SERVICE, bob2RosterListener);
factory.login(bob2).get();
Thread.sleep(SLEEP);
getAddressBroadcaster(injectors[0]).listeners.broadcast(new AddressEvent(
new ConnectableImpl("199.199.199.199", 2048, true),
AddressEvent.Type.ADDRESS_CHANGED));
Thread.sleep(SLEEP);
// Simulate Alice talking to two presences of Bob
MessageReaderMock aliceFromBob = new MessageReaderMock();
FriendPresence bobPresence = aliceRosterListener.getFirstPresence(USERNAME_2);
MessageWriter aliceToBob = bobPresence.getFriend().createChat(aliceFromBob);
// Alice writes a message to Bob
aliceToBob.writeMessage("Hello Bob");
aliceToBob.writeMessage("Both Bobs should get this");
Thread.sleep(SLEEP);
// Confirm that both presences of Bob get the message
List<String> receivedByBob = bobRosterListener.listener.reader.messages;
List<String> receivedByBob2 = bob2RosterListener.listener.reader.messages;
assertEquals(2, receivedByBob.size());
assertEquals("Hello Bob", receivedByBob.get(0));
assertEquals("Both Bobs should get this", receivedByBob.get(1));
assertEquals(2, receivedByBob2.size());
assertEquals("Hello Bob", receivedByBob2.get(0));
assertEquals("Both Bobs should get this", receivedByBob2.get(1));
// Bob sends a message; Alice should get it
MessageWriter bobToAlice = bobRosterListener.listener.writer;
bobToAlice.writeMessage("Bob writing to Alice");
Thread.sleep(SLEEP);
assertEquals(1, aliceFromBob.messages.size());
assertEquals("Bob writing to Alice", aliceFromBob.messages.get(0));
// When Alice writes back, only Bob should receive the message
aliceToBob.writeMessage("Only Bob should get this");
Thread.sleep(SLEEP);
assertEquals(3, receivedByBob.size()); // One extra message received
assertEquals("Only Bob should get this", receivedByBob.get(2));
assertEquals(2, receivedByBob2.size()); // Other presence is unaffected
// Bob2 writes to Alice; when Alice writes back, only Bob2 should
// receive the message
MessageWriter bob2ToAlice = bob2RosterListener.listener.writer;
bob2ToAlice.writeMessage("Bob2 writing to Alice");
Thread.sleep(SLEEP);
assertEquals(2, aliceFromBob.messages.size());
assertEquals("Bob2 writing to Alice", aliceFromBob.messages.get(1));
aliceToBob.writeMessage("Only Bob2 should get this");
Thread.sleep(SLEEP);
assertEquals(3, receivedByBob2.size()); // One extra message received
assertEquals("Only Bob2 should get this", receivedByBob2.get(2));
assertEquals(3,receivedByBob.size()); // Other presence is unaffected
} finally {
factory.stop();
registry.stop();
}
}
}