mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 06:12:05 +01:00
commit
35c645e24b
2 changed files with 584 additions and 26 deletions
|
@ -629,6 +629,7 @@ public class MultiUserChat {
|
||||||
* joining the room, the room will decide the amount of history to send.
|
* joining the room, the room will decide the amount of history to send.
|
||||||
*
|
*
|
||||||
* @param nickname the nickname to use.
|
* @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 NoResponseException if there was no response from the remote entity.
|
||||||
* @throws XMPPErrorException if an error occurs joining the room. In particular, a
|
* @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
|
* 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 InterruptedException if the calling thread was interrupted.
|
||||||
* @throws NotAMucServiceException if the entity is not a MUC serivce.
|
* @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 {
|
NotConnectedException, InterruptedException, NotAMucServiceException {
|
||||||
MucEnterConfiguration.Builder builder = getEnterConfigurationBuilder(nickname);
|
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.
|
* decide to create a new room or not.
|
||||||
*
|
*
|
||||||
* @param mucEnterConfiguration the configuration used to enter the MUC.
|
* @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
|
* @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
|
* 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
|
* 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 InterruptedException if the calling thread was interrupted.
|
||||||
* @throws NotAMucServiceException if the entity is not a MUC serivce.
|
* @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 {
|
throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException, NotAMucServiceException {
|
||||||
// If we've already joined the room, leave it before joining under a new
|
// If we've already joined the room, leave it before joining under a new
|
||||||
// nickname.
|
// nickname.
|
||||||
|
@ -714,7 +717,8 @@ public class MultiUserChat {
|
||||||
LOGGER.log(Level.WARNING, "Could not leave MUC prior joining, assuming we are not joined", e);
|
LOGGER.log(Level.WARNING, "Could not leave MUC prior joining, assuming we are not joined", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enter(mucEnterConfiguration);
|
Presence reflectedJoinPresence = enter(mucEnterConfiguration);
|
||||||
|
return reflectedJoinPresence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.jivesoftware.smack.MessageListener;
|
import org.jivesoftware.smack.MessageListener;
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
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.smack.util.StringUtils;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.muc.MultiUserChat.MucCreateConfigFormHandle;
|
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.jivesoftware.smackx.muc.packet.MUCUser;
|
||||||
|
|
||||||
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
|
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.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
|
||||||
import org.jxmpp.jid.DomainBareJid;
|
import org.jxmpp.jid.DomainBareJid;
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.jid.parts.Localpart;
|
import org.jxmpp.jid.parts.Localpart;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
|
@ -56,6 +56,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
|
|
||||||
private final MultiUserChatManager mucManagerOne;
|
private final MultiUserChatManager mucManagerOne;
|
||||||
private final MultiUserChatManager mucManagerTwo;
|
private final MultiUserChatManager mucManagerTwo;
|
||||||
|
private final MultiUserChatManager mucManagerThree;
|
||||||
private final DomainBareJid mucService;
|
private final DomainBareJid mucService;
|
||||||
|
|
||||||
public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment)
|
public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||||
|
@ -64,6 +65,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
super(environment);
|
super(environment);
|
||||||
mucManagerOne = MultiUserChatManager.getInstanceFor(conOne);
|
mucManagerOne = MultiUserChatManager.getInstanceFor(conOne);
|
||||||
mucManagerTwo = MultiUserChatManager.getInstanceFor(conTwo);
|
mucManagerTwo = MultiUserChatManager.getInstanceFor(conTwo);
|
||||||
|
mucManagerThree = MultiUserChatManager.getInstanceFor(conThree);
|
||||||
|
|
||||||
List<DomainBareJid> services = mucManagerOne.getMucServiceDomains();
|
List<DomainBareJid> services = mucManagerOne.getMucServiceDomains();
|
||||||
if (services.isEmpty()) {
|
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
|
@SmackIntegrationTest
|
||||||
public void mucJoinLeaveTest() throws XmppStringprepException, NotAMucServiceException, NoResponseException,
|
public void mucJoinTest() throws Exception {
|
||||||
XMPPErrorException, NotConnectedException, InterruptedException, MucNotJoinedException {
|
EntityBareJid mucAddress = getRandomRoom("smack-inttest-join-leave");
|
||||||
EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from("smack-inttest-join-leave-" + randomString),
|
|
||||||
mucService.getDomain());
|
|
||||||
|
|
||||||
MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress);
|
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
|
@SmackIntegrationTest
|
||||||
public void mucTest() throws Exception {
|
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 mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
|
||||||
MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress);
|
MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress);
|
||||||
|
@ -112,24 +159,497 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MucCreateConfigFormHandle handle = mucAsSeenByOne.createOrJoin(Resourcepart.from("one-" + randomString));
|
createMUC(mucAsSeenByOne, "one-" + randomString);
|
||||||
if (handle != null) {
|
|
||||||
handle.makeInstant();
|
|
||||||
}
|
|
||||||
mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString));
|
mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString));
|
||||||
|
|
||||||
mucAsSeenByOne.sendMessage(mucMessage);
|
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
|
@SmackIntegrationTest
|
||||||
public void mucDestroyTest() throws TimeoutException, Exception {
|
public void mucDestroyTest() throws TimeoutException, Exception {
|
||||||
|
|
||||||
EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from("smack-inttest-join-leave-" + randomString),
|
EntityBareJid mucAddress = getRandomRoom("smack-inttest-join-leave");
|
||||||
mucService.getDomain());
|
|
||||||
|
|
||||||
MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress);
|
MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress);
|
||||||
muc.join(Resourcepart.from("nick-one"));
|
muc.join(Resourcepart.from("nick-one"));
|
||||||
|
@ -161,4 +681,38 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
||||||
assertEquals(0, muc.getOccupantsCount());
|
assertEquals(0, muc.getOccupantsCount());
|
||||||
assertNull(muc.getNickname());
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue