Smack/smack-im/src/test/java/org/jivesoftware/smack/roster/SubscriptionPreApprovalTest...

209 lines
8.3 KiB
Java

/**
*
* Copyright © 2015 Tomáš Havlas
*
* 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.smack.roster;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.jivesoftware.smack.DummyConnection;
import org.jivesoftware.smack.SmackException.FeatureNotSupportedException;
import org.jivesoftware.smack.im.InitSmackIm;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.roster.RosterTest.TestRosterListener;
import org.jivesoftware.smack.roster.packet.RosterPacket;
import org.jivesoftware.smack.roster.packet.RosterPacket.Item;
import org.jivesoftware.smack.roster.packet.RosterPacket.ItemType;
import org.jivesoftware.smack.roster.packet.SubscriptionPreApproval;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
/**
* Tests that verifies the correct behavior of the pre-approval implementation.
*
* @see <a href="http://xmpp.org/rfcs/rfc6121.html#sub-preapproval">Pre-Approving a Subscription Request</a>
* @author Tomáš Havlas
*/
public class SubscriptionPreApprovalTest extends InitSmackIm {
private DummyConnection connection;
private Roster roster;
private TestRosterListener rosterListener;
@Before
public void setUp() throws Exception {
connection = new DummyConnection();
connection.connect();
connection.login();
rosterListener = new TestRosterListener();
roster = Roster.getInstanceFor(connection);
roster.addRosterListener(rosterListener);
connection.setReplyTimeout(1000 * 60 * 5);
}
@After
public void tearDown() throws Exception {
connection.disconnect();
connection = null;
}
@Test(expected=FeatureNotSupportedException.class)
public void testPreApprovalNotSupported() throws Throwable {
final Jid contactJID = JidCreate.from("preapproval@example.com");
roster.preApprove(contactJID.asBareJid());
}
@Test
public void testPreApproveAndCreate() throws Throwable {
final BareJid contactJID = JidCreate.bareFrom("preapproval@example.com");
final String contactName = "PreApproval";
final String[] contactGroup = {};
connection.enableStreamFeature(SubscriptionPreApproval.INSTANCE);
final PreApproveAndCreateEntryResponder serverSimulator = new PreApproveAndCreateEntryResponder() {
@Override
void verifyRosterUpdateRequest(final RosterPacket updateRequest) {
final Item item = updateRequest.getRosterItems().iterator().next();
assertSame("The provided JID doesn't match the requested!",
contactJID,
item.getJid());
assertSame("The provided name doesn't match the requested!",
contactName,
item.getName());
assertSame("The provided group number doesn't match the requested!",
0,
item.getGroupNames().size());
}
@Override
void verifyPreApprovalRequest(Presence preApproval) {
assertSame("The provided name doesn't match the requested!",
contactJID,
preApproval.getTo());
assertSame("The provided presence type is incorrect!",
Presence.Type.subscribed,
preApproval.getType());
}
};
serverSimulator.start();
roster.preApproveAndCreateEntry(contactJID, contactName, contactGroup);
serverSimulator.join();
// Check if an error occurred within the simulator
final Throwable exception = serverSimulator.getException();
if (exception != null) {
throw exception;
}
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID);
assertNotNull("The new contact wasn't added to the roster!", addedEntry);
assertTrue("The roster listener wasn't invoked for the new contact!",
rosterListener.getAddedAddresses().contains(contactJID));
assertSame("Setup wrong name for the new contact!",
contactName,
addedEntry.getName());
assertSame("Setup wrong default subscription status!",
ItemType.none,
addedEntry.getType());
assertSame("The new contact should be member of exactly one group!",
0,
addedEntry.getGroups().size());
}
/**
* This class can be used to simulate the server response for
* a pre approve request request.
*/
private abstract class PreApproveAndCreateEntryResponder extends Thread {
private Throwable exception = null;
/**
* Overwrite this method to check if the received roster update request is valid.
*
* @param updateRequest the request which would be sent to the server.
*/
abstract void verifyRosterUpdateRequest(final RosterPacket updateRequest);
/**
* Overwrite this method to check if recieved pre-approval request is valid
*
* @param preApproval the request which would be sent to server.
*/
abstract void verifyPreApprovalRequest(final Presence preApproval);
public void run() {
try {
while (true) {
final Stanza packet = connection.getSentPacket();
if (packet instanceof RosterPacket && ((IQ) packet).getType() == Type.set) {
final RosterPacket rosterRequest = (RosterPacket) packet;
// Prepare and process the roster push
final RosterPacket rosterPush = new RosterPacket();
final Item item = rosterRequest.getRosterItems().iterator().next();
if (item.getItemType() != ItemType.remove) {
item.setItemType(ItemType.none);
}
rosterPush.setType(Type.set);
rosterPush.setTo(connection.getUser());
rosterPush.addRosterItem(item);
connection.processStanza(rosterPush);
// Create and process the IQ response
final IQ response = IQ.createResultIQ(rosterRequest);
connection.processStanza(response);
// Verify the roster update request
assertSame("A roster set MUST contain one and only one <item/> element.",
1,
rosterRequest.getRosterItemCount());
verifyRosterUpdateRequest(rosterRequest);
break;
}
else if (packet instanceof Presence && ((Presence) packet).getType() == Presence.Type.subscribed) {
final Presence approval = (Presence) packet;
verifyPreApprovalRequest(approval);
}
}
}
catch (Throwable e) {
exception = e;
fail(e.getMessage());
}
}
/**
* Returns the exception or error if something went wrong.
*
* @return the Throwable exception or error that occurred.
*/
public Throwable getException() {
return exception;
}
}
}