AbstractMultiUserChatIntegrationTest.java

  1. /**
  2.  *
  3.  * Copyright 2021-2024 Florian Schmaus
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.jivesoftware.smackx.muc;

  18. import java.util.List;
  19. import java.util.logging.Level;

  20. import org.jivesoftware.smack.SmackException;
  21. import org.jivesoftware.smack.XMPPException;
  22. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  23. import org.jivesoftware.smack.packet.StanzaError;
  24. import org.jivesoftware.smack.util.StringUtils;
  25. import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException;
  26. import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException;
  27. import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException;
  28. import org.jivesoftware.smackx.xdata.form.FillableForm;
  29. import org.jivesoftware.smackx.xdata.form.Form;

  30. import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
  31. import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
  32. import org.igniterealtime.smack.inttest.TestNotPossibleException;
  33. import org.jxmpp.jid.DomainBareJid;
  34. import org.jxmpp.jid.EntityBareJid;
  35. import org.jxmpp.jid.impl.JidCreate;
  36. import org.jxmpp.jid.parts.Localpart;
  37. import org.jxmpp.jid.parts.Resourcepart;
  38. import org.jxmpp.stringprep.XmppStringprepException;


  39. public abstract class AbstractMultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {

  40.     final String randomString = StringUtils.insecureRandomString(6);

  41.     final MultiUserChatManager mucManagerOne;
  42.     final MultiUserChatManager mucManagerTwo;
  43.     final MultiUserChatManager mucManagerThree;
  44.     final DomainBareJid mucService;

  45.     public AbstractMultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment)
  46.             throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
  47.             InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException {
  48.         super(environment);
  49.         mucManagerOne = MultiUserChatManager.getInstanceFor(conOne);
  50.         mucManagerTwo = MultiUserChatManager.getInstanceFor(conTwo);
  51.         mucManagerThree = MultiUserChatManager.getInstanceFor(conThree);

  52.         List<DomainBareJid> services = mucManagerOne.getMucServiceDomains();
  53.         if (services.isEmpty()) {
  54.             throw new TestNotPossibleException("No MUC (XEP-0045) service found");
  55.         }

  56.         DomainBareJid needle = null;
  57.         for (final DomainBareJid service : services) {
  58.             MultiUserChat multiUserChat = null;
  59.             try {
  60.                 String roomNameLocal = String.join("-", "smack-inttest-abstract", testRunId, StringUtils.insecureRandomString(6));
  61.                 EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from(roomNameLocal), service.getDomain());
  62.                 multiUserChat = mucManagerOne.getMultiUserChat(mucAddress);

  63.                 createMuc(multiUserChat, "test");

  64.                 needle = service;
  65.                 break;
  66.             } catch (XMPPException.XMPPErrorException e) {
  67.                 mucCreationDisallowedOrThrow(e);
  68.                 LOGGER.log(Level.FINER, "MUC service " + service + " does not allow MUC creation", e);
  69.             } finally {
  70.                 tryDestroy(multiUserChat);
  71.             }
  72.         }

  73.         if (needle == null) {
  74.             throw new TestNotPossibleException("No MUC (XEP-0045) service found that allows test users to createa new room. Considered MUC services: " + services);
  75.         }
  76.         mucService = needle;
  77.     }

  78.     static void mucCreationDisallowedOrThrow(XMPPException.XMPPErrorException e) throws XMPPErrorException {
  79.         StanzaError.Condition condition = e.getStanzaError().getCondition();
  80.         if (condition == StanzaError.Condition.not_allowed)
  81.             return;
  82.         throw e;
  83.     }

  84.     /**
  85.      * Gets a random room name.
  86.      *
  87.      * @param prefix A prefix to add to the room name for descriptive purposes
  88.      * @return the bare JID of a random room
  89.      * @throws XmppStringprepException if the prefix isn't a valid XMPP Localpart
  90.      */
  91.     public EntityBareJid getRandomRoom(String prefix) throws XmppStringprepException {
  92.         final String roomNameLocal = String.join("-", prefix, testRunId, StringUtils.insecureRandomString(6));
  93.         return JidCreate.entityBareFrom(Localpart.from(roomNameLocal), mucService.getDomain());
  94.     }

  95.     /**
  96.      * Destroys a MUC room, ignoring any exceptions.
  97.      *
  98.      * @param muc The room to destroy (can be null).
  99.      * @throws InterruptedException if the calling thread was interrupted.
  100.      * @throws SmackException.NotConnectedException if the XMPP connection is not connected.
  101.      * @throws XMPPException.XMPPErrorException if there was an XMPP error returned.
  102.      * @throws SmackException.NoResponseException if there was no response from the remote entity.
  103.      */
  104.     static void tryDestroy(final MultiUserChat muc) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException {
  105.         if (muc == null) {
  106.             return;
  107.         }
  108.         muc.destroy("test fixture teardown", null);
  109.     }

  110.     static void createMuc(MultiUserChat muc, Resourcepart resourceName) throws
  111.             SmackException.NoResponseException, XMPPException.XMPPErrorException,
  112.             InterruptedException, MultiUserChatException.MucAlreadyJoinedException,
  113.             SmackException.NotConnectedException,
  114.             MultiUserChatException.MissingMucCreationAcknowledgeException,
  115.             MultiUserChatException.NotAMucServiceException {
  116.         muc.create(resourceName).makeInstant();
  117.     }

  118.     static void createMuc(MultiUserChat muc, String nickname) throws
  119.             XmppStringprepException, MultiUserChatException.MucAlreadyJoinedException,
  120.             XMPPException.XMPPErrorException, SmackException.NotConnectedException,
  121.             MultiUserChatException.MissingMucCreationAcknowledgeException,
  122.             SmackException.NoResponseException, InterruptedException,
  123.             MultiUserChatException.NotAMucServiceException {
  124.         createMuc(muc, Resourcepart.from(nickname));
  125.     }

  126.     static void createMembersOnlyMuc(MultiUserChat muc, Resourcepart resourceName) throws
  127.             SmackException.NoResponseException, XMPPException.XMPPErrorException,
  128.             InterruptedException, MultiUserChatException.MucAlreadyJoinedException,
  129.             SmackException.NotConnectedException,
  130.             MultiUserChatException.MissingMucCreationAcknowledgeException,
  131.             MultiUserChatException.MucConfigurationNotSupportedException,
  132.             MultiUserChatException.NotAMucServiceException {
  133.         muc.create(resourceName)
  134.             .getConfigFormManager()
  135.             .makeMembersOnly()
  136.             .submitConfigurationForm();
  137.     }

  138.     static void createModeratedMuc(MultiUserChat muc, Resourcepart resourceName)
  139.                     throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException,
  140.                     MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException,
  141.                     MultiUserChatException.MissingMucCreationAcknowledgeException,
  142.                     MultiUserChatException.NotAMucServiceException,
  143.                     MultiUserChatException.MucConfigurationNotSupportedException {
  144.         muc.create(resourceName)
  145.             .getConfigFormManager()
  146.             .makeModerated()
  147.             .submitConfigurationForm();
  148.     }

  149.     static void createHiddenMuc(MultiUserChat muc, Resourcepart resourceName)
  150.                     throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException,
  151.                     MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException,
  152.                     MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException, XmppStringprepException,
  153.                     MultiUserChatException.MucConfigurationNotSupportedException {
  154.         muc.create(resourceName)
  155.             .getConfigFormManager()
  156.             .makeHidden()
  157.             .submitConfigurationForm();
  158.     }

  159.     /**
  160.      * Creates a non-anonymous room.
  161.      *
  162.      * <p>From XEP-0045 § 10.1.3:</p>
  163.      * <blockquote>
  164.      * Note: The _whois configuration option specifies whether the room is non-anonymous (a value of "anyone"),
  165.      * semi-anonymous (a value of "moderators"), or fully anonymous (a value of "none", not shown here).
  166.      * </blockquote>
  167.      */
  168.     static void createNonAnonymousMuc(MultiUserChat muc, Resourcepart resourceName) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException {
  169.         muc.create(resourceName);
  170.         Form configForm = muc.getConfigurationForm();
  171.         FillableForm answerForm = configForm.getFillableForm();
  172.         answerForm.setAnswer("muc#roomconfig_whois", "anyone");
  173.         muc.sendConfigurationForm(answerForm);
  174.     }

  175.     /**
  176.      * Creates a semi-anonymous room.
  177.      *
  178.      * <p>From XEP-0045 § 10.1.3:</p>
  179.      * <blockquote>
  180.      * Note: The _whois configuration option specifies whether the room is non-anonymous (a value of "anyone"),
  181.      * semi-anonymous (a value of "moderators"), or fully anonymous (a value of "none", not shown here).
  182.      * </blockquote>
  183.      */
  184.     static void createSemiAnonymousMuc(MultiUserChat muc, Resourcepart resourceName) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException {
  185.         muc.create(resourceName);
  186.         Form configForm = muc.getConfigurationForm();
  187.         FillableForm answerForm = configForm.getFillableForm();
  188.         answerForm.setAnswer("muc#roomconfig_whois", "moderators");
  189.         muc.sendConfigurationForm(answerForm);
  190.     }

  191.     /**
  192.      * Creates a password-protected room.
  193.      */
  194.     static void createPasswordProtectedMuc(MultiUserChat muc, Resourcepart resourceName, String password) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException {
  195.         muc.create(resourceName);
  196.         Form configForm = muc.getConfigurationForm();
  197.         FillableForm answerForm = configForm.getFillableForm();
  198.         answerForm.setAnswer("muc#roomconfig_passwordprotectedroom", true);
  199.         answerForm.setAnswer("muc#roomconfig_roomsecret", password);
  200.         muc.sendConfigurationForm(answerForm);
  201.     }

  202.     static void setMaxUsers(MultiUserChat muc, int maxUsers) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException {
  203.         Form configForm = muc.getConfigurationForm();
  204.         FillableForm answerForm = configForm.getFillableForm();
  205.         answerForm.setAnswer("muc#roomconfig_maxusers", maxUsers);
  206.         muc.sendConfigurationForm(answerForm);
  207.     }

  208. }