Merge pull request #446 from Fishbowler/add_muc_tests

Add MUC tests
This commit is contained in:
Florian Schmaus 2021-04-08 10:23:37 +02:00 committed by GitHub
commit 35c645e24b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 584 additions and 26 deletions

View File

@ -629,6 +629,7 @@ public class MultiUserChat {
* joining the room, the room will decide the amount of history to send.
*
* @param nickname the nickname to use.
* @return the leave self-presence as reflected by the MUC.
* @throws NoResponseException if there was no response from the remote entity.
* @throws XMPPErrorException if an error occurs joining the room. In particular, a
* 401 error can occur if no password was provided and one is required; or a
@ -641,10 +642,11 @@ public class MultiUserChat {
* @throws InterruptedException if the calling thread was interrupted.
* @throws NotAMucServiceException if the entity is not a MUC serivce.
*/
public void join(Resourcepart nickname) throws NoResponseException, XMPPErrorException,
public Presence join(Resourcepart nickname) throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException, NotAMucServiceException {
MucEnterConfiguration.Builder builder = getEnterConfigurationBuilder(nickname);
join(builder.build());
Presence reflectedJoinPresence = join(builder.build());
return reflectedJoinPresence;
}
/**
@ -691,6 +693,7 @@ public class MultiUserChat {
* decide to create a new room or not.
*
* @param mucEnterConfiguration the configuration used to enter the MUC.
* @return the join self-presence as reflected by the MUC.
* @throws XMPPErrorException if an error occurs joining the room. In particular, a
* 401 error can occur if no password was provided and one is required; or a
* 403 error can occur if the user is banned; or a
@ -702,7 +705,7 @@ public class MultiUserChat {
* @throws InterruptedException if the calling thread was interrupted.
* @throws NotAMucServiceException if the entity is not a MUC serivce.
*/
public synchronized void join(MucEnterConfiguration mucEnterConfiguration)
public synchronized Presence join(MucEnterConfiguration mucEnterConfiguration)
throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException, NotAMucServiceException {
// If we've already joined the room, leave it before joining under a new
// nickname.
@ -714,7 +717,8 @@ public class MultiUserChat {
LOGGER.log(Level.WARNING, "Could not leave MUC prior joining, assuming we are not joined", e);
}
}
enter(mucEnterConfiguration);
Presence reflectedJoinPresence = enter(mucEnterConfiguration);
return reflectedJoinPresence;
}
/**

View File

@ -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<DomainBareJid> 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).
*
* <p>From XEP-0045 § 7.2.2:</p>
* <blockquote>
* ...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)
* </blockquote>
*
* @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).
*
* <p>From XEP-0045 § 7.14:</p>
* <blockquote>
* 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"
* </blockquote>
*
* @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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 9.6:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the addition of
* moderator status...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 9.6:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the addition of
* moderator status...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 9.7:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the removal of
* moderator status...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 9.6:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the removal of
* moderator status...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 8.4:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the removal of
* voice privileges...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.1.3:</p>
* <blockquote>
* ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 8.4:</p>
* <blockquote>
* The service MUST then send updated presence from this individual to all occupants, indicating the removal of
* voice privileges...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.2.2:</p>
* <blockquote>
* ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 10.6:</p>
* <blockquote>
* 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...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.2.2:</p>
* <blockquote>
* ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that
* to all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 10.6:</p>
* <blockquote>
* 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...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.2.2:</p>
* <blockquote>
* ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to
* all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 10.7:</p>
* <blockquote>
* 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...
* </blockquote>
*
* @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<String, Exception> 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
*
* <p>From XEP-0045 § 5.2.2:</p>
* <blockquote>
* ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to
* all occupants...
* </blockquote>
*
* <p>From XEP-0045 § 10.7:</p>
* <blockquote>
* 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...
* </blockquote>
*
* @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<String, Exception> 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();
}
}
}