org.jivesoftware.smackx.muc.MultiUserChatEntityIntegrationTest Maven / Gradle / Ivy
The newest version!
/**
*
* Copyright 2021 Dan Caseley
*
* 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.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import java.util.Map;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException;
import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException;
import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException;
import org.jivesoftware.smackx.muc.packet.MUCInitialPresence;
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.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
@SpecificationReference(document = "XEP-0045", version = "1.34.6")
public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatIntegrationTest {
public MultiUserChatEntityIntegrationTest(SmackIntegrationTestEnvironment environment)
throws SmackException.NoResponseException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException {
super(environment);
}
/**
* Asserts that a MUC service can be discovered.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.1", quote =
"An entity often discovers a MUC service by sending a Service Discovery items (\"disco#items\") request to " +
"its own server. The server then returns the services that are associated with it.")
public void mucTestForDiscoveringMuc() throws Exception {
// This repeats some logic from the `AbstractMultiUserChatIntegrationTest` constructor, but is preserved here
// as an explicit test, because that might not always be true.
List services = ServiceDiscoveryManager.getInstanceFor(conOne).findServices(MUCInitialPresence.NAMESPACE, true, false);
assertFalse(services.isEmpty(), "Expected to be able to find MUC services on the domain that '" + conOne.getUser() + "' is connecting to (but could not).");
}
/**
* Asserts that a MUC service can have its features discovered.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.2", quote =
"An entity may wish to discover if a service implements the Multi-User Chat protocol; in order to do so, it " +
"sends a service discovery information (\"disco#info\") query to the MUC service's JID. The service MUST " +
"return its identity and the features it supports.")
public void mucTestForDiscoveringFeatures() throws Exception {
DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(conOne).discoverInfo(mucService);
assertFalse(info.getIdentities().isEmpty(), "Expected the service discovery information for service " + mucService + " to include identities (but it did not).");
assertFalse(info.getFeatures().isEmpty(), "Expected the service discovery information for service " + mucService + " to include features (but it did not).");
}
/**
* Asserts that a MUC Service lists its public rooms.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.3", quote =
"The service discovery items (\"disco#items\") protocol enables an entity to query a service for a list of " +
"associated items, which in the case of a chat service would consist of the specific chat rooms hosted by the" +
"service. The service SHOULD return a full list of the public rooms it hosts (i.e., not return any rooms that" +
"are hidden).")
public void mucTestForDiscoveringRooms() throws Exception {
EntityBareJid mucAddressPublic = getRandomRoom("smack-inttest-publicroom");
MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddressPublic);
EntityBareJid mucAddressHidden = getRandomRoom("smack-inttest-hiddenroom");
MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddressHidden);
createMuc(mucAsSeenByOne, Resourcepart.from("one-" + randomString));
Map rooms;
try {
createHiddenMuc(mucAsSeenByTwo, Resourcepart.from("two-" + randomString));
rooms = mucManagerThree.getRoomsHostedBy(mucService);
} finally {
tryDestroy(mucAsSeenByOne);
tryDestroy(mucAsSeenByTwo);
}
assertTrue(rooms.containsKey(mucAddressPublic), "Expected the disco response from " + mucService + " to include the public room " + mucAddressPublic + " (but it did not).");
assertFalse(rooms.containsKey(mucAddressHidden), "Expected the disco response from " + mucService + " to not include the hidden room " + mucAddressHidden + " (but it did).");
}
/**
* Asserts that a MUC Service returns disco info for a room.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.4", quote =
"Using the disco#info protocol, an entity may also query a specific chat room for more detailed information " +
"about the room....The room MUST return its identity and SHOULD return the features it supports")
public void mucTestForDiscoveringRoomInfo() throws Exception {
EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoinfo");
MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
createMuc(mucAsSeenByOne, Resourcepart.from("one-" + randomString));
DiscoverInfo discoInfo;
try {
// Use SDM because mucManagerOne.getRoomInfo(mucAddress) might not use Disco
discoInfo = ServiceDiscoveryManager.getInstanceFor(conOne).discoverInfo(mucAddress);
} finally {
tryDestroy(mucAsSeenByOne);
}
assertFalse(discoInfo.getIdentities().isEmpty(), "Expected the service discovery information for room " + mucAddress + " to include identities (but it did not).");
assertFalse(discoInfo.getFeatures().isEmpty(), "Expected the service discovery information for room " + mucAddress + " to include features (but it did not).");
assertTrue(discoInfo.getFeatures().stream().anyMatch(feature -> MultiUserChatConstants.NAMESPACE.equals(feature.getVar())), "Expected the service discovery information for room " + mucAddress + " to include the '" + MultiUserChatConstants.NAMESPACE + "' feature (but it did not).");
}
/**
* Asserts that a MUC Service returns disco info for a room's items.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.5", quote =
"An entity MAY also query a specific chat room for its associated items. An implementation MAY return a list " +
"of existing occupants if that information is publicly available, or return no list at all if this " +
"information is kept private.")
public void mucTestForDiscoveringRoomItems() throws Exception {
EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoitems");
MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
createMuc(mucAsSeenByOne, Resourcepart.from("one-" + randomString));
DiscoverItems roomItems;
try {
roomItems = ServiceDiscoveryManager.getInstanceFor(conTwo).discoverItems(mucAddress);
} finally {
tryDestroy(mucAsSeenByOne);
}
assertEquals(1, roomItems.getItems().size(), "Unexpected amount of disco items for " + mucAddress);
}
/**
* Asserts that a non-occupant receives a Bad Request error when attempting to query an occupant by their
* occupant JID.
*
* @throws Exception when errors occur
*/
@SmackIntegrationTest(section = "6.6", quote =
"If a non-occupant attempts to send a disco request to an address of the form , a MUC " +
"service MUST return a error")
public void mucTestForRejectingDiscoOnRoomOccupantByNonOccupant() throws Exception {
EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoitems");
MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress);
final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString);
createMuc(mucAsSeenByOne, nicknameOne);
final EntityFullJid mucAsSeenByOneUserJid = mucAsSeenByOne.getMyRoomJid();
// Ensure that we do not invoke discoverItems() with null below. This should not happen, as the room JID should
// be non-null after we created and joined the room. But it can not hurt to explicitly test for it either.
if (mucAsSeenByOneUserJid == null) {
throw new AssertionError();
}
XMPPException.XMPPErrorException xe;
try {
xe = assertThrows(XMPPException.XMPPErrorException.class,
() -> ServiceDiscoveryManager.getInstanceFor(conTwo).discoverItems(mucAsSeenByOneUserJid),
"Expected an XMPP error when " + conTwo.getUser() + " was trying to discover items of " + mucAsSeenByOneUserJid);
} finally {
tryDestroy(mucAsSeenByOne);
}
final StanzaError.Condition expectedCondition;
switch (sinttestConfiguration.compatibilityMode) {
default:
expectedCondition = StanzaError.Condition.bad_request;
break;
case ejabberd:
expectedCondition = StanzaError.Condition.not_acceptable;
break;
}
assertEquals(expectedCondition, xe.getStanzaError().getCondition(),
"Unexpected error condition in error returned when " + conTwo.getUser() + " was trying to discover items of " + mucAsSeenByOneUserJid);
}
}