xmpp-compliance-tester

XMPP Compliance Tester, forked from github.com/iNPUTmice/ComplianceTester
git clone https://git.in0rdr.ch/xmpp-compliance-tester.git
Log | Files | Refs | Pull requests |Archive | README | LICENSE

commit 3e1044134b7eef12bd24d1b6df7fe516f5d93988
Author: Daniel Gultsch <daniel@gultsch.de>
Date:   Sun,  5 Jun 2016 15:54:31 +0200

provide command line tool, some test cases and an 'everything' compliance suite

Diffstat:
AREADME.md | 10++++++++++
Apom.xml | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/ComplianceTester.java | 40++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/Result.java | 7+++++++
Asrc/main/java/eu/siacs/compliance/suites/AbstractTestSuite.java | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/suites/EverythingTestSuite.java | 39+++++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/suites/TestSuiteFactory.java | 19+++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/AbstractDiscoTest.java | 36++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/AbstractServiceTest.java | 31+++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/AbstractStreamFeatureTest.java | 27+++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/AbstractTest.java | 18++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/Blocking.java | 29+++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/CSI.java | 29+++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/EntityCapabilities.java | 25+++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/HttpUpload.java | 21+++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/MAM.java | 29+++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/MultiUserChat.java | 22++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/PEP.java | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/Push.java | 29+++++++++++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/RosterVersioning.java | 21+++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/StreamManagement.java | 21+++++++++++++++++++++
Asrc/main/java/eu/siacs/compliance/tests/TestFactory.java | 23+++++++++++++++++++++++
22 files changed, 649 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,10 @@ +Compliance Tester for XMPP Servers +================================== + +Use this tool to test various your XMPP server for compatibility with various compliance suits. + +You can easily mix and match various test cases to compose your own compliance suite or you can use a preexisting compliance suite. + +Build with ```mvn package``` (needs Java 8) + +Run with ```java -jar target/ComplianceTester.jar username@domain password``` diff --git a/pom.xml b/pom.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>eu.siacs</groupId> + <artifactId>ComplianceTester</artifactId> + <version>0.1</version> + <packaging>jar</packaging> + + <repositories> + <repository> + <id>sonatype-nexus-snapshots</id> + <name>Sonatype Nexus Snapshots</name> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <dependencies> + + + <dependency> + <groupId>rocks.xmpp</groupId> + <artifactId>xmpp-core-client</artifactId> + <version>0.7.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>rocks.xmpp</groupId> + <artifactId>xmpp-extensions-client</artifactId> + <version>0.7.0-SNAPSHOT</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>eu.siacs.ComplianceTester</mainClass> + </transformer> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.3</version> + <configuration> + <source>8</source> + <target>8</target> + </configuration> + </plugin> + </plugins> + </build> + + +</project> diff --git a/src/main/java/eu/siacs/ComplianceTester.java b/src/main/java/eu/siacs/ComplianceTester.java @@ -0,0 +1,40 @@ +package eu.siacs; + +import eu.siacs.compliance.suites.AbstractTestSuite; +import eu.siacs.compliance.suites.EverythingTestSuite; +import eu.siacs.compliance.suites.TestSuiteFactory; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.XmppException; +import rocks.xmpp.core.sasl.AuthenticationException; +import rocks.xmpp.core.session.XmppClient; + +public class ComplianceTester { + + + public static void main(String[] args) { + if (args.length != 2) { + System.err.println("java -jar ComplianceTester.jar username@domain.tld password"); + System.exit(1); + } + Jid jid = Jid.of(args[0]); + String password = args[1]; + XmppClient xmppClient = XmppClient.create(jid.getDomain()); + try { + xmppClient.connect(); + xmppClient.login(jid.getLocal(), password); + try { + AbstractTestSuite testSuite = TestSuiteFactory.create(EverythingTestSuite.class, xmppClient); + testSuite.run(); + System.out.println(testSuite.getName() + ": " + testSuite.result()); + } catch (AbstractTestSuite.TestSuiteCreationException e) { + e.printStackTrace(); + System.out.println("Test suite creation failed"); + } + } catch(AuthenticationException e) { + System.err.println("username or password wrong"); + System.exit(1); + } catch (XmppException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/eu/siacs/compliance/Result.java b/src/main/java/eu/siacs/compliance/Result.java @@ -0,0 +1,6 @@ +package eu.siacs.compliance; + +public enum Result { + FAILED, + PASSED, +} +\ No newline at end of file diff --git a/src/main/java/eu/siacs/compliance/suites/AbstractTestSuite.java b/src/main/java/eu/siacs/compliance/suites/AbstractTestSuite.java @@ -0,0 +1,54 @@ +package eu.siacs.compliance.suites; + +import eu.siacs.compliance.tests.AbstractTest; +import eu.siacs.compliance.Result; +import eu.siacs.compliance.tests.TestFactory; +import rocks.xmpp.core.session.XmppClient; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public abstract class AbstractTestSuite { + + private final XmppClient mXmppClient; + + private HashMap<Class<?extends AbstractTest>,Result> mTestResults = new HashMap<>(); + + public AbstractTestSuite(XmppClient client) { + mXmppClient = client; + } + + public void run() { + for(Class<? extends AbstractTest> test : getTests()) { + run(test); + } + int passed = Collections.frequency(mTestResults.values(),Result.PASSED); + System.out.println("passed "+passed+"/"+mTestResults.size()); + } + + public Result result() { + return Collections.frequency(mTestResults.values(),Result.FAILED) == 0 ? Result.PASSED : Result.FAILED; + } + + private void run(Class<? extends AbstractTest> clazz) { + try { + AbstractTest test = TestFactory.create(clazz,mXmppClient); + System.out.print("running "+test.getName()+"…"); + Result result = test.run(); + System.out.println("\t\t"+result); + mTestResults.put(clazz, test.run()); + } catch (TestFactory.TestCreationException e) { + System.err.println("failed to create test for class "+clazz.toString()); + mTestResults.put(clazz, Result.FAILED); + } + } + + abstract List<Class<?extends AbstractTest>> getTests(); + + public abstract String getName(); + + public static class TestSuiteCreationException extends Exception { + + } +} diff --git a/src/main/java/eu/siacs/compliance/suites/EverythingTestSuite.java b/src/main/java/eu/siacs/compliance/suites/EverythingTestSuite.java @@ -0,0 +1,39 @@ +package eu.siacs.compliance.suites; + +import eu.siacs.compliance.tests.*; +import rocks.xmpp.core.session.XmppClient; + +import java.util.Arrays; +import java.util.List; + + +/** + * this test suite just tests for everything + */ +public class EverythingTestSuite extends AbstractTestSuite { + + public EverythingTestSuite(XmppClient client) { + super(client); + } + + @Override + List<Class<? extends AbstractTest>> getTests() { + return Arrays.asList( + RosterVersioning.class, + StreamManagement.class, + CSI.class, + Blocking.class, + MAM.class, + Push.class, + EntityCapabilities.class, + MultiUserChat.class, + HttpUpload.class, + PEP.class + ); + } + + @Override + public String getName() { + return "Relevant for Conversations"; + } +} diff --git a/src/main/java/eu/siacs/compliance/suites/TestSuiteFactory.java b/src/main/java/eu/siacs/compliance/suites/TestSuiteFactory.java @@ -0,0 +1,19 @@ +package eu.siacs.compliance.suites; + +import rocks.xmpp.core.session.XmppClient; + +public class TestSuiteFactory { + + public static AbstractTestSuite create(Class <? extends AbstractTestSuite> clazz, XmppClient client) throws AbstractTestSuite.TestSuiteCreationException { + if (client == null) { + throw new AbstractTestSuite.TestSuiteCreationException(); + } + try { + AbstractTestSuite testSuite = clazz.getDeclaredConstructor(XmppClient.class).newInstance(client); + return testSuite; + } catch (Exception e) { + e.printStackTrace(); + throw new AbstractTestSuite.TestSuiteCreationException(); + } + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/AbstractDiscoTest.java b/src/main/java/eu/siacs/compliance/tests/AbstractDiscoTest.java @@ -0,0 +1,36 @@ +package eu.siacs.compliance.tests; + +import eu.siacs.compliance.Result; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.util.concurrent.AsyncResult; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +public abstract class AbstractDiscoTest extends AbstractTest { + + public AbstractDiscoTest(XmppClient client) { + super(client); + } + + //test will succeed if any namespace matches + abstract List<String> getNamespaces(); + + abstract boolean checkOnServer(); + + @Override + public Result run() { + Jid target = checkOnServer() ? Jid.of(client.getConnectedResource().getDomain()) : client.getConnectedResource().asBareJid(); + for(String namespace : getNamespaces()) { + AsyncResult<Boolean> result = client.isSupported(namespace, target); + try { + Boolean hasCarbons = result.getResult(10, TimeUnit.SECONDS); + return hasCarbons ? Result.PASSED : Result.FAILED; + } catch (Exception e) { + //ignore and go to next namespace + } + } + return Result.FAILED; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/AbstractServiceTest.java b/src/main/java/eu/siacs/compliance/tests/AbstractServiceTest.java @@ -0,0 +1,31 @@ +package eu.siacs.compliance.tests; + + +import eu.siacs.compliance.Result; +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.extensions.disco.ServiceDiscoveryManager; +import rocks.xmpp.extensions.disco.model.items.Item; +import rocks.xmpp.util.concurrent.AsyncResult; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +public abstract class AbstractServiceTest extends AbstractTest { + + public AbstractServiceTest(XmppClient client) { + super(client); + } + + @Override + public Result run() { + ServiceDiscoveryManager manager = client.getManager(ServiceDiscoveryManager.class); + AsyncResult<List<Item>> result = manager.discoverServices(getNamespace()); + try { + return result.getResult(10, TimeUnit.SECONDS).size() >= 1 ? Result.PASSED : Result.FAILED; + } catch (Exception e) { + return Result.FAILED; + } + } + + public abstract String getNamespace(); +} diff --git a/src/main/java/eu/siacs/compliance/tests/AbstractStreamFeatureTest.java b/src/main/java/eu/siacs/compliance/tests/AbstractStreamFeatureTest.java @@ -0,0 +1,27 @@ +package eu.siacs.compliance.tests; + +import eu.siacs.compliance.Result; +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.core.stream.StreamFeaturesManager; +import rocks.xmpp.core.stream.model.StreamFeature; + +import java.util.Map; + +public abstract class AbstractStreamFeatureTest extends AbstractTest { + + public AbstractStreamFeatureTest(XmppClient client) { + super(client); + } + + @Override + public Result run() { + Map<Class<? extends StreamFeature>, StreamFeature> features = client.getManager(StreamFeaturesManager.class).getFeatures(); + if (features.containsKey(getStreamFeature())) { + return Result.PASSED; + } else { + return Result.FAILED; + } + } + + abstract Class<? extends StreamFeature> getStreamFeature(); +} diff --git a/src/main/java/eu/siacs/compliance/tests/AbstractTest.java b/src/main/java/eu/siacs/compliance/tests/AbstractTest.java @@ -0,0 +1,18 @@ +package eu.siacs.compliance.tests; + +import eu.siacs.compliance.Result; +import rocks.xmpp.core.session.XmppClient; + +public abstract class AbstractTest { + + protected final XmppClient client; + + public AbstractTest(XmppClient client) { + this.client = client; + } + + + public abstract Result run(); + + public abstract String getName(); +} diff --git a/src/main/java/eu/siacs/compliance/tests/Blocking.java b/src/main/java/eu/siacs/compliance/tests/Blocking.java @@ -0,0 +1,29 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +import java.util.Arrays; +import java.util.List; + +public class Blocking extends AbstractDiscoTest { + + public Blocking(XmppClient client) { + super(client); + } + + @Override + List<String> getNamespaces() { + return Arrays.asList("urn:xmpp:blocking"); + } + + @Override + boolean checkOnServer() { + return true; + } + + + @Override + public String getName() { + return "XEP-0191: Blocking Command"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/CSI.java b/src/main/java/eu/siacs/compliance/tests/CSI.java @@ -0,0 +1,29 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +import java.util.Arrays; +import java.util.List; + +public class CSI extends AbstractDiscoTest { + + public CSI(XmppClient client) { + super(client); + } + + @Override + List<String> getNamespaces() { + return Arrays.asList("urn:xmpp:carbons:2"); + } + + @Override + boolean checkOnServer() { + return true; + } + + + @Override + public String getName() { + return "XEP-0352: Client State Indication"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/EntityCapabilities.java b/src/main/java/eu/siacs/compliance/tests/EntityCapabilities.java @@ -0,0 +1,25 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.core.stream.model.StreamFeature; + +/** + * This test is looking for the c element in a servers stream features + * see http://xmpp.org/extensions/xep-0115.html#stream + */ +public class EntityCapabilities extends AbstractStreamFeatureTest { + + public EntityCapabilities(XmppClient client) { + super(client); + } + + @Override + Class<? extends StreamFeature> getStreamFeature() { + return rocks.xmpp.extensions.caps.model.EntityCapabilities.class; + } + + @Override + public String getName() { + return "XEP-0115: Entity Capabilities"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/HttpUpload.java b/src/main/java/eu/siacs/compliance/tests/HttpUpload.java @@ -0,0 +1,21 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +public class HttpUpload extends AbstractServiceTest { + + public HttpUpload(XmppClient client) { + super(client); + } + + @Override + public String getNamespace() { + return "urn:xmpp:http:upload"; + } + + + @Override + public String getName() { + return "XEP-0363: HTTP File Upload"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/MAM.java b/src/main/java/eu/siacs/compliance/tests/MAM.java @@ -0,0 +1,29 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +import java.util.Arrays; +import java.util.List; + +public class MAM extends AbstractDiscoTest { + + public MAM(XmppClient client) { + super(client); + } + + @Override + List<String> getNamespaces() { + return Arrays.asList("urn:xmpp:mam:0","urn:xmpp:mam:1"); + } + + @Override + boolean checkOnServer() { + return true; + } + + + @Override + public String getName() { + return "XEP-0313: Message Archive Management"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/MultiUserChat.java b/src/main/java/eu/siacs/compliance/tests/MultiUserChat.java @@ -0,0 +1,22 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.extensions.muc.model.Muc; + +public class MultiUserChat extends AbstractServiceTest { + + public MultiUserChat(XmppClient client) { + super(client); + } + + @Override + public String getNamespace() { + return Muc.NAMESPACE; + } + + + @Override + public String getName() { + return "XEP-0045: Multi-User Chat"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/PEP.java b/src/main/java/eu/siacs/compliance/tests/PEP.java @@ -0,0 +1,41 @@ +package eu.siacs.compliance.tests; + +import eu.siacs.compliance.Result; +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.extensions.disco.ServiceDiscoveryManager; +import rocks.xmpp.extensions.disco.model.info.Identity; +import rocks.xmpp.extensions.disco.model.info.InfoNode; +import rocks.xmpp.util.concurrent.AsyncResult; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class PEP extends AbstractTest { + + public PEP(XmppClient client) { + super(client); + } + + @Override + public Result run() { + ServiceDiscoveryManager manager = client.getManager(ServiceDiscoveryManager.class); + AsyncResult<InfoNode> result = manager.discoverInformation(client.getConnectedResource().asBareJid()); + try { + Set<Identity> identies = result.getResult(10, TimeUnit.SECONDS).getIdentities(); + for(Identity identity : identies) { + if ("pep".equalsIgnoreCase(identity.getType()) && "pubsub".equalsIgnoreCase(identity.getCategory())) { + return Result.PASSED; + } + } + return Result.FAILED; + } catch (Exception e) { + e.printStackTrace(); + return Result.FAILED; + } + } + + @Override + public String getName() { + return "XEP-0163: Personal Eventing Protocol"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/Push.java b/src/main/java/eu/siacs/compliance/tests/Push.java @@ -0,0 +1,29 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +import java.util.Arrays; +import java.util.List; + +public class Push extends AbstractDiscoTest { + + public Push(XmppClient client) { + super(client); + } + + @Override + List<String> getNamespaces() { + return Arrays.asList("urn:xmpp:push:0"); + } + + @Override + boolean checkOnServer() { + return false; + } + + + @Override + public String getName() { + return "XEP-0357: Push Notifications"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/RosterVersioning.java b/src/main/java/eu/siacs/compliance/tests/RosterVersioning.java @@ -0,0 +1,21 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.core.stream.model.StreamFeature; + + +public class RosterVersioning extends AbstractStreamFeatureTest { + public RosterVersioning(XmppClient client) { + super(client); + } + + @Override + Class<? extends StreamFeature> getStreamFeature() { + return rocks.xmpp.im.roster.versioning.model.RosterVersioning.class; + } + + @Override + public String getName() { + return "Roster Versioning"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/StreamManagement.java b/src/main/java/eu/siacs/compliance/tests/StreamManagement.java @@ -0,0 +1,21 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; +import rocks.xmpp.core.stream.model.StreamFeature; + +public class StreamManagement extends AbstractStreamFeatureTest { + + public StreamManagement(XmppClient client) { + super(client); + } + + @Override + Class<? extends StreamFeature> getStreamFeature() { + return rocks.xmpp.extensions.sm.model.StreamManagement.class; + } + + @Override + public String getName() { + return "XEP-0198: Stream Management"; + } +} diff --git a/src/main/java/eu/siacs/compliance/tests/TestFactory.java b/src/main/java/eu/siacs/compliance/tests/TestFactory.java @@ -0,0 +1,23 @@ +package eu.siacs.compliance.tests; + +import rocks.xmpp.core.session.XmppClient; + +public class TestFactory { + + public static AbstractTest create(Class <? extends AbstractTest> clazz, XmppClient client) throws TestCreationException { + if (client == null) { + throw new TestCreationException(); + } + try { + AbstractTest test = clazz.getDeclaredConstructor(XmppClient.class).newInstance(client); + return test; + } catch (Exception e) { + e.printStackTrace(); + throw new TestCreationException(); + } + } + + public static class TestCreationException extends Exception { + + } +}