1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-22 14:22:05 +01:00

Re-activate EntityCaps integration test

This commit is contained in:
Florian Schmaus 2016-12-19 14:35:09 +01:00
parent 1f7770b831
commit 7655ac17f2
16 changed files with 358 additions and 181 deletions

View file

@ -45,7 +45,6 @@ import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.AbstractPresenceEventListener; import org.jivesoftware.smack.roster.AbstractPresenceEventListener;
import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.roster.SubscribeListener; import org.jivesoftware.smack.roster.SubscribeListener;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
@ -353,10 +352,7 @@ public final class IoTProvisioningManager extends Manager {
} }
public boolean iAmFriendOf(BareJid otherJid) { public boolean iAmFriendOf(BareJid otherJid) {
RosterEntry entry = roster.getEntry(otherJid); return roster.iAmSubscribedTo(otherJid);
if (entry == null) return false;
return entry.canSeeHisPresence();
} }
public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException { public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException {

View file

@ -1,147 +0,0 @@
package org.jivesoftware.smackx.entitycaps;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.TCPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.filter.IQTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.test.SmackTestCase;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.packet.DiscoverInfo;
public class EntityCapsTest extends SmackTestCase {
private static final String DISCOVER_TEST_FEATURE = "entityCapsTest";
XMPPTCPConnection con0;
XMPPTCPConnection con1;
EntityCapsManager ecm0;
EntityCapsManager ecm1;
ServiceDiscoveryManager sdm0;
ServiceDiscoveryManager sdm1;
private boolean discoInfoSend = false;
public EntityCapsTest(String arg0) {
super(arg0);
}
@Override
protected int getMaxConnections() {
return 2;
}
@Override
protected void setUp() throws Exception {
super.setUp();
SmackConfiguration.setAutoEnableEntityCaps(true);
con0 = getConnection(0);
con1 = getConnection(1);
ecm0 = EntityCapsManager.getInstanceFor(getConnection(0));
ecm1 = EntityCapsManager.getInstanceFor(getConnection(1));
sdm0 = ServiceDiscoveryManager.getInstanceFor(con0);
sdm1 = ServiceDiscoveryManager.getInstanceFor(con1);
letsAllBeFriends();
}
public void testLocalEntityCaps() throws InterruptedException {
DiscoverInfo info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecm1.getLocalNodeVer());
assertFalse(info.containsFeature(DISCOVER_TEST_FEATURE));
dropWholeEntityCapsCache();
// This should cause a new presence stanza from con1 with and updated
// 'ver' String
sdm1.addFeature(DISCOVER_TEST_FEATURE);
// Give the server some time to handle the stanza and send it to con0
Thread.sleep(2000);
// The presence stanza should get received by con0 and the data should
// be recorded in the map
// Note that while both connections use the same static Entity Caps
// cache,
// it's assured that *not* con1 added the data to the Entity Caps cache.
// Every time the entities features
// and identities change only a new caps 'ver' is calculated and send
// with the presence stanza
// The other connection has to receive this stanza and record the
// information in order for this test to succeed.
info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecm1.getLocalNodeVer());
assertNotNull(info);
assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE));
}
/**
* Test if entity caps actually prevent a disco info request and reply
*
* @throws XMPPException
*
*/
public void testPreventDiscoInfo() throws XMPPException {
con0.addPacketSendingListener(new PacketListener() {
@Override
public void processPacket(Packet packet) {
discoInfoSend = true;
}
}, new AndFilter(new StanzaTypeFilter(DiscoverInfo.class), new IQTypeFilter(IQ.Type.get)));
// add a bogus feature so that con1 ver won't match con0's
sdm1.addFeature(DISCOVER_TEST_FEATURE);
dropCapsCache();
// discover that
DiscoverInfo info = sdm0.discoverInfo(con1.getUser());
// that discovery should cause a disco#info
assertTrue(discoInfoSend);
assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE));
discoInfoSend = false;
// discover that
info = sdm0.discoverInfo(con1.getUser());
// that discovery shouldn't cause a disco#info
assertFalse(discoInfoSend);
assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE));
}
public void testCapsChanged() {
String nodeVerBefore = EntityCapsManager.getNodeVersionByJid(con1.getUser());
sdm1.addFeature(DISCOVER_TEST_FEATURE);
String nodeVerAfter = EntityCapsManager.getNodeVersionByJid(con1.getUser());
assertFalse(nodeVerBefore.equals(nodeVerAfter));
}
public void testEntityCaps() throws XMPPException, InterruptedException {
dropWholeEntityCapsCache();
sdm1.addFeature(DISCOVER_TEST_FEATURE);
Thread.sleep(3000);
DiscoverInfo info = sdm0.discoverInfo(con1.getUser());
assertTrue(info.containsFeature(DISCOVER_TEST_FEATURE));
String u1ver = EntityCapsManager.getNodeVersionByJid(con1.getUser());
assertNotNull(u1ver);
DiscoverInfo entityInfo = EntityCapsManager.caps.get(u1ver);
assertNotNull(entityInfo);
assertEquals(info.toXML(), entityInfo.toXML());
}
private static void dropWholeEntityCapsCache() {
EntityCapsManager.caps.clear();
EntityCapsManager.jidCaps.clear();
}
private static void dropCapsCache() {
EntityCapsManager.caps.clear();
}
}

View file

@ -101,7 +101,7 @@ public final class EntityCapsManager extends Manager {
/** /**
* Map of "node + '#' + hash" to DiscoverInfo data * Map of "node + '#' + hash" to DiscoverInfo data
*/ */
private static final LruCache<String, DiscoverInfo> CAPS_CACHE = new LruCache<String, DiscoverInfo>(1000); static final LruCache<String, DiscoverInfo> CAPS_CACHE = new LruCache<String, DiscoverInfo>(1000);
/** /**
* Map of Full JID -&gt; DiscoverInfo/null. In case of c2s connection the * Map of Full JID -&gt; DiscoverInfo/null. In case of c2s connection the
@ -109,7 +109,7 @@ public final class EntityCapsManager extends Manager {
* link-local connection the key is formed as user@host (no resource) In * link-local connection the key is formed as user@host (no resource) In
* case of a server or component the key is formed as domain * case of a server or component the key is formed as domain
*/ */
private static final LruCache<Jid, NodeVerHash> JID_TO_NODEVER_CACHE = new LruCache<>(10000); static final LruCache<Jid, NodeVerHash> JID_TO_NODEVER_CACHE = new LruCache<>(10000);
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@ -159,7 +159,7 @@ public final class EntityCapsManager extends Manager {
* the user (Full JID) * the user (Full JID)
* @return the node version (node#ver) or null * @return the node version (node#ver) or null
*/ */
public static String getNodeVersionByJid(String jid) { public static String getNodeVersionByJid(Jid jid) {
NodeVerHash nvh = JID_TO_NODEVER_CACHE.get(jid); NodeVerHash nvh = JID_TO_NODEVER_CACHE.get(jid);
if (nvh != null) { if (nvh != null) {
return nvh.nodeVer; return nvh.nodeVer;

View file

@ -1099,6 +1099,25 @@ public final class Roster extends Manager {
return entry.canSeeMyPresence(); return entry.canSeeMyPresence();
} }
/**
* Check if the XMPP entity this roster belongs to is subscribed to the presence of the given JID.
*
* @param jid the jid to check.
* @return <code>true</code> if we are subscribed to the presence of the given jid.
* @since 4.2
*/
public boolean iAmSubscribedTo(Jid jid) {
if (jid == null) {
return false;
}
BareJid bareJid = jid.asBareJid();
RosterEntry entry = getEntry(bareJid);
if (entry == null) {
return false;
}
return entry.canSeeHisPresence();
}
/** /**
* Sets if the roster will be loaded from the server when logging in for newly created instances * Sets if the roster will be loaded from the server when logging in for newly created instances
* of {@link Roster}. * of {@link Roster}.

View file

@ -26,6 +26,7 @@ import java.util.concurrent.locks.ReentrantLock;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.SmackException.NotLoggedInException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Presence;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
@ -111,4 +112,46 @@ public class RosterUtil {
} }
} }
public static void ensureSubscribed(XMPPConnection connectionOne, XMPPConnection connectionTwo, long timeout)
throws NotLoggedInException, NotConnectedException, InterruptedException, TimeoutException {
ensureSubscribedTo(connectionOne, connectionTwo, timeout);
ensureSubscribedTo(connectionTwo, connectionOne, timeout);
}
public static void ensureSubscribedTo(XMPPConnection connectionOne, XMPPConnection connectionTwo, long timeout)
throws NotLoggedInException, NotConnectedException, InterruptedException, TimeoutException {
Date deadline = new Date(System.currentTimeMillis() + timeout);
ensureSubscribedTo(connectionOne, connectionTwo, deadline);
}
public static void ensureSubscribedTo(final XMPPConnection connectionOne, final XMPPConnection connectionTwo,
final Date deadline)
throws NotLoggedInException, NotConnectedException, InterruptedException, TimeoutException {
final Roster rosterOne = Roster.getInstanceFor(connectionOne);
final BareJid jidTwo = connectionTwo.getUser().asBareJid();
if (rosterOne.iAmSubscribedTo(jidTwo))
return;
final BareJid jidOne = connectionOne.getUser().asBareJid();
final SubscribeListener subscribeListener = new SubscribeListener() {
@Override
public SubscribeAnswer processSubscribe(Jid from, Presence subscribeRequest) {
if (from.equals(jidOne)) {
return SubscribeAnswer.Approve;
}
return null;
}
};
final Roster rosterTwo = Roster.getInstanceFor(connectionTwo);
rosterTwo.addSubscribeListener(subscribeListener);
try {
rosterOne.sendSubscriptionRequest(jidTwo);
waitUntilOtherEntityIsSubscribed(rosterTwo, jidOne, deadline);
}
finally {
rosterTwo.removeSubscribeListener(subscribeListener);
}
}
} }

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2015 Florian Schmaus * Copyright 2015-2016 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,12 +17,58 @@
package org.igniterealtime.smack.inttest; package org.igniterealtime.smack.inttest;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.StanzaFilter;
public abstract class AbstractSmackIntTest { public abstract class AbstractSmackIntTest {
protected static final Logger LOGGER = Logger.getLogger(AbstractSmackIntTest.class.getName()); protected static final Logger LOGGER = Logger.getLogger(AbstractSmackIntTest.class.getName());
protected static final Random INSECURE_RANDOM = new Random(); protected static final Random INSECURE_RANDOM = new Random();
protected final String testRunId;
protected final long timeout;
protected AbstractSmackIntTest(String testRunId, long timeout) {
this.testRunId = testRunId;
this.timeout = timeout;
}
protected void performActionAndWaitUntilStanzaReceived(Runnable action, XMPPConnection connection, StanzaFilter filter)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
PacketCollector.Configuration configuration = PacketCollector.newConfiguration().setStanzaFilter(
filter).setSize(1);
PacketCollector collector = connection.createPacketCollector(configuration);
try {
action.run();
collector.nextResultOrThrow(timeout);
}
finally {
collector.cancel();
}
}
protected void waitUntilTrue(Condition condition) throws TimeoutException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
final long deadline = System.currentTimeMillis() + timeout;
do {
if (condition.evaluate()) {
return;
}
Thread.yield();
} while (System.currentTimeMillis() <= deadline);
throw new TimeoutException("Timeout waiting for condition to become true. Timeout was " + timeout + " ms.");
}
protected interface Condition {
boolean evaluate() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException;
}
} }

View file

@ -40,19 +40,10 @@ public abstract class AbstractSmackIntegrationTest extends AbstractSmackIntTest
*/ */
protected final XMPPConnection connection; protected final XMPPConnection connection;
protected final String testRunId;
protected final long defaultTimeout;
public AbstractSmackIntegrationTest(SmackIntegrationTestEnvironment environment) { public AbstractSmackIntegrationTest(SmackIntegrationTestEnvironment environment) {
super(environment.testRunId, environment.configuration.replyTimeout);
this.connection = this.conOne = environment.conOne; this.connection = this.conOne = environment.conOne;
this.conTwo = environment.conTwo; this.conTwo = environment.conTwo;
this.conThree = environment.conThree; this.conThree = environment.conThree;
if (environment.configuration.replyTimeout > 0) {
this.defaultTimeout = environment.configuration.replyTimeout;
} else {
this.defaultTimeout = 2 * 60 * 1000;
}
this.testRunId = environment.testRunId;
} }
} }

View file

@ -36,14 +36,12 @@ public abstract class AbstractSmackLowLevelIntegrationTest extends AbstractSmack
*/ */
protected final Configuration configuration; protected final Configuration configuration;
protected final String testRunId;
protected final DomainBareJid service; protected final DomainBareJid service;
public AbstractSmackLowLevelIntegrationTest(SmackIntegrationTestEnvironment environment) { public AbstractSmackLowLevelIntegrationTest(SmackIntegrationTestEnvironment environment) {
super(environment.testRunId, environment.configuration.replyTimeout);
this.environment = environment; this.environment = environment;
this.configuration = environment.configuration; this.configuration = environment.configuration;
this.testRunId = environment.testRunId;
this.service = configuration.service; this.service = configuration.service;
} }

View file

@ -83,7 +83,11 @@ public final class Configuration {
"'service' must be set. Either via 'properties' files or via system property 'sinttest.service'."); "'service' must be set. Either via 'properties' files or via system property 'sinttest.service'.");
this.serviceTlsPin = serviceTlsPin; this.serviceTlsPin = serviceTlsPin;
this.securityMode = securityMode; this.securityMode = securityMode;
this.replyTimeout = replyTimeout; if (replyTimeout > 0) {
this.replyTimeout = replyTimeout;
} else {
this.replyTimeout = 60000;
}
this.debug = debug; this.debug = debug;
if (StringUtils.isNotEmpty(adminAccountUsername, adminAccountPassword)) { if (StringUtils.isNotEmpty(adminAccountUsername, adminAccountPassword)) {
accountRegistration = AccountRegistration.serviceAdministration; accountRegistration = AccountRegistration.serviceAdministration;

View file

@ -95,9 +95,14 @@ public class SmackIntegrationTestFramework {
LOGGER.info("Could not run " + testNotPossible.testMethod.getName() + " because: " LOGGER.info("Could not run " + testNotPossible.testMethod.getName() + " because: "
+ testNotPossible.testNotPossibleException.getMessage()); + testNotPossible.testNotPossibleException.getMessage());
} }
final int successfulTests = testRunResult.successfulTests.size();
final int availableTests = testRunResult.getNumberOfAvailableTests();
final int possibleTests = testRunResult.getNumberOfPossibleTests();
LOGGER.info("SmackIntegrationTestFramework[" + testRunResult.testRunId + ']' + ": Finished [" LOGGER.info("SmackIntegrationTestFramework[" + testRunResult.testRunId + ']' + ": Finished ["
+ testRunResult.successfulTests.size() + '/' + testRunResult.numberOfTests + ']'); + successfulTests + '/' + possibleTests + "] (of " + availableTests + " available tests)");
if (!testRunResult.failedIntegrationTests.isEmpty()) { if (!testRunResult.failedIntegrationTests.isEmpty()) {
final int failedTests = testRunResult.failedIntegrationTests.size();
LOGGER.warning("The following " + failedTests + " tests failed!");
for (FailedTest failedTest : testRunResult.failedIntegrationTests) { for (FailedTest failedTest : testRunResult.failedIntegrationTests) {
final Method method = failedTest.testMethod; final Method method = failedTest.testMethod;
final String className = method.getDeclaringClass().getName(); final String className = method.getDeclaringClass().getName();
@ -106,6 +111,8 @@ public class SmackIntegrationTestFramework {
LOGGER.severe(className + CLASS_METHOD_SEP + methodName + " failed: " + cause); LOGGER.severe(className + CLASS_METHOD_SEP + methodName + " failed: " + cause);
} }
System.exit(2); System.exit(2);
} else {
LOGGER.info("All possible Smack Integration Tests completed successfully. \\o/");
} }
System.exit(0); System.exit(0);
} }
@ -251,7 +258,9 @@ public class SmackIntegrationTestFramework {
continue; continue;
} }
testRunResult.numberOfTests.addAndGet(smackIntegrationTestMethods.size()); final int detectedTestMethodsCount = smackIntegrationTestMethods.size();
testRunResult.numberOfAvailableTests.addAndGet(detectedTestMethodsCount);
testRunResult.numberOfPossibleTests.addAndGet(detectedTestMethodsCount);
AbstractSmackIntTest test; AbstractSmackIntTest test;
switch (testType) { switch (testType) {
@ -274,6 +283,7 @@ public class SmackIntegrationTestFramework {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
if (cause instanceof TestNotPossibleException) { if (cause instanceof TestNotPossibleException) {
testRunResult.impossibleTestClasses.put(testClass, cause.getMessage()); testRunResult.impossibleTestClasses.put(testClass, cause.getMessage());
testRunResult.numberOfPossibleTests.addAndGet(-detectedTestMethodsCount);
} }
else { else {
throwFatalException(cause); throwFatalException(cause);
@ -306,6 +316,7 @@ public class SmackIntegrationTestFramework {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
if (cause instanceof TestNotPossibleException) { if (cause instanceof TestNotPossibleException) {
testRunResult.impossibleTestClasses.put(testClass, cause.getMessage()); testRunResult.impossibleTestClasses.put(testClass, cause.getMessage());
testRunResult.numberOfPossibleTests.addAndGet(-detectedTestMethodsCount);
} }
else { else {
throwFatalException(cause); throwFatalException(cause);
@ -622,7 +633,8 @@ public class SmackIntegrationTestFramework {
private final List<FailedTest> failedIntegrationTests = Collections.synchronizedList(new LinkedList<FailedTest>()); private final List<FailedTest> failedIntegrationTests = Collections.synchronizedList(new LinkedList<FailedTest>());
private final List<TestNotPossible> impossibleTestMethods = Collections.synchronizedList(new LinkedList<TestNotPossible>()); private final List<TestNotPossible> impossibleTestMethods = Collections.synchronizedList(new LinkedList<TestNotPossible>());
private final Map<Class<? extends AbstractSmackIntTest>, String> impossibleTestClasses = new HashMap<>(); private final Map<Class<? extends AbstractSmackIntTest>, String> impossibleTestClasses = new HashMap<>();
private final AtomicInteger numberOfTests = new AtomicInteger(); private final AtomicInteger numberOfAvailableTests = new AtomicInteger();
private final AtomicInteger numberOfPossibleTests = new AtomicInteger();
private TestRunResult() { private TestRunResult() {
} }
@ -631,8 +643,12 @@ public class SmackIntegrationTestFramework {
return testRunId; return testRunId;
} }
public int getNumberOfTests() { public int getNumberOfAvailableTests() {
return numberOfTests.get(); return numberOfAvailableTests.get();
}
public int getNumberOfPossibleTests() {
return numberOfPossibleTests.get();
} }
public List<SuccessfulTest> getSuccessfulTests() { public List<SuccessfulTest> getSuccessfulTests() {

View file

@ -55,12 +55,12 @@ public class ChatTest extends AbstractSmackIntegrationTest {
} }
@BeforeClass @BeforeClass
public static void setUp() { public void setUp() {
JivePropertiesManager.setJavaObjectEnabled(true); JivePropertiesManager.setJavaObjectEnabled(true);
} }
@AfterClass @AfterClass
public static void tearDown() { public void tearDown() {
JivePropertiesManager.setJavaObjectEnabled(false); JivePropertiesManager.setJavaObjectEnabled(false);
} }

View file

@ -0,0 +1,210 @@
/**
*
* Copyright 2013-2016 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.caps;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.NotLoggedInException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.filter.IQTypeFilter;
import org.jivesoftware.smack.filter.PresenceTypeFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.RosterUtil;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class EntityCapsTest extends AbstractSmackIntegrationTest {
private final EntityCapsManager ecmTwo;
private final ServiceDiscoveryManager sdmOne;
private final ServiceDiscoveryManager sdmTwo;
private boolean discoInfoSend = false;
public EntityCapsTest(SmackIntegrationTestEnvironment environment) {
super(environment);
ecmTwo = EntityCapsManager.getInstanceFor(environment.conTwo);
sdmOne = ServiceDiscoveryManager.getInstanceFor(environment.conOne);
sdmTwo = ServiceDiscoveryManager.getInstanceFor(environment.conTwo);
}
private final AtomicInteger dummyFeatureId = new AtomicInteger();
private final Set<String> dummyFeatures = new HashSet<>();
private String getNewDummyFeature() {
String dummyFeature = "entityCapsTest" + dummyFeatureId.incrementAndGet();
dummyFeatures.add(dummyFeature);
return dummyFeature;
}
@BeforeClass
public void setUp() throws NotLoggedInException, NotConnectedException, InterruptedException, TimeoutException {
RosterUtil.ensureSubscribed(conOne, conTwo, timeout);
}
@AfterClass
public void tearDown() throws NotConnectedException, InterruptedException {
RosterUtil.ensureNotSubscribedToEachOther(conOne, conTwo);
ServiceDiscoveryManager[] sdms = new ServiceDiscoveryManager[] { sdmOne, sdmTwo };
for (ServiceDiscoveryManager sdm : sdms) {
for (String dummyFeature : dummyFeatures) {
sdm.removeFeature(dummyFeature);
}
}
}
@SmackIntegrationTest
public void testLocalEntityCaps() throws InterruptedException, NoResponseException, XMPPErrorException, NotConnectedException {
final String dummyFeature = getNewDummyFeature();
DiscoverInfo info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecmTwo.getLocalNodeVer());
assertFalse(info.containsFeature(dummyFeature));
dropWholeEntityCapsCache();
performActionAndWaitUntilStanzaReceived(new Runnable() {
@Override
public void run() {
// This should cause a new presence stanza from con1 with and updated
// 'ver' String
sdmTwo.addFeature(dummyFeature);
}
}, conOne, new AndFilter(PresenceTypeFilter.AVAILABLE, FromMatchesFilter.create(conTwo.getUser())));
// The presence stanza should get received by con0 and the data should
// be recorded in the map
// Note that while both connections use the same static Entity Caps
// cache,
// it's assured that *not* con1 added the data to the Entity Caps cache.
// Every time the entities features
// and identities change only a new caps 'ver' is calculated and send
// with the presence stanza
// The other connection has to receive this stanza and record the
// information in order for this test to succeed.
info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecmTwo.getLocalNodeVer());
assertNotNull(info);
assertTrue(info.containsFeature(dummyFeature));
}
/**
* Test if entity caps actually prevent a disco info request and reply.
*
* @throws XMPPException
* @throws InterruptedException
* @throws NotConnectedException
* @throws NoResponseException
*
*/
@SmackIntegrationTest
public void testPreventDiscoInfo() throws XMPPException, NoResponseException, NotConnectedException, InterruptedException {
final String dummyFeature = getNewDummyFeature();
conOne.addPacketSendingListener(new StanzaListener() {
@Override
public void processPacket(Stanza stanza) {
discoInfoSend = true;
}
}, new AndFilter(new StanzaTypeFilter(DiscoverInfo.class), IQTypeFilter.GET));
// add a bogus feature so that con1 ver won't match con0's
sdmTwo.addFeature(dummyFeature);
dropCapsCache();
// discover that
DiscoverInfo info = sdmOne.discoverInfo(conTwo.getUser());
// that discovery should cause a disco#info
assertTrue(discoInfoSend);
assertTrue(info.containsFeature(dummyFeature));
discoInfoSend = false;
// discover that
info = sdmOne.discoverInfo(conTwo.getUser());
// that discovery shouldn't cause a disco#info
assertFalse(discoInfoSend);
assertTrue(info.containsFeature(dummyFeature));
}
@SmackIntegrationTest
public void testCapsChanged() {
final String dummyFeature = getNewDummyFeature();
String nodeVerBefore = EntityCapsManager.getNodeVersionByJid(conTwo.getUser());
sdmTwo.addFeature(dummyFeature);
String nodeVerAfter = EntityCapsManager.getNodeVersionByJid(conTwo.getUser());
assertFalse(nodeVerBefore.equals(nodeVerAfter));
}
@SmackIntegrationTest
public void testEntityCaps() throws XMPPException, InterruptedException, NoResponseException, NotConnectedException, TimeoutException {
final String dummyFeature = getNewDummyFeature();
dropWholeEntityCapsCache();
performActionAndWaitUntilStanzaReceived(new Runnable() {
@Override
public void run() {
sdmTwo.addFeature(dummyFeature);
}
}, connection, new AndFilter(PresenceTypeFilter.AVAILABLE, FromMatchesFilter.create(conTwo.getUser())));
waitUntilTrue(new Condition() {
@Override
public boolean evaluate() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
DiscoverInfo info = sdmOne.discoverInfo(conTwo.getUser());
return info.containsFeature(dummyFeature);
}
});
DiscoverInfo info = sdmOne.discoverInfo(conTwo.getUser());
String u1ver = EntityCapsManager.getNodeVersionByJid(conTwo.getUser());
assertNotNull(u1ver);
DiscoverInfo entityInfo = EntityCapsManager.CAPS_CACHE.get(u1ver);
assertNotNull(entityInfo);
assertEquals(info.toXML(), entityInfo.toXML());
}
private static void dropWholeEntityCapsCache() {
EntityCapsManager.CAPS_CACHE.clear();
EntityCapsManager.JID_TO_NODEVER_CACHE.clear();
}
private static void dropCapsCache() {
EntityCapsManager.CAPS_CACHE.clear();
}
}

View file

@ -0,0 +1 @@
../../../../../../../../smack-extensions/src/main/java/org/jivesoftware/smackx/caps/package-info.java

View file

@ -81,7 +81,7 @@ public class IoTControlIntegrationTest extends AbstractSmackIntegrationTest {
IoTControlManagerOne.installThing(controlThing); IoTControlManagerOne.installThing(controlThing);
try { try {
RosterIntegrationTest.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, defaultTimeout); RosterIntegrationTest.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout);
SetData data = new SetBoolData(testRunId, true); SetData data = new SetBoolData(testRunId, true);
IoTSetResponse response = IoTControlManagerTwo.setUsingIq(conOne.getUser(), data); IoTSetResponse response = IoTControlManagerTwo.setUsingIq(conOne.getUser(), data);
@ -92,6 +92,6 @@ public class IoTControlIntegrationTest extends AbstractSmackIntegrationTest {
RosterIntegrationTest.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); RosterIntegrationTest.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo);
} }
syncPoint.waitForResult(defaultTimeout); syncPoint.waitForResult(timeout);
} }
} }

View file

@ -73,7 +73,7 @@ public class IoTDataIntegrationTest extends AbstractSmackIntegrationTest {
List<IoTFieldsExtension> values; List<IoTFieldsExtension> values;
try { try {
RosterIntegrationTest.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, defaultTimeout); RosterIntegrationTest.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout);
values = iotDataManagerTwo.requestMomentaryValuesReadOut(conOne.getUser()); values = iotDataManagerTwo.requestMomentaryValuesReadOut(conOne.getUser());
} }

View file

@ -88,7 +88,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString)); mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString));
mucAsSeenByOne.sendMessage(mucMessage); mucAsSeenByOne.sendMessage(mucMessage);
resultSyncPoint.waitForResult(defaultTimeout); resultSyncPoint.waitForResult(timeout);
mucAsSeenByOne.leave(); mucAsSeenByOne.leave();
mucAsSeenByTwo.leave(); mucAsSeenByTwo.leave();