1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-26 21:34:50 +02:00
Smack/core/src/integration-test/java/org/jivesoftware/smack/RosterSmackTest.java
Florian Schmaus 602a8fc812 Activate the jingle subproject and move integration tests
The jingle subproject builds now. This doesn't change that the code is
outdated with regard to the specification and unmaintained for
years. But hopefully this is the first step to change that. :)

The integration tests have been moved into SourceSets of 'core' and
'extensions'.
2014-02-19 10:38:30 +01:00

711 lines
28 KiB
Java

/**
*
* Copyright 2005 Jive Software.
*
* 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 org.jivesoftware.smack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.test.SmackTestCase;
import org.jivesoftware.smack.util.StringUtils;
import org.mockito.internal.util.RemoveFirstLine;
/**
* Tests the Roster functionality by creating and removing roster entries.
*
* @author Gaston Dombiak
*/
public class RosterSmackTest extends SmackTestCase {
/**
* Constructor for RosterSmackTest.
* @param name
*/
public RosterSmackTest(String name) {
super(name);
}
/**
* 1. Create entries in roster groups
* 2. Iterate on the groups and remove the entry from each group
* 3. Check that the entries are kept as unfiled entries
*/
public void testDeleteAllRosterGroupEntries() {
try {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
CountDownLatch latch = new CountDownLatch(2);
setupCountdown(latch, roster);
roster.createEntry(getBareJID(1), "gato11", new String[] { "Friends", "Family" });
roster.createEntry(getBareJID(2), "gato12", new String[] { "Family" });
waitForCountdown(latch, roster, 2);
final CountDownLatch removeLatch = new CountDownLatch(3);
RosterListener latchCounter = new RosterListener() {
@Override
public void presenceChanged(Presence presence) {}
@Override
public void entriesUpdated(Collection<String> addresses) {
removeLatch.countDown();
}
@Override
public void entriesDeleted(Collection<String> addresses) {}
@Override
public void entriesAdded(Collection<String> addresses) {}
};
roster.addRosterListener(latchCounter);
for (RosterEntry entry : roster.getEntries()) {
for (RosterGroup rosterGroup : entry.getGroups()) {
rosterGroup.removeEntry(entry);
}
}
removeLatch.await(5, TimeUnit.SECONDS);
roster.removeRosterListener(latchCounter);
assertEquals("The number of entries in connection 1 should be 1", 1, getConnection(1).getRoster().getEntryCount());
assertEquals("The number of groups in connection 1 should be 0", 0, getConnection(1).getRoster().getGroupCount());
assertEquals("The number of entries in connection 2 should be 1", 1, getConnection(2).getRoster().getEntryCount());
assertEquals("The number of groups in connection 2 should be 0", 0, getConnection(2).getRoster().getGroupCount());
assertEquals("The number of entries in connection 0 should be 2", 2, roster.getEntryCount());
assertEquals("The number of groups in connection 0 should be 0", 0, roster.getGroupCount());
}
catch (Exception e) {
fail(e.getMessage());
}
}
private void setupCountdown(final CountDownLatch latch, Roster roster) {
roster.addRosterListener(new RosterListener() {
@Override
public void presenceChanged(Presence presence) {}
@Override
public void entriesUpdated(Collection<String> addresses) {
latch.countDown();
}
@Override
public void entriesDeleted(Collection<String> addresses) {}
@Override
public void entriesAdded(Collection<String> addresses) {}
});
}
private void waitForCountdown(CountDownLatch latch, Roster roster, int entryCount) throws InterruptedException {
latch.await(5, TimeUnit.SECONDS);
assertEquals(entryCount, roster.getEntryCount());
}
/**
* 1. Create entries in roster groups
* 2. Iterate on all the entries and remove them from the roster
* 3. Check that the number of entries and groups is zero
*/
public void testDeleteAllRosterEntries() throws Exception {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
CountDownLatch latch = new CountDownLatch(2);
setupCountdown(latch, roster);
roster.createEntry(getBareJID(1), "gato11", new String[] { "Friends" });
roster.createEntry(getBareJID(2), "gato12", new String[] { "Family" });
waitForCountdown(latch, roster, 2);
CountDownLatch removeLatch = new CountDownLatch(2);
RosterListener latchCounter = new RemovalListener(removeLatch);
roster.addRosterListener(latchCounter);
for (RosterEntry entry : roster.getEntries()) {
roster.removeEntry(entry);
}
removeLatch.await(5, TimeUnit.SECONDS);
roster.removeRosterListener(latchCounter);
assertEquals("Wrong number of entries in connection 0", 0, roster.getEntryCount());
assertEquals("Wrong number of groups in connection 0", 0, roster.getGroupCount());
assertEquals("Wrong number of entries in connection 1", 0, getConnection(1).getRoster().getEntryCount());
assertEquals("Wrong number of groups in connection 1", 0, getConnection(1).getRoster().getGroupCount());
}
/**
* 1. Create unfiled entries
* 2. Iterate on all the entries and remove them from the roster
* 3. Check that the number of entries and groups is zero
*/
public void testDeleteAllUnfiledRosterEntries() {
try {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
CountDownLatch latch = new CountDownLatch(2);
setupCountdown(latch, roster);
roster.createEntry(getBareJID(1), "gato11", null);
roster.createEntry(getBareJID(2), "gato12", null);
waitForCountdown(latch, roster, 2);
CountDownLatch removeLatch = new CountDownLatch(2);
RosterListener latchCounter = new RemovalListener(removeLatch);
roster.addRosterListener(latchCounter);
for (RosterEntry entry : roster.getEntries()) {
roster.removeEntry(entry);
}
removeLatch.await(5, TimeUnit.SECONDS);
roster.removeRosterListener(latchCounter);
assertEquals("Wrong number of entries in connection 0", 0, roster.getEntryCount());
assertEquals("Wrong number of groups in connection 0", 0, roster.getGroupCount());
assertEquals("Wrong number of entries in connection 1", 0, getConnection(1).getRoster().getEntryCount());
assertEquals("Wrong number of groups in connection 1", 0, getConnection(1).getRoster().getGroupCount());
}
catch (Exception e) {
fail(e.getMessage());
}
}
/**
* 1. Create an unfiled entry
* 2. Change its name
* 3. Check that the name has been modified
* 4. Reload the whole roster
* 5. Check that the name has been modified
*/
public void testChangeNameToUnfiledEntry() {
try {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
CountDownLatch latch = new CountDownLatch(1);
setupCountdown(latch, roster);
roster.createEntry(getBareJID(1), null, null);
waitForCountdown(latch, roster, 1);
final CountDownLatch updateLatch = new CountDownLatch(2);
RosterListener latchCounter = new RosterListener() {
@Override
public void entriesAdded(Collection<String> addresses) {}
@Override
public void entriesUpdated(Collection<String> addresses) {
updateLatch.countDown();
}
@Override
public void entriesDeleted(Collection<String> addresses) {}
@Override
public void presenceChanged(Presence presence) {}
};
roster.addRosterListener(latchCounter);
// Change the roster entry name and check if the change was made
for (RosterEntry entry : roster.getEntries()) {
entry.setName("gato11");
assertEquals("gato11", entry.getName());
}
// Reload the roster and check the name again
roster.reload();
updateLatch.await(5, TimeUnit.SECONDS);
for (RosterEntry entry : roster.getEntries()) {
assertEquals("gato11", entry.getName());
}
}
catch (Exception e) {
fail(e.getMessage());
}
}
/**
* 1. Create an unfiled entry with no name
* 2. Check that the the entry does not belong to any group
* 3. Change its name and add it to a group
* 4. Check that the name has been modified and that the entry belongs to a group
*/
public void testChangeGroupAndNameToUnfiledEntry() {
try {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), null, null);
Thread.sleep(500);
getConnection(1).getRoster().createEntry(getBareJID(0), null, null);
// Wait up to 5 seconds to receive presences of the new roster contacts
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 5000 &&
!roster.getPresence(getBareJID(0)).isAvailable()) {
Thread.sleep(100);
}
//assertNotNull("Presence not received", roster.getPresence(getBareJID(0)));
for (RosterEntry entry : roster.getEntries()) {
assertFalse("The roster entry belongs to a group", !entry.getGroups().isEmpty());
}
// Change the roster entry name and check if the change was made
roster.createEntry(getBareJID(1), "NewName", new String[] { "Friends" });
// Reload the roster and check the name again
Thread.sleep(200);
for (RosterEntry entry : roster.getEntries()) {
assertEquals("Name of roster entry is wrong", "NewName", entry.getName());
assertTrue("The roster entry does not belong to any group", !entry.getGroups().isEmpty());
}
// Wait up to 5 seconds to receive presences of the new roster contacts
initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 5000 &&
!roster.getPresence(getBareJID(1)).isAvailable()) {
Thread.sleep(100);
}
assertTrue("Presence not received", roster.getPresence(getBareJID(1)).isAvailable());
} catch (Exception e) {
fail(e.getMessage());
}
}
/**
* Tests that adding an existing roster entry that belongs to a group to another group
* works fine.
*/
public void testAddEntryToNewGroup() {
try {
Thread.sleep(500);
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), "gato11", new String[] { "Friends" });
roster.createEntry(getBareJID(2), "gato12", new String[] { "Family" });
// Wait up to 2 seconds to receive new roster contacts
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 && roster.getEntryCount() != 2) {
Thread.sleep(100);
}
assertEquals("Wrong number of entries in connection 0", 2, roster.getEntryCount());
// Add "gato11" to a new group called NewGroup
roster.createGroup("NewGroup").addEntry(roster.getEntry(getBareJID(1)));
// Log in from another resource so we can test the roster
XMPPConnection con2 = createConnection();
con2.connect();
con2.login(getUsername(0), getUsername(0), "MyNewResource");
Roster roster2 = con2.getRoster();
assertEquals("Wrong number of entries in new connection", 2, roster2.getEntryCount());
assertEquals("Wrong number of groups in new connection", 3, roster2.getGroupCount());
RosterEntry entry = roster2.getEntry(getBareJID(1));
assertNotNull("No entry for user 1 was found", entry);
List<String> groupNames = new ArrayList<String>();
for (RosterGroup rosterGroup : entry.getGroups()) {
groupNames.add(rosterGroup.getName());
}
assertTrue("Friends group was not found", groupNames.contains("Friends"));
assertTrue("NewGroup group was not found", groupNames.contains("NewGroup"));
// Close the new connection
con2.disconnect();
Thread.sleep(500);
}
catch (Exception e) {
fail(e.getMessage());
}
}
/**
* Test if renaming a roster group works fine.
*
*/
public void testRenameRosterGroup() {
try {
Thread.sleep(200);
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), "gato11", new String[] { "Friends" });
roster.createEntry(getBareJID(2), "gato12", new String[] { "Friends" });
// Wait up to 2 seconds to let the server process presence subscriptions
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 && (
!roster.getPresence(getBareJID(1)).isAvailable() ||
!roster.getPresence(getBareJID(2)).isAvailable())) {
Thread.sleep(100);
}
roster.getGroup("Friends").setName("Amigos");
// Wait up to 2 seconds
initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 &&
(roster.getGroup("Friends") != null)) {
Thread.sleep(100);
}
assertNull("The group Friends still exists", roster.getGroup("Friends"));
assertNotNull("The group Amigos does not exist", roster.getGroup("Amigos"));
assertEquals(
"Wrong number of entries in the group Amigos",
2,
roster.getGroup("Amigos").getEntryCount());
// Setting the name to empty is like removing this group
roster.getGroup("Amigos").setName("");
// Wait up to 2 seconds for the group to change its name
initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 &&
(roster.getGroup("Amigos") != null)) {
Thread.sleep(100);
}
assertNull("The group Amigos still exists", roster.getGroup("Amigos"));
assertNull("The group with no name does exist", roster.getGroup(""));
assertEquals("There are still groups in the roster", 0, roster.getGroupCount());
assertEquals(
"Wrong number of unfiled entries",
2,
roster.getUnfiledEntryCount());
Thread.sleep(200);
}
catch (Exception e) {
fail(e.getMessage());
}
}
/**
* Test presence management.<p>
*
* 1. Log in user0 from a client and user1 from 2 clients
* 2. Create presence subscription of type BOTH between 2 users
* 3. Check that presence is correctly delivered to both users
* 4. User1 logs out from a client
* 5. Check that presence for each connected resource is correct
*/
public void testRosterPresences() throws Exception {
Presence presence;
// Create another connection for the same user of connection 1
ConnectionConfiguration connectionConfiguration =
new ConnectionConfiguration(getHost(), getPort(), getServiceName());
XMPPConnection conn4 = new XMPPConnection(connectionConfiguration);
conn4.connect();
conn4.login(getUsername(1), getPassword(1), "Home");
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), "gato11", null);
// Wait up to 2 seconds
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 &&
(roster.getPresence(getBareJID(1)).getType() == Presence.Type.unavailable)) {
Thread.sleep(100);
}
// Check that a presence is returned for a user
presence = roster.getPresence(getBareJID(1));
assertTrue("Returned a null Presence for an existing user", presence.isAvailable());
// Check that the right presence is returned for a user+resource
presence = roster.getPresenceResource(getUsername(1) + "@" + conn4.getServiceName() + "/Home");
assertEquals("Returned the wrong Presence", "Home",
StringUtils.parseResource(presence.getFrom()));
// Check that the right presence is returned for a user+resource
presence = roster.getPresenceResource(getFullJID(1));
assertTrue("Presence not found for user " + getFullJID(1), presence.isAvailable());
assertEquals("Returned the wrong Presence", "Smack",
StringUtils.parseResource(presence.getFrom()));
// Check the returned presence for a non-existent user+resource
presence = roster.getPresenceResource("noname@" + getServiceName() + "/Smack");
assertFalse("Available presence was returned for a non-existing user", presence.isAvailable());
assertEquals("Returned Presence for a non-existing user has the incorrect type",
Presence.Type.unavailable, presence.getType());
// Check that the returned presences are correct
Iterator<Presence> presences = roster.getPresences(getBareJID(1));
int count = 0;
while (presences.hasNext()) {
count++;
presences.next();
}
assertEquals("Wrong number of returned presences", count, 2);
// Close the connection so one presence must go
conn4.disconnect();
// Check that the returned presences are correct
presences = roster.getPresences(getBareJID(1));
count = 0;
while (presences.hasNext()) {
count++;
presences.next();
}
assertEquals("Wrong number of returned presences", count, 1);
}
/**
* User1 is connected from 2 resources. User1 adds User0 to his roster. Ensure
* that both resources of user1 get the available presence of User0. Remove User0
* from User1's roster and check presences again.
*/
public void testMultipleResources() throws Exception {
// Create another connection for the same user of connection 1
ConnectionConfiguration connectionConfiguration =
new ConnectionConfiguration(getHost(), getPort(), getServiceName());
XMPPConnection conn4 = new XMPPConnection(connectionConfiguration);
conn4.connect();
conn4.login(getUsername(1), getPassword(1), "Home");
// Add a new roster entry
Roster roster = conn4.getRoster();
roster.createEntry(getBareJID(0), "gato11", null);
// Wait up to 2 seconds
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 && (
!roster.getPresence(getBareJID(0)).isAvailable() ||
!getConnection(1).getRoster().getPresence(getBareJID(0)).isAvailable())) {
Thread.sleep(100);
}
// Check that a presence is returned for the new contact
Presence presence = roster.getPresence(getBareJID(0));
assertTrue("Returned a null Presence for an existing user", presence.isAvailable());
// Check that a presence is returned for the new contact
presence = getConnection(1).getRoster().getPresence(getBareJID(0));
assertTrue("Returned a null Presence for an existing user", presence.isAvailable());
// Delete user from roster
roster.removeEntry(roster.getEntry(getBareJID(0)));
// Wait up to 2 seconds
initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 && (
roster.getPresence(getBareJID(0)).getType() != Presence.Type.unavailable ||
getConnection(1).getRoster().getPresence(getBareJID(0)).getType() !=
Presence.Type.unavailable)) {
Thread.sleep(100);
}
// Check that no presence is returned for the removed contact
presence = roster.getPresence(getBareJID(0));
assertFalse("Available presence was returned for removed contact", presence.isAvailable());
assertEquals("Returned Presence for removed contact has incorrect type",
Presence.Type.unavailable, presence.getType());
// Check that no presence is returned for the removed contact
presence = getConnection(1).getRoster().getPresence(getBareJID(0));
assertFalse("Available presence was returned for removed contact", presence.isAvailable());
assertEquals("Returned Presence for removed contact has incorrect type",
Presence.Type.unavailable, presence.getType());
}
/**
* Tests that the server and Smack are able to handle nicknames that include
* < > characters.
*/
public void testNotCommonNickname() throws Exception {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), "Thiago <12001200>", null);
Thread.sleep(500);
assertEquals("Created entry was never received", 1, roster.getEntryCount());
// Create another connection for the same user of connection 0
ConnectionConfiguration connectionConfiguration =
new ConnectionConfiguration(getHost(), getPort(), getServiceName());
XMPPConnection conn2 = new XMPPConnection(connectionConfiguration);
conn2.connect();
conn2.login(getUsername(0), getPassword(0), "Home");
// Retrieve roster and verify that new contact is there and nickname is correct
Roster roster2 = conn2.getRoster();
assertEquals("Created entry was never received", 1, roster2.getEntryCount());
RosterEntry entry = roster2.getEntry(getBareJID(1));
assertNotNull("New entry was not returned from the server", entry);
assertEquals("Roster item name is incorrect", "Thiago <12001200>", entry.getName());
}
/**
* Clean up all the entries in the roster
*/
private void cleanUpRoster() {
for (int i=0; i<getMaxConnections(); i++) {
// Delete all the entries from the roster
Roster roster = getConnection(i).getRoster();
final CountDownLatch removalLatch = new CountDownLatch(roster.getEntryCount());
roster.addRosterListener(new RosterListener() {
@Override
public void presenceChanged(Presence presence) {}
@Override
public void entriesUpdated(Collection<String> addresses) {}
@Override
public void entriesDeleted(Collection<String> addresses) {
removalLatch.countDown();
}
@Override
public void entriesAdded(Collection<String> addresses) {}
});
for (RosterEntry entry : roster.getEntries()) {
try {
roster.removeEntry(entry);
}
catch (XMPPException e) {
e.printStackTrace();
fail(e.getMessage());
}
}
try {
removalLatch.await(5, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
fail(e.getMessage());
}
}
assertEquals("Wrong number of entries in connection 0", 0, getConnection(0).getRoster().getEntryCount());
assertEquals("Wrong number of entries in connection 1", 0, getConnection(1).getRoster().getEntryCount());
assertEquals("Wrong number of entries in connection 2", 0, getConnection(2).getRoster().getEntryCount());
}
/**
* Tests the creation of a roster and then simulates abrupt termination. Cached presences
* must go offline. At reconnection, presences must go back to online.
* <ol>
* <li> Create some entries
* <li> Breack the connection
* <li> Check offline presences
* <li> Whait for automatic reconnection
* <li> Check online presences
* </ol>
*/
public void testOfflinePresencesAfterDisconnection() throws Exception {
// Add a new roster entry
Roster roster = getConnection(0).getRoster();
roster.createEntry(getBareJID(1), "gato11", null);
roster.createEntry(getBareJID(2), "gato12", null);
// Wait up to 2 seconds to let the server process presence subscriptions
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 2000 && (
!roster.getPresence(getBareJID(1)).isAvailable() ||
!roster.getPresence(getBareJID(2)).isAvailable())) {
Thread.sleep(100);
}
Thread.sleep(200);
// Break the connection
getConnection(0).notifyConnectionError(new Exception("Simulated Error"));
Presence presence = roster.getPresence(getBareJID(1));
assertFalse("Unavailable presence not found for offline user", presence.isAvailable());
assertEquals("Unavailable presence not found for offline user", Presence.Type.unavailable,
presence.getType());
// Reconnection should occur in 10 seconds
Thread.sleep(12200);
presence = roster.getPresence(getBareJID(1));
assertTrue("Presence not found for user", presence.isAvailable());
assertEquals("Presence should be online after a connection reconnection",
Presence.Type.available, presence.getType());
}
protected int getMaxConnections() {
return 3;
}
protected void setUp() throws Exception {
super.setUp();
cleanUpRoster();
}
@Override
protected void tearDown() throws Exception {
cleanUpRoster();
super.tearDown();
}
private class RemovalListener implements RosterListener {
private CountDownLatch latch;
private RemovalListener(CountDownLatch removalLatch) {
latch = removalLatch;
}
@Override
public void presenceChanged(Presence presence) {}
@Override
public void entriesUpdated(Collection<String> addresses) {}
@Override
public void entriesDeleted(Collection<String> addresses) {
latch.countDown();
}
@Override
public void entriesAdded(Collection<String> addresses) {}
};
}