MultiUserChatIntegrationTest.java
- /**
- *
- * Copyright 2015-2024 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.smackx.muc;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertFalse;
- import static org.junit.jupiter.api.Assertions.assertNull;
- import static org.junit.jupiter.api.Assertions.assertThrows;
- import java.util.Set;
- import java.util.concurrent.TimeoutException;
- import org.jivesoftware.smack.MessageListener;
- import org.jivesoftware.smack.SmackException;
- import org.jivesoftware.smack.SmackException.NoResponseException;
- import org.jivesoftware.smack.SmackException.NotConnectedException;
- import org.jivesoftware.smack.XMPPException;
- import org.jivesoftware.smack.XMPPException.XMPPErrorException;
- import org.jivesoftware.smack.packet.Message;
- import org.jivesoftware.smack.packet.StanzaError;
- import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException;
- import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException;
- import org.jivesoftware.smackx.muc.MultiUserChatException.MucConfigurationNotSupportedException;
- import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException;
- import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
- import org.igniterealtime.smack.inttest.TestNotPossibleException;
- import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest;
- import org.igniterealtime.smack.inttest.annotations.SpecificationReference;
- import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
- import org.jxmpp.jid.EntityBareJid;
- import org.jxmpp.jid.parts.Resourcepart;
- import org.jxmpp.stringprep.XmppStringprepException;
- @SpecificationReference(document = "XEP-0045", version = "1.34.6")
- public class MultiUserChatIntegrationTest extends AbstractMultiUserChatIntegrationTest {
- public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment)
- throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
- InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException {
- super(environment);
- }
- @SmackIntegrationTest
- public void mucTest() throws Exception {
- EntityBareJid mucAddress = getRandomRoom("smack-inttest-message");
- MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
- MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress);
- final String mucMessage = "Smack Integration Test MUC Test Message " + randomString;
- final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint();
- mucAsSeenByTwo.addMessageListener(new MessageListener() {
- @Override
- public void processMessage(Message message) {
- String body = message.getBody();
- if (mucMessage.equals(body)) {
- resultSyncPoint.signal();
- }
- }
- });
- createMuc(mucAsSeenByOne, "one-" + randomString);
- mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString));
- mucAsSeenByOne.sendMessage(mucMessage);
- try {
- assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to receive message that was sent by " + conOne.getUser() + " in room " + mucAddress + " (but it did not).");
- } finally {
- tryDestroy(mucAsSeenByOne);
- }
- }
- /**
- * Asserts that an owner is notified of room destruction when they destroy a room.
- *
- * @throws TimeoutException when roomDestroyed event doesn't get fired
- * @throws Exception when other errors occur
- */
- @SmackIntegrationTest(section = "10.9", quote =
- "A room owner MUST be able to destroy a room, especially if the room is persistent... The room removes all " +
- "users from the room... and destroys the room")
- public void mucDestroyOwnerTest() throws TimeoutException, Exception {
- EntityBareJid mucAddress = getRandomRoom("smack-inttest-destroy-owner");
- MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress);
- createMuc(muc, Resourcepart.from("one-" + randomString));
- // These would be a test implementation bug, not assertion failure.
- if (!mucManagerOne.getJoinedRooms().contains(mucAddress)) {
- tryDestroy(muc);
- throw new IllegalStateException("Expected user to have joined a room '" + mucAddress + "' (but does not appear to have done so).");
- }
- final SimpleResultSyncPoint mucDestroyed = new SimpleResultSyncPoint();
- UserStatusListener userStatusListener = new UserStatusListener() {
- @Override
- public void roomDestroyed(MultiUserChat alternateMUC, String password, String reason) {
- mucDestroyed.signal();
- }
- };
- muc.addUserStatusListener(userStatusListener);
- try {
- muc.destroy("Dummy reason", null);
- assertResult(mucDestroyed, "Expected " + conOne.getUser() + " to be notified of destruction of room " + mucAddress + " (but was not).");
- } finally {
- muc.removeUserStatusListener(userStatusListener);
- }
- Set<EntityBareJid> joinedRooms = mucManagerOne.getJoinedRooms();
- assertFalse(muc.isJoined(), "Expected " + conOne.getUser() + " to no longer be in room " + mucAddress + " after it was destroyed, but it is still in.");
- assertEquals(0, joinedRooms.size(), "Expected " + conOne.getUser() + " to no longer be in any rooms after " + mucAddress + " was destroyed. But it is still in " + joinedRooms);
- assertEquals(0, muc.getOccupantsCount(), "Expected room " + mucAddress + " to no longer have any occupants after it was destroyed (but it has).");
- assertNull(muc.getNickname());
- }
- /**
- * Asserts that an occupant of a room is notified when a room is destroyed.
- *
- * @throws TimeoutException when roomDestroyed event doesn't get fired
- * @throws Exception when other errors occur
- */
- @SmackIntegrationTest(section = "10.9", quote =
- "A room owner MUST be able to destroy a room, especially if the room is persistent... The room removes all " +
- "users from the room... and destroys the room")
- public void mucDestroyTestOccupant() throws TimeoutException, Exception {
- EntityBareJid mucAddress = getRandomRoom("smack-inttest-destroy-occupant");
- MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress);
- MultiUserChat mucAsSeenByParticipant = mucManagerTwo.getMultiUserChat(mucAddress);
- createMuc(mucAsSeenByOwner, Resourcepart.from("one-" + randomString));
- // These would be a test implementation bug, not assertion failure.
- mucAsSeenByParticipant.join(Resourcepart.from("two-" + randomString));
- if (!mucManagerTwo.getJoinedRooms().contains(mucAddress)) {
- tryDestroy(mucAsSeenByOwner);
- throw new IllegalStateException("Expected user to have joined a room '" + mucAddress + "' (but does not appear to have done so).");
- }
- final SimpleResultSyncPoint mucDestroyed = new SimpleResultSyncPoint();
- UserStatusListener userStatusListener = new UserStatusListener() {
- @Override
- public void roomDestroyed(MultiUserChat alternateMUC, String password, String reason) {
- mucDestroyed.signal();
- }
- };
- mucAsSeenByParticipant.addUserStatusListener(userStatusListener);
- try {
- mucAsSeenByOwner.destroy("Dummy reason", null);
- assertResult(mucDestroyed, "Expected " + conTwo.getUser() + " to be notified of destruction of room " + mucAddress + " (but was not).");
- } finally {
- mucAsSeenByParticipant.removeUserStatusListener(userStatusListener);
- }
- Set<EntityBareJid> joinedRooms = mucManagerTwo.getJoinedRooms();
- assertFalse(mucAsSeenByParticipant.isJoined(), "Expected " + conTwo.getUser() + " to no longer be in room " + mucAddress + " after it was destroyed, but it is still in.");
- assertEquals(0, joinedRooms.size(), "Expected " + conTwo.getUser() + " to no longer be in any rooms after " + mucAddress + " was destroyed. But it is still in " + joinedRooms);
- assertEquals(0, mucAsSeenByParticipant.getOccupantsCount(), "Expected room " + mucAddress + " to no longer have any occupants after it was destroyed (but it has).");
- assertNull(mucAsSeenByParticipant.getNickname());
- }
- @SmackIntegrationTest
- public void mucNameChangeTest()
- throws XmppStringprepException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException,
- NotAMucServiceException, NoResponseException, XMPPErrorException, NotConnectedException,
- InterruptedException, MucConfigurationNotSupportedException {
- EntityBareJid mucAddress = getRandomRoom("smack-inttest-muc-name-change");
- MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress);
- createMuc(muc, Resourcepart.from("one-" + randomString));
- final String newRoomName = "New Room Name (" + randomString + ")";
- try {
- muc.getConfigFormManager()
- .setRoomName(newRoomName)
- .submitConfigurationForm();
- MultiUserChatManager mucManager = MultiUserChatManager.getInstanceFor(conTwo);
- RoomInfo roomInfo = mucManager.getRoomInfo(muc.getRoom());
- assertEquals(newRoomName, roomInfo.getName());
- } finally {
- tryDestroy(muc);
- }
- }
- @SmackIntegrationTest(section = "8.1", quote = "modify the subject [...] MUST be denied if the <user@host> of the 'from' address of the request does not match "
- + "the bare JID portion of one of the moderators; in this case, the service MUST return a <forbidden/> error.")
- public void mucTestVisitorNotAllowedToChangeSubject() throws XmppStringprepException, MucAlreadyJoinedException,
- MissingMucCreationAcknowledgeException, NotAMucServiceException, NoResponseException,
- XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException {
- final EntityBareJid mucAddress = getRandomRoom("smack-inttest-visitor-change-subject");
- final MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
- final MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress);
- final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString);
- final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString);
- createMuc(mucAsSeenByOne, nicknameOne);
- try {
- MucConfigFormManager configFormManager = mucAsSeenByOne.getConfigFormManager();
- if (configFormManager.occupantsAreAllowedToChangeSubject()) {
- configFormManager.disallowOccupantsToChangeSubject().submitConfigurationForm();
- }
- mucAsSeenByTwo.join(nicknameTwo);
- final XMPPException.XMPPErrorException e = assertThrows(XMPPException.XMPPErrorException.class, () -> {
- mucAsSeenByTwo.changeSubject("Test Subject Change");
- }, "Expected an error after '" + conTwo.getUser()
- + "' (that is not a moderator) tried to change the subject of room '" + mucAddress
- + "' (but none occurred).");
- assertEquals(StanzaError.Condition.forbidden, e.getStanzaError().getCondition(),
- "Unexpected error condition in the (expected) error that was returned to '"
- + conTwo.getUser() + "' after it tried to change to subject of room '"
- + mucAddress + "' while not being a moderator.");
- } catch (MucConfigurationNotSupportedException e) {
- throw new TestNotPossibleException(e);
- } finally {
- tryDestroy(mucAsSeenByOne);
- }
- }
- @SmackIntegrationTest
- public void mucTestChangeRoomName() throws XmppStringprepException, MucAlreadyJoinedException,
- MissingMucCreationAcknowledgeException, NotAMucServiceException, NoResponseException,
- XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException {
- final EntityBareJid mucAddress = getRandomRoom("smack-inttest-change-room-name");
- final MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
- final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString);
- createMuc(mucAsSeenByOne, nicknameOne);
- try {
- String initialRoomName = "Initial Room Name";
- mucAsSeenByOne.getConfigFormManager().setRoomName(initialRoomName).submitConfigurationForm();
- RoomInfo roomInfo = mucManagerOne.getRoomInfo(mucAddress);
- assertEquals(initialRoomName, roomInfo.getName());
- String newRoomName = "New Room Name";
- mucAsSeenByOne.getConfigFormManager().setRoomName(newRoomName).submitConfigurationForm();
- roomInfo = mucManagerOne.getRoomInfo(mucAddress);
- assertEquals(newRoomName, roomInfo.getName());
- } catch (MucConfigurationNotSupportedException e) {
- throw new TestNotPossibleException(e);
- } finally {
- tryDestroy(mucAsSeenByOne);
- }
- }
- }