From aff6283798afebf0f6529f9c027fa0f562d09f0f Mon Sep 17 00:00:00 2001 From: Dan Caseley Date: Wed, 7 Apr 2021 10:32:58 +0100 Subject: [PATCH] Add MUC tests for presence & self-presence for role & affiliation changes --- .../muc/MultiUserChatIntegrationTest.java | 598 +++++++++++++++++- 1 file changed, 576 insertions(+), 22 deletions(-) diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java index afd34e36e..28a9f26b3 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java @@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.concurrent.TimeoutException; +import java.util.logging.Level; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.SmackException.NoResponseException; @@ -33,8 +34,6 @@ import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.muc.MultiUserChat.MucCreateConfigFormHandle; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucNotJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; import org.jivesoftware.smackx.muc.packet.MUCUser; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; @@ -45,6 +44,7 @@ import org.igniterealtime.smack.inttest.util.ResultSyncPoint; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.parts.Localpart; import org.jxmpp.jid.parts.Resourcepart; @@ -56,6 +56,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { private final MultiUserChatManager mucManagerOne; private final MultiUserChatManager mucManagerTwo; + private final MultiUserChatManager mucManagerThree; private final DomainBareJid mucService; public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment) @@ -64,6 +65,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { super(environment); mucManagerOne = MultiUserChatManager.getInstanceFor(conOne); mucManagerTwo = MultiUserChatManager.getInstanceFor(conTwo); + mucManagerThree = MultiUserChatManager.getInstanceFor(conThree); List services = mucManagerOne.getMucServiceDomains(); if (services.isEmpty()) { @@ -74,27 +76,72 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { } } + /** + * Asserts that when a user joins a room, they are themselves included on the list of users notified (self-presence). + * + *

From XEP-0045 § 7.2.2:

+ *
+ * ...the service MUST also send presence from the new participant's occupant JID to the full JIDs of all the + * occupants (including the new occupant) + *
+ * + * @throws Exception when errors occur + */ @SmackIntegrationTest - public void mucJoinLeaveTest() throws XmppStringprepException, NotAMucServiceException, NoResponseException, - XMPPErrorException, NotConnectedException, InterruptedException, MucNotJoinedException { - EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from("smack-inttest-join-leave-" + randomString), - mucService.getDomain()); + public void mucJoinTest() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest-join-leave"); MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); + try { + Presence reflectedJoinPresence = muc.join(Resourcepart.from("nick-one")); - muc.join(Resourcepart.from("nick-one")); + MUCUser mucUser = MUCUser.from(reflectedJoinPresence); - Presence reflectedLeavePresence = muc.leave(); + assertNotNull(mucUser); + assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)); + assertEquals(mucAddress + "/nick-one", reflectedJoinPresence.getFrom().toString()); + assertEquals(reflectedJoinPresence.getTo().toString(), conOne.getUser().asEntityFullJidIfPossible().toString()); + } finally { + tryDestroy(muc); + } + } - MUCUser mucUser = MUCUser.from(reflectedLeavePresence); - assertNotNull(mucUser); + /** + * Asserts that when a user leaves a room, they are themselves included on the list of users notified (self-presence). + * + *

From XEP-0045 § 7.14:

+ *
+ * The service MUST then send a presence stanzas of type "unavailable" from the departing user's occupant JID to + * the departing occupant's full JIDs, including a status code of "110" to indicate that this notification is + * "self-presence" + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucLeaveTest() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest-join-leave"); - assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)); + MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); + try { + muc.join(Resourcepart.from("nick-one")); + + Presence reflectedLeavePresence = muc.leave(); + + MUCUser mucUser = MUCUser.from(reflectedLeavePresence); + assertNotNull(mucUser); + + assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)); + assertEquals(mucAddress + "/nick-one", reflectedLeavePresence.getFrom().toString()); + assertEquals(reflectedLeavePresence.getTo().toString(), conOne.getUser().asEntityFullJidIfPossible().toString()); + } finally { + tryDestroy(muc); + } } @SmackIntegrationTest public void mucTest() throws Exception { - EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from("smack-inttest-" + randomString), mucService.getDomain()); + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); @@ -112,24 +159,497 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { } }); - MucCreateConfigFormHandle handle = mucAsSeenByOne.createOrJoin(Resourcepart.from("one-" + randomString)); - if (handle != null) { - handle.makeInstant(); - } + createMUC(mucAsSeenByOne, "one-" + randomString); mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString)); - mucAsSeenByOne.sendMessage(mucMessage); - resultSyncPoint.waitForResult(timeout); + try { + resultSyncPoint.waitForResult(timeout); + } catch (TimeoutException e) { + throw new AssertionError("Failed to receive presence", e); + } finally { + tryDestroy(mucAsSeenByOne); + } + } - mucAsSeenByOne.leave(); - mucAsSeenByTwo.leave(); + /** + * Asserts that a user who undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 9.6:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the addition of + * moderator status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForReceivingModerator() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { + @Override + public void moderatorGranted() { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + + // This implicitly tests "The service MUST add the user to the moderator list and then inform the admin of + // success" in §9.6, since it'll throw on either an error IQ or on no response. + mucAsSeenByOne.grantModerator(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 9.6:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the addition of + * moderator status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForWitnessingModerator() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void moderatorGranted(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByThree.join(nicknameThree); + + mucAsSeenByOne.grantModerator(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + + } + + /** + * Asserts that a user who undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 9.7:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * moderator status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForRemovingModerator() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { + @Override + public void moderatorRevoked() { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + + mucAsSeenByOne.grantModerator(nicknameTwo); + mucAsSeenByOne.revokeModerator(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 9.6:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * moderator status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForWitnessingModeratorRemoval() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void moderatorRevoked(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByThree.join(nicknameThree); + + mucAsSeenByOne.grantModerator(nicknameTwo); + mucAsSeenByOne.revokeModerator(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user in an unmoderated room who undergoes an afilliation change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 8.4:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * voice privileges... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForRevokingVoice() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { + @Override + public void voiceRevoked() { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByOne.revokeVoice(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.1.3:

+ *
+ * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
+ * + *

From XEP-0045 § 8.4:

+ *
+ * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * voice privileges... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucRoleTestForWitnessingRevokingVoice() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void voiceRevoked(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByThree.join(nicknameThree); + + mucAsSeenByOne.revokeVoice(nicknameTwo); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who undergoes an affiliation change receives that change as a presence update + * + *

From XEP-0045 § 5.2.2:

+ *
+ * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that + * to all occupants... + *
+ * + *

From XEP-0045 § 10.6:

+ *
+ * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the granting of admin status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucAffiliationTestForReceivingAdmin() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + + mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { + @Override + public void adminGranted() { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + + // This implicitly tests "The service MUST add the user to the admin list and then inform the owner of success" in §10.6, since it'll throw on either an error IQ or on no response. + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who is present when another user undergoes an affiliation change receives that change as a + * presence update + * + *

From XEP-0045 § 5.2.2:

+ *
+ * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that + * to all occupants... + *
+ * + *

From XEP-0045 § 10.6:

+ *
+ * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the granting of admin status... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucAffiliationTestForWitnessingAdmin() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void adminGranted(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByThree.join(nicknameThree); + + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.2.2:

+ *
+ * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to + * all occupants... + *
+ * + *

From XEP-0045 § 10.7:

+ *
+ * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the loss of admin status by sending a presence element... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucAffiliationTestForRemovingAdmin() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { + @Override + public void adminRevoked() { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + mucAsSeenByOne.revokeAdmin(conTwo.getUser().asEntityBareJid()); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } + } + + /** + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

From XEP-0045 § 5.2.2:

+ *
+ * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to + * all occupants... + *
+ * + *

From XEP-0045 § 10.7:

+ *
+ * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the loss of admin status by sending a presence element... + *
+ * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucAffiliationTestForWitnessingAdminRemoval() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest"); + + MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); + MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); + + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + + mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void adminRevoked(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + + createMUC(mucAsSeenByOne, "one-" + randomString); + final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); + final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); + mucAsSeenByTwo.join(nicknameTwo); + mucAsSeenByThree.join(nicknameThree); + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + + mucAsSeenByOne.revokeAdmin(conTwo.getUser().asEntityBareJid()); + try { + resultSyncPoint.waitForResult(timeout); + } finally { + tryDestroy(mucAsSeenByOne); + } } @SmackIntegrationTest public void mucDestroyTest() throws TimeoutException, Exception { - EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from("smack-inttest-join-leave-" + randomString), - mucService.getDomain()); + EntityBareJid mucAddress = getRandomRoom("smack-inttest-join-leave"); MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); muc.join(Resourcepart.from("nick-one")); @@ -161,4 +681,38 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { assertEquals(0, muc.getOccupantsCount()); assertNull(muc.getNickname()); } + + /** + * Gets a random room name + * + * @param prefix A prefix to add to the room name for descriptive purposes + */ + private EntityBareJid getRandomRoom(String prefix) throws XmppStringprepException { + final String roomNameLocal = String.join("-", prefix, testRunId, StringUtils.insecureRandomString(6)); + return JidCreate.entityBareFrom(Localpart.from(roomNameLocal), mucService.getDomain()); + } + + /** + * Destroys a MUC room, ignoring any exceptions. + * + * @param muc The room to destroy (can be null). + */ + static void tryDestroy(final MultiUserChat muc) { + if (muc == null) { + return; + } + try { + muc.destroy("test fixture teardown", null); + } catch (Exception ex) { + LOGGER.log(Level.FINEST, "Failed to tear down a randomly generated MUC (" + muc.getRoom().toString() + ") used as a test fixture. Continuing anyway.", ex); + } + } + + private static void createMUC(MultiUserChat muc, String resourceName) throws NoResponseException, XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException, XmppStringprepException { + MucCreateConfigFormHandle handle = muc.create(Resourcepart.from(resourceName)); + if (handle != null) { + handle.makeInstant(); + } + } + }