1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-10 09:39:39 +02:00

Rework incoming packet listeners and Roster

Differentiate between asynchronous and synchronous ones. Asynchronous
are the ones where the invocation order may not be the same as the order
in which the stanzas arrived.

Since it's no longer guaranteed that when a unit test calls

processPacket(stanza)

the stanza will be completely processed when the call returns, it was
necessary to extend the unit tests (mostly Roster and ChatManager) with
a packet listener that waits for his invocation. Since we now also use
LinkedHashMaps as Map for the packet listeners (SMACK-531, SMACK-424),
adding a packet listeners as last also means that it will be called as
last. We exploit this behavior change now in the unit tests.

Rename 'recvListeners' to 'syncRecvListeners' in AbstractXMPPConnection.

Rename 'rosterInitialized' to 'loaded' in Roster.

Add Roster.isLoaded().

Reset 'loaded' to false in
Roster.setOfflinePresencesAndResetLoaded() (was setOfflinePresences()).

Fixes SMACK-583, SMACK-532, SMACK-424
This commit is contained in:
Florian Schmaus 2015-01-05 21:42:35 +01:00
parent e5c6c9bdf8
commit 717090d272
39 changed files with 443 additions and 306 deletions

View file

@ -27,102 +27,108 @@ import org.jivesoftware.smack.ChatManager.MatchMode;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.test.util.WaitForPacketListener;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ChatConnectionTest {
private DummyConnection connection;
private DummyConnection dc;
private ChatManager cm;
private TestChatManagerListener listener;
private WaitForPacketListener waitListener;
@Before
public void setUp() throws Exception {
connection = getConnection();
// Defaults
ChatManager.setDefaultIsNormalIncluded(true);
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
dc = DummyConnection.newConnectedDummyConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
waitListener = new WaitForPacketListener();
dc.addSyncPacketListener(waitListener, null);
}
@After
public void tearDown() throws Exception {
if (connection != null)
connection.disconnect();
if (dc != null) {
dc.disconnect();
}
}
@Test
public void validateDefaultSetNormalIncluded() {
public void validateDefaultSetNormalIncludedFalse() {
ChatManager.setDefaultIsNormalIncluded(false);
assertFalse(ChatManager.getInstanceFor(getConnection()).isNormalIncluded());
assertFalse(ChatManager.getInstanceFor(new DummyConnection()).isNormalIncluded());
}
@Test
public void validateDefaultSetNormalIncludedTrue() {
ChatManager.setDefaultIsNormalIncluded(true);
assertTrue(ChatManager.getInstanceFor(getConnection()).isNormalIncluded());
assertTrue(ChatManager.getInstanceFor(new DummyConnection()).isNormalIncluded());
}
@Test
public void validateDefaultSetMatchMode() {
public void validateDefaultSetMatchModeNone() {
ChatManager.setDefaultMatchMode(MatchMode.NONE);
assertEquals(MatchMode.NONE, ChatManager.getInstanceFor(getConnection()).getMatchMode());
assertEquals(MatchMode.NONE, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
}
@Test
public void validateDefaultSetMatchModeBareJid() {
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
assertEquals(MatchMode.BARE_JID, ChatManager.getInstanceFor(getConnection()).getMatchMode());
assertEquals(MatchMode.BARE_JID, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
}
@Test
public void validateMessageTypeWithDefaults() {
DummyConnection dc = getConnection();
ChatManager cm = ChatManager.getInstanceFor(dc);
TestChatManagerListener listener = new TestChatManagerListener();
cm.addChatListener(listener);
public void validateMessageTypeWithDefaults1() {
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.chat);
processServerMessage(incomingChat, dc);
processServerMessage(incomingChat);
assertNotNull(listener.getNewChat());
}
dc = getConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
@Test
public void validateMessageTypeWithDefaults2() {
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.normal);
processServerMessage(incomingChat, dc);
processServerMessage(incomingChat);
assertNotNull(listener.getNewChat());
dc = getConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
}
@Test
public void validateMessageTypeWithDefaults3() {
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.groupchat);
processServerMessage(incomingChat, dc);
assertNull(listener.getNewChat());
dc = getConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.headline);
processServerMessage(incomingChat, dc);
processServerMessage(incomingChat);
assertNull(listener.getNewChat());
}
@Test
public void validateMessageTypeWithNoNormal() {
DummyConnection dc = getConnection();
ChatManager cm = ChatManager.getInstanceFor(dc);
public void validateMessageTypeWithDefaults4() {
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.headline);
assertNull(listener.getNewChat());
}
@Test
public void validateMessageTypeWithNoNormal1() {
cm.setNormalIncluded(false);
TestChatManagerListener listener = new TestChatManagerListener();
cm.addChatListener(listener);
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.chat);
processServerMessage(incomingChat, dc);
processServerMessage(incomingChat);
assertNotNull(listener.getNewChat());
}
dc = getConnection();
cm = ChatManager.getInstanceFor(dc);
@Test
public void validateMessageTypeWithNoNormal2() {
cm.setNormalIncluded(false);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.normal);
processServerMessage(incomingChat, dc);
processServerMessage(incomingChat);
assertNull(listener.getNewChat());
}
@ -130,65 +136,59 @@ public class ChatConnectionTest {
@Test
public void chatMatchedOnJIDWhenNoThreadBareMode() {
// MatchMode.BARE_JID is the default, so setting required.
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
Chat newChat = listener.getNewChat();
assertNotNull(newChat);
// Should match on chat with full jid
incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages());
// Should match on chat with bare jid
incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(3, msgListener.getNumMessages());
}
@Test
public void chatMatchedOnJIDWhenNoThreadJidMode() {
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setMatchMode(MatchMode.SUPPLIED_JID);
cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
Chat newChat = listener.getNewChat();
assertNotNull(newChat);
cm.removeChatListener(listener);
// Should match on chat with full jid
incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages());
// Should not match on chat with bare jid
TestChatManagerListener listener2 = new TestChatManagerListener();
cm.addChatListener(listener2);
incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages());
assertNotNull(listener2.getNewChat());
}
@Test
public void chatMatchedOnJIDWhenNoThreadNoneMode() {
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setMatchMode(MatchMode.NONE);
cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
Chat newChat = listener.getNewChat();
assertNotNull(newChat);
assertEquals(1, msgListener.getNumMessages());
@ -198,7 +198,7 @@ public class ChatConnectionTest {
TestChatManagerListener listener2 = new TestChatManagerListener();
cm.addChatListener(listener2);
incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(1, msgListener.getNumMessages());
assertNotNull(newChat);
cm.removeChatListener(listener2);
@ -207,7 +207,7 @@ public class ChatConnectionTest {
TestChatManagerListener listener3 = new TestChatManagerListener();
cm.addChatListener(listener3);
incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con);
processServerMessage(incomingChat);
assertEquals(1, msgListener.getNumMessages());
assertNotNull(listener3.getNewChat());
}
@ -218,9 +218,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatFoundWhenNoThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(null, true);
@ -237,9 +234,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatFoundWhenNoThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(null, false);
@ -256,9 +250,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatFoundWithSameThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID(), true);
@ -275,9 +266,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatFoundWithSameThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID(), false);
@ -294,9 +282,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatNotFoundWithDiffThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false);
@ -313,9 +298,6 @@ public class ChatConnectionTest {
*/
@Test
public void chatNotFoundWithDiffThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true);
@ -328,11 +310,7 @@ public class ChatConnectionTest {
@Test
public void chatNotMatchedWithTypeNormal() {
TestChatManagerListener listener = new TestChatManagerListener();
DummyConnection con = getConnection();
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setNormalIncluded(false);
cm.addChatListener(listener);
Message incomingChat = createChatPacket(null, false);
incomingChat.setType(Type.normal);
@ -341,50 +319,26 @@ public class ChatConnectionTest {
assertNull(listener.getNewChat());
}
@SuppressWarnings("unused")
private ChatManager getChatManager(boolean includeNormal, MatchMode mode) {
ChatManager cm = ChatManager.getInstanceFor(getConnection());
cm.setMatchMode(mode);
cm.setNormalIncluded(includeNormal);
return cm;
}
private DummyConnection getConnection() {
DummyConnection con = new DummyConnection();
try {
con.connect();
con.login();
} catch (Exception e) {
// No need for handling in a dummy connection.
}
return con;
}
private Message createChatPacket(final String threadId, final boolean isFullJid) {
Message chatMsg = new Message("me@testserver", Message.Type.chat);
chatMsg.setBody("the body message - " + System.currentTimeMillis());
chatMsg.setFrom("you@testserver" + (isFullJid ? "/resource" : ""));
if (threadId != null)
chatMsg.setThread(threadId);
chatMsg.setThread(threadId);
return chatMsg;
}
private void processServerMessage(Packet incomingChat) {
processServerMessage(incomingChat, connection);
}
private void processServerMessage(Packet incomingChat, DummyConnection con) {
TestChatServer chatServer = new TestChatServer(incomingChat, con);
TestChatServer chatServer = new TestChatServer(incomingChat, dc);
chatServer.start();
try {
chatServer.join();
} catch (InterruptedException e) {
fail();
}
waitListener.waitAndReset();
}
class TestChatManagerListener implements ChatManagerListener {
class TestChatManagerListener extends WaitForPacketListener implements ChatManagerListener {
private Chat newChat;
private ChatMessageListener listener;
@ -401,6 +355,7 @@ public class ChatConnectionTest {
if (listener != null)
newChat.addMessageListener(listener);
reportInvoked();
}
public Chat getNewChat() {

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smack;
import java.io.IOException;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
@ -189,7 +190,7 @@ public class DummyConnection extends AbstractXMPPConnection {
*/
@SuppressWarnings("unchecked")
public <P extends TopLevelStreamElement> P getSentPacket() throws InterruptedException {
return (P) queue.poll();
return (P) queue.poll(5, TimeUnit.MINUTES);
}
/**
@ -221,6 +222,18 @@ public class DummyConnection extends AbstractXMPPConnection {
invokePacketCollectorsAndNotifyRecvListeners(packet);
}
public static DummyConnection newConnectedDummyConnection() {
DummyConnection dummyConnection = new DummyConnection();
try {
dummyConnection.connect();
dummyConnection.login();
}
catch (SmackException | IOException | XMPPException e) {
throw new IllegalStateException(e);
}
return dummyConnection;
}
public static class DummyConnectionConfiguration extends ConnectionConfiguration {
protected DummyConnectionConfiguration(Builder builder) {
super(builder);

View file

@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.jivesoftware.smack.packet.IQ;
@ -36,6 +37,7 @@ import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.RosterPacket.Item;
import org.jivesoftware.smack.packet.RosterPacket.ItemType;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.test.util.WaitForPacketListener;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.junit.After;
import org.junit.Before;
@ -52,6 +54,7 @@ import org.xmlpull.v1.XmlPullParser;
public class RosterTest {
private DummyConnection connection;
private Roster roster;
private TestRosterListener rosterListener;
@Before
@ -63,7 +66,9 @@ public class RosterTest {
connection.connect();
connection.login();
rosterListener = new TestRosterListener();
connection.getRoster().addRosterListener(rosterListener);
roster = connection.getRoster();
roster.addRosterListener(rosterListener);
connection.setPacketReplyTimeout(1000 * 60 * 5);
}
@After
@ -83,19 +88,17 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-login"
* >RFC3921: Retrieving One's Roster on Login</a>.
*/
@Test(timeout=5000)
@Test
public void testSimpleRosterInitialization() throws Exception {
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
assertFalse("Roster shouldn't be already initialized!",
roster.rosterInitialized);
assertFalse("Roster shouldn't be already loaded!",
roster.isLoaded());
// Perform roster initialization
initRoster(connection, roster);
initRoster();
// Verify roster
assertTrue("Roster can't be initialized!", roster.rosterInitialized);
assertTrue("Roster can't be loaded!", roster.waitUntilLoaded());
verifyRomeosEntry(roster.getEntry("romeo@example.net"));
verifyMercutiosEntry(roster.getEntry("mercutio@example.com"));
verifyBenvoliosEntry(roster.getEntry("benvolio@example.net"));
@ -121,7 +124,7 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-add"
* >RFC3921: Adding a Roster Item</a>.
*/
@Test(timeout=5000)
@Test
public void testAddRosterItem() throws Throwable {
// Constants for the new contact
final String contactJID = "nurse@example.com";
@ -129,9 +132,8 @@ public class RosterTest {
final String[] contactGroup = {"Servants"};
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Adding the new roster item
@ -161,6 +163,7 @@ public class RosterTest {
if (exception != null) {
throw exception;
}
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -192,7 +195,7 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-update"
* >RFC3921: Updating a Roster Item</a>.
*/
@Test(timeout=5000)
@Test
public void testUpdateRosterItem() throws Throwable {
// Constants for the updated contact
final String contactJID = "romeo@example.net";
@ -200,9 +203,8 @@ public class RosterTest {
final String[] contactGroups = {"Friends", "Lovers"};
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Updating the roster item
@ -235,6 +237,7 @@ public class RosterTest {
if (exception != null) {
throw exception;
}
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the updated contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -267,15 +270,14 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-delete"
* >RFC3921: Deleting a Roster Item</a>.
*/
@Test(timeout=5000)
@Test
public void testDeleteRosterItem() throws Throwable {
// The contact which should be deleted
final String contactJID = "romeo@example.net";
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Delete a roster item
@ -296,6 +298,7 @@ public class RosterTest {
if (exception != null) {
throw exception;
}
rosterListener.waitUntilInvocationOrTimeout();
// Verify
final RosterEntry deletedEntry = roster.getEntry(contactJID);
@ -314,10 +317,9 @@ public class RosterTest {
* <a href="http://xmpp.org/internet-drafts/draft-ietf-xmpp-3921bis-03.html#roster-syntax-actions-push"
* >RFC3921bis-03: Roster Push</a>.
*/
@Test(timeout=5000)
@Test
public void testSimpleRosterPush() throws Throwable {
final String contactJID = "nurse@example.com";
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
final StringBuilder sb = new StringBuilder();
sb.append("<iq id=\"rostertest1\" type=\"set\" ")
@ -328,11 +330,12 @@ public class RosterTest {
.append("</iq>");
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
final IQ rosterPush = PacketParserUtils.parse(parser, connection);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Simulate receiving the roster push
connection.processPacket(rosterPush);
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -358,7 +361,7 @@ public class RosterTest {
*
* @see <a href="http://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push">RFC 6121, Section 2.1.6</a>
*/
@Test(timeout=5000)
@Test
public void testIgnoreInvalidFrom() {
RosterPacket packet = new RosterPacket();
packet.setType(Type.set);
@ -366,8 +369,11 @@ public class RosterTest {
packet.setFrom("mallory@example.com");
packet.addRosterItem(new Item("spam@example.com", "Cool products!"));
WaitForPacketListener waitForPacketListener = new WaitForPacketListener();
connection.addAsyncPacketListener(waitForPacketListener, null);
// Simulate receiving the roster push
connection.processPacket(packet);
waitForPacketListener.waitUntilInvocationOrTimeout();
assertNull("Contact was added to roster", connection.getRoster().getEntry("spam@example.com"));
}
@ -386,9 +392,8 @@ public class RosterTest {
final String[] contactGroup = {""};
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Adding the new roster item
@ -416,6 +421,7 @@ public class RosterTest {
if (exception != null) {
throw exception;
}
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -445,10 +451,9 @@ public class RosterTest {
*
* @see <a href="http://www.igniterealtime.org/issues/browse/SMACK-294">SMACK-294</a>
*/
@Test(timeout=5000)
@Test
public void testEmptyGroupRosterPush() throws Throwable {
final String contactJID = "nurse@example.com";
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster);
final StringBuilder sb = new StringBuilder();
sb.append("<iq id=\"rostertest2\" type=\"set\" ")
@ -461,11 +466,12 @@ public class RosterTest {
.append("</iq>");
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
final IQ rosterPush = PacketParserUtils.parse(parser, connection);
initRoster(connection, roster);
initRoster();
rosterListener.reset();
// Simulate receiving the roster push
connection.processPacket(rosterPush);
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -520,7 +526,7 @@ public class RosterTest {
* @param roster the roster (or buddy list) which should be initialized.
* @throws SmackException
*/
public static void initRoster(DummyConnection connection, Roster roster) throws InterruptedException, XMPPException, SmackException {
private void initRoster() throws InterruptedException, XMPPException, SmackException {
roster.reload();
while (true) {
final Packet sentPacket = connection.getSentPacket();
@ -558,6 +564,8 @@ public class RosterTest {
break;
}
}
roster.waitUntilLoaded();
rosterListener.waitUntilInvocationOrTimeout();
}
/**
@ -687,10 +695,10 @@ public class RosterTest {
/**
* This class can be used to check if the RosterListener was invoked.
*/
public static class TestRosterListener implements RosterListener {
private CopyOnWriteArrayList<String> addressesAdded = new CopyOnWriteArrayList<String>();
private CopyOnWriteArrayList<String> addressesDeleted = new CopyOnWriteArrayList<String>();
private CopyOnWriteArrayList<String> addressesUpdated = new CopyOnWriteArrayList<String>();
public static class TestRosterListener extends WaitForPacketListener implements RosterListener {
private final List<String> addressesAdded = new CopyOnWriteArrayList<>();
private final List<String> addressesDeleted = new CopyOnWriteArrayList<>();
private final List<String> addressesUpdated = new CopyOnWriteArrayList<>();
public synchronized void entriesAdded(Collection<String> addresses) {
addressesAdded.addAll(addresses);
@ -699,6 +707,7 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " added.");
}
}
reportInvoked();
}
public synchronized void entriesDeleted(Collection<String> addresses) {
@ -708,6 +717,7 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " deleted.");
}
}
reportInvoked();
}
public synchronized void entriesUpdated(Collection<String> addresses) {
@ -717,12 +727,14 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " updated.");
}
}
reportInvoked();
}
public void presenceChanged(Presence presence) {
if (SmackConfiguration.DEBUG_ENABLED) {
System.out.println("Roster presence changed: " + presence.toXML());
}
reportInvoked();
}
/**
@ -756,6 +768,7 @@ public class RosterTest {
* Reset the lists of added, deleted or updated items.
*/
public synchronized void reset() {
super.reset();
addressesAdded.clear();
addressesDeleted.clear();
addressesUpdated.clear();

View file

@ -27,6 +27,7 @@ import java.util.Collection;
import java.util.HashSet;
import org.jivesoftware.smack.ConnectionConfiguration.Builder;
import org.jivesoftware.smack.RosterTest.TestRosterListener;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Packet;
@ -53,15 +54,14 @@ import org.junit.rules.TemporaryFolder;
public class RosterVersioningTest {
private DummyConnection connection;
private Roster roster;
private TestRosterListener rosterListener;
@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder();
@Before
public void setUp() throws Exception {
// Uncomment this to enable debug output
//XMPPConnection.DEBUG_ENABLED = true;
DirectoryRosterStore store = DirectoryRosterStore.init(tmpFolder.newFolder("store"));
populateStore(store);
@ -69,13 +69,20 @@ public class RosterVersioningTest {
builder.setRosterStore(store);
connection = new DummyConnection(builder.build());
connection.connect();
connection.login();
rosterListener = new TestRosterListener();
roster = connection.getRoster();
roster.addRosterListener(rosterListener);
roster.reload();
}
@After
public void tearDown() throws Exception {
if (connection != null) {
if (rosterListener != null && roster != null) {
roster.removeRosterListener(rosterListener);
rosterListener = null;
}
connection.disconnect();
connection = null;
}
@ -89,10 +96,9 @@ public class RosterVersioningTest {
*/
@Test(timeout = 5000)
public void testEqualVersionStored() throws InterruptedException, IOException, XMPPException, SmackException {
connection.getRoster().reload();
answerWithEmptyRosterResult();
roster.waitUntilLoaded();
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
assertSame("Size of the roster", 3, entries.size());
@ -124,8 +130,6 @@ public class RosterVersioningTest {
*/
@Test(timeout = 5000)
public void testOtherVersionStored() throws InterruptedException, XMPPException, SmackException {
connection.getRoster().reload();
Item vaglafItem = vaglafItem();
// We expect that the roster request is the only packet sent. This is not part of the specification,
@ -141,7 +145,9 @@ public class RosterVersioningTest {
answer.setVersion("newVersion");
answer.addRosterItem(vaglafItem);
rosterListener.reset();
connection.processPacket(answer);
rosterListener.waitUntilInvocationOrTimeout();
} else {
assertTrue("Expected to get a RosterPacket ", false);
}
@ -164,11 +170,10 @@ public class RosterVersioningTest {
*/
@Test(timeout = 5000)
public void testRosterVersioningWithCachedRosterAndPushes() throws Throwable {
connection.getRoster().reload();
answerWithEmptyRosterResult();
rosterListener.waitAndReset();
RosterStore store = connection.getConfiguration().getRosterStore();
Roster roster = connection.getRoster();
// Simulate a roster push adding vaglaf
{
@ -179,7 +184,9 @@ public class RosterVersioningTest {
Item pushedItem = vaglafItem();
rosterPush.addRosterItem(pushedItem);
rosterListener.reset();
connection.processPacket(rosterPush);
rosterListener.waitAndReset();
assertEquals("Expect store version after push", "v97", store.getRosterVersion());
@ -204,7 +211,9 @@ public class RosterVersioningTest {
Item item = new Item("vaglaf@example.com", "vaglaf the only");
item.setItemType(ItemType.remove);
rosterPush.addRosterItem(item);
rosterListener.reset();
connection.processPacket(rosterPush);
rosterListener.waitAndReset();
assertNull("Store doses not contain vaglaf", store.getEntry("vaglaf@example.com"));
assertEquals("Expect store version after push", "v98", store.getRosterVersion());

View file

@ -0,0 +1,60 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* 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.test.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.packet.Packet;
public class WaitForPacketListener implements PacketListener {
private CountDownLatch latch = new CountDownLatch(1);
@Override
public void processPacket(Packet packet) throws NotConnectedException {
reportInvoked();
}
protected void reportInvoked() {
latch.countDown();
}
public void waitAndReset() {
waitUntilInvocationOrTimeout();
reset();
}
public void waitUntilInvocationOrTimeout() {
try {
boolean res = latch.await(30, TimeUnit.SECONDS);
if (!res) {
throw new IllegalStateException("Latch timed out before it reached zero");
}
}
catch (InterruptedException e) {
// TODO better handling of spurious interrupts
throw new IllegalStateException(e);
}
}
public void reset() {
latch = new CountDownLatch(1);
}
}