/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.vysper.xmpp.modules.core.im.handler; import static org.apache.vysper.xmpp.modules.roster.AskSubscriptionType.ASK_SUBSCRIBE; import static org.apache.vysper.xmpp.modules.roster.SubscriptionType.FROM; import static org.apache.vysper.xmpp.modules.roster.SubscriptionType.NONE; import org.apache.vysper.xmpp.addressing.EntityFormatException; import org.apache.vysper.xmpp.addressing.EntityImpl; import org.apache.vysper.xmpp.stanza.PresenceStanzaType; import org.apache.vysper.xmpp.stanza.Stanza; import org.apache.vysper.xmpp.stanza.StanzaBuilder; import org.apache.vysper.xmpp.stanza.XMPPCoreStanza; import org.apache.vysper.xmpp.state.resourcebinding.BindException; import org.apache.vysper.xmpp.state.resourcebinding.ResourceState; /** */ public class PresenceSubRequestOutHandlerTestCase extends PresenceHandlerBaseTestCase { protected PresenceHandler handler = new PresenceHandler(); public void testUnrelatedApprovesSubscription_Inbound() throws BindException, EntityFormatException { requestSubscribeToUnrelated_Outbound(); assertStanzasDeliveredAndRelayed(0); // now entity 'unrelated' approves the subscription XMPPCoreStanza requestApproval = XMPPCoreStanza.getWrapper(StanzaBuilder.createPresenceStanza( unrelatedUser.getEntityFQ(), initiatingUser.getEntity(), null, PresenceStanzaType.SUBSCRIBED, null, null).build()); handler.executeCore(requestApproval, sessionContext.getServerRuntimeContext(), false, sessionContext); // 3 roster pushes but... for (int i = 1; i <= 3; i++) { Stanza stanza = sessionContext.getNextRecordedResponse(); assertEquals("iq", stanza.getName()); } // ... BUT no subscription approval (presence) or anything additional to the roster pushes assertNull(sessionContext.getNextRecordedResponse()); resetRecordedStanzas(); } private void requestSubscribeToUnrelated_Outbound() { setResourceState(initiatingUser.getBoundResourceId(), ResourceState.AVAILABLE_INTERESTED); // SUBSCRIBE FROM XMPPCoreStanza initialPresence = XMPPCoreStanza.getWrapper(StanzaBuilder .createPresenceStanza(initiatingUser.getEntityFQ(), unrelatedUser.getEntity(), null, PresenceStanzaType.SUBSCRIBE, null, null).build()); handler.executeCore(initialPresence, sessionContext.getServerRuntimeContext(), true, sessionContext); assertEquals(ResourceState.AVAILABLE_INTERESTED, getResourceState()); // 1 to TO + 3 roster pushes assertStanzasDeliveredAndRelayed(1); assertStanzasReceivedDirectly(3); // roster push for 1 interested initiator of _same_ session Stanza initiatorNotification = getNextDirectResponseFor(initiatingUser); assertTrue(checkRosterPush(initiatorNotification, initiatingUser.getEntityFQ(), unrelatedUser.getEntity(), NONE, ASK_SUBSCRIBE)); // no stanzas for not interested assertNull(getNextDirectResponseFor(anotherAvailableUser)); // roster 2 interested resources of _same_ session... // roster push for interested Stanza interestedResourceNotification = getNextDirectResponseFor(anotherInterestedUser); assertTrue(checkRosterPush(interestedResourceNotification, new EntityImpl(initiatingUser.getEntity(), anotherInterestedUser.getBoundResourceId()), unrelatedUser.getEntity(), NONE, ASK_SUBSCRIBE)); assertNull(getNextDirectResponseFor(anotherInterestedUser)); // no more stanzas; // roster push for interested but not avail Stanza interestedNotYetAvailResourceNotification = getNextDirectResponseFor(anotherInterestedNotAvailUser); assertTrue(checkRosterPush(interestedNotYetAvailResourceNotification, new EntityImpl( initiatingUser.getEntity(), anotherInterestedNotAvailUser.getBoundResourceId()), unrelatedUser .getEntity(), NONE, ASK_SUBSCRIBE)); assertNull(getNextDirectResponseFor(anotherInterestedNotAvailUser)); // no more stanzas; // sub request sent to contact assertTrue(checkPresence(unrelatedUser.getNextStanza(), PresenceStanzaType.SUBSCRIBE, initiatingUser .getEntity(), null)); assertNull(unrelatedUser.getNextStanza()); // no other stanza assertTrue(checkRosterItem(unrelatedUser.getEntity(), NONE, ASK_SUBSCRIBE)); resetRecordedStanzas(); } public void testWithFROM() throws BindException, EntityFormatException { setResourceState(initiatingUser.getBoundResourceId(), ResourceState.AVAILABLE_INTERESTED); // SUBSCRIBE FROM XMPPCoreStanza initialPresence = XMPPCoreStanza.getWrapper(StanzaBuilder.createPresenceStanza( initiatingUser.getEntityFQ(), subscribed_FROM.getEntity(), null, PresenceStanzaType.SUBSCRIBE, null, null).build()); handler.executeCore(initialPresence, sessionContext.getServerRuntimeContext(), true, sessionContext); assertEquals(ResourceState.AVAILABLE_INTERESTED, getResourceState()); // 1 to TO + 3 roster pushes assertStanzasDeliveredAndRelayed(1); assertStanzasReceivedDirectly(3); // roster push for 1 interested initiator... Stanza initiatorNotification = getNextDirectResponseFor(initiatingUser); assertTrue(checkRosterPush(initiatorNotification, initiatingUser.getEntityFQ(), subscribed_FROM.getEntity(), FROM, ASK_SUBSCRIBE)); // .. and 2 interested resources of _same_ session Stanza anotherInterestedUserNotification = getNextDirectResponseFor(anotherInterestedUser); assertTrue(checkRosterPush(anotherInterestedUserNotification, anotherInterestedUser.getEntityFQ(), subscribed_FROM.getEntity(), FROM, ASK_SUBSCRIBE)); Stanza anotherInterestedNotAvailUserNotification = getNextDirectResponseFor(anotherInterestedNotAvailUser); assertTrue(checkRosterPush(anotherInterestedNotAvailUserNotification, anotherInterestedNotAvailUser .getEntityFQ(), subscribed_FROM.getEntity(), FROM, ASK_SUBSCRIBE)); assertNull(sessionContext.getNextRecordedResponse()); // no more stanzas // sub request sent to contact assertTrue(checkPresence(subscribed_FROM.getNextStanza(), PresenceStanzaType.SUBSCRIBE, initiatingUser .getEntity(), null)); assertNull(subscribed_FROM.getNextStanza()); // no other stanza assertTrue(checkRosterItem(subscribed_FROM.getEntity(), FROM, ASK_SUBSCRIBE)); } public void testWithTO() throws BindException, EntityFormatException { setResourceState(initiatingUser.getBoundResourceId(), ResourceState.AVAILABLE_INTERESTED); XMPPCoreStanza initialPresence = XMPPCoreStanza.getWrapper(StanzaBuilder .createPresenceStanza(initiatingUser.getEntityFQ(), subscribed_TO.getEntity(), null, PresenceStanzaType.SUBSCRIBE, null, null).build()); handler.executeCore(initialPresence, sessionContext.getServerRuntimeContext(), true, sessionContext); assertEquals(ResourceState.AVAILABLE_INTERESTED, getResourceState()); assertStanzasDeliveredAndRelayed(0); // TO subscription already exists } public void testWithBOTH() throws BindException, EntityFormatException { setResourceState(initiatingUser.getBoundResourceId(), ResourceState.AVAILABLE_INTERESTED); XMPPCoreStanza initialPresence = XMPPCoreStanza.getWrapper(StanzaBuilder.createPresenceStanza( initiatingUser.getEntityFQ(), subscribed_BOTH.getEntity(), null, PresenceStanzaType.SUBSCRIBE, null, null).build()); handler.executeCore(initialPresence, sessionContext.getServerRuntimeContext(), true, sessionContext); assertEquals(ResourceState.AVAILABLE_INTERESTED, getResourceState()); assertStanzasDeliveredAndRelayed(0); // TO subscription already exists with subscribed_BOTH } }