mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-09 17:19:39 +02:00
SmackReactor/NIO, Java8/Android19, Pretty print XML, FSM connections
This commit adds - SmackReactor / NIO - a framework for finite state machine connections - support for Java 8 - pretty printed XML debug output It also - reworks the integration test framework - raises the minimum Android API level to 19 - introduces XmppNioTcpConnection Furthermore fixes SMACK-801 (at least partly). Java 8 language features are available, but not all runtime library methods. For that we would need to raise the Android API level to 24 or higher.
This commit is contained in:
parent
dba12919d0
commit
e98d42790a
144 changed files with 8692 additions and 1455 deletions
|
@ -0,0 +1,266 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.igniterealtime.smack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.MessageTypeFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.util.Async;
|
||||
import org.jivesoftware.smack.util.MultiMap;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.jiveproperties.JivePropertiesManager;
|
||||
import org.jivesoftware.smackx.jiveproperties.packet.JivePropertiesExtension;
|
||||
|
||||
import org.igniterealtime.smack.XmppConnectionStressTest.StressTestFailedException.ErrorsWhileSendingOrReceivingException;
|
||||
import org.igniterealtime.smack.XmppConnectionStressTest.StressTestFailedException.NotAllMessagesReceivedException;
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
|
||||
public class XmppConnectionStressTest {
|
||||
|
||||
private static final String MESSAGE_NUMBER_PROPERTY = "message-number";
|
||||
|
||||
public static class Configuration {
|
||||
public final long seed;
|
||||
public final int messagesPerConnection;
|
||||
public final int maxPayloadChunkSize;
|
||||
public final int maxPayloadChunks;
|
||||
public final boolean intermixMessages;
|
||||
|
||||
public Configuration(long seed, int messagesPerConnection, int maxPayloadChunkSize, int maxPayloadChunks,
|
||||
boolean intermixMessages) {
|
||||
this.seed = seed;
|
||||
this.messagesPerConnection = messagesPerConnection;
|
||||
this.maxPayloadChunkSize = maxPayloadChunkSize;
|
||||
this.maxPayloadChunks = maxPayloadChunks;
|
||||
this.intermixMessages = intermixMessages;
|
||||
}
|
||||
}
|
||||
|
||||
private final Configuration configuration;
|
||||
|
||||
public XmppConnectionStressTest(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
private volatile long waitStart;
|
||||
|
||||
public void run(List<? extends XMPPConnection> connections, final long replyTimeoutMillis)
|
||||
throws InterruptedException, NotAllMessagesReceivedException, ErrorsWhileSendingOrReceivingException {
|
||||
final MultiMap<XMPPConnection, Message> messages = new MultiMap<>();
|
||||
final Random random = new Random(configuration.seed);
|
||||
final Map<XMPPConnection, Exception> sendExceptions = new ConcurrentHashMap<>();
|
||||
final Map<XMPPConnection, Exception> receiveExceptions = new ConcurrentHashMap<>();
|
||||
|
||||
waitStart = -1;
|
||||
|
||||
for (XMPPConnection fromConnection : connections) {
|
||||
MultiMap<XMPPConnection, Message> toConnectionMessages = new MultiMap<>();
|
||||
for (XMPPConnection toConnection : connections) {
|
||||
for (int i = 0; i < configuration.messagesPerConnection; i++) {
|
||||
Message message = new Message();
|
||||
message.setTo(toConnection.getUser());
|
||||
|
||||
int payloadChunkCount = random.nextInt(configuration.maxPayloadChunks) + 1;
|
||||
for (int c = 0; c < payloadChunkCount; c++) {
|
||||
int payloadChunkSize = random.nextInt(configuration.maxPayloadChunkSize) + 1;
|
||||
String payloadCunk = StringUtils.randomString(payloadChunkSize, random);
|
||||
JivePropertiesManager.addProperty(message, "payload-chunk-" + c, payloadCunk);
|
||||
}
|
||||
|
||||
JivePropertiesManager.addProperty(message, MESSAGE_NUMBER_PROPERTY, i);
|
||||
|
||||
toConnectionMessages.put(toConnection, message);
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.intermixMessages) {
|
||||
while (!toConnectionMessages.isEmpty()) {
|
||||
int next = random.nextInt(connections.size());
|
||||
Message message = null;
|
||||
while (message == null) {
|
||||
XMPPConnection toConnection = connections.get(next);
|
||||
message = toConnectionMessages.getFirst(toConnection);
|
||||
next = (next + 1) % connections.size();
|
||||
}
|
||||
messages.put(fromConnection, message);
|
||||
}
|
||||
} else {
|
||||
for (XMPPConnection toConnection : connections) {
|
||||
for (Message message : toConnectionMessages.getAll(toConnection)) {
|
||||
messages.put(fromConnection, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Semaphore receivedSemaphore = new Semaphore(-connections.size() + 1);
|
||||
Map<XMPPConnection, Map<EntityFullJid, boolean[]>> receiveMarkers = new ConcurrentHashMap<>(connections.size());
|
||||
|
||||
for (XMPPConnection connection : connections) {
|
||||
connection.addSyncStanzaListener(new StanzaListener() {
|
||||
@Override
|
||||
public void processStanza(Stanza stanza) {
|
||||
waitStart = System.currentTimeMillis();
|
||||
|
||||
EntityFullJid from = stanza.getFrom().asEntityFullJidOrThrow();
|
||||
Message message = (Message) stanza;
|
||||
JivePropertiesExtension extension = JivePropertiesExtension.from(message);
|
||||
|
||||
Integer messageNumber = (Integer) extension.getProperty(MESSAGE_NUMBER_PROPERTY);
|
||||
|
||||
Map<EntityFullJid, boolean[]> myReceiveMarkers = receiveMarkers.get(connection);
|
||||
if (myReceiveMarkers == null) {
|
||||
myReceiveMarkers = new HashMap<>(connections.size());
|
||||
receiveMarkers.put(connection, myReceiveMarkers);
|
||||
}
|
||||
|
||||
boolean[] fromMarkers = myReceiveMarkers.get(from);
|
||||
if (fromMarkers == null) {
|
||||
fromMarkers = new boolean[configuration.messagesPerConnection];
|
||||
myReceiveMarkers.put(from, fromMarkers);
|
||||
}
|
||||
|
||||
// Sanity check: All markers before must be true, all markers including the messageNumber marker must be false.
|
||||
for (int i = 0; i < fromMarkers.length; i++) {
|
||||
if ((i < messageNumber && !fromMarkers[i])
|
||||
|| (i >= messageNumber && fromMarkers[i])) {
|
||||
// TODO: Better exception.
|
||||
Exception exception = new Exception("out of order");
|
||||
receiveExceptions.put(connection, exception);
|
||||
// TODO: Current Smack design does not guarantee that the listener won't be invoked again.
|
||||
// This is because the decission to invoke a sync listeners is done at a different place
|
||||
// then invoking the listener.
|
||||
connection.removeSyncStanzaListener(this);
|
||||
receivedSemaphore.release();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fromMarkers[messageNumber] = true;
|
||||
|
||||
if (myReceiveMarkers.size() != connections.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (boolean[] markers : myReceiveMarkers.values()) {
|
||||
for (boolean b : markers) {
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// All markers set to true, this means we received all messages.
|
||||
receivedSemaphore.release();
|
||||
}
|
||||
}, new AndFilter(MessageTypeFilter.NORMAL,
|
||||
new StanzaExtensionFilter(JivePropertiesExtension.ELEMENT, JivePropertiesExtension.NAMESPACE)));
|
||||
}
|
||||
|
||||
Semaphore sendSemaphore = new Semaphore(-connections.size() + 1);
|
||||
|
||||
for (XMPPConnection connection : connections) {
|
||||
Async.go(() -> {
|
||||
List<Message> messagesToSend;
|
||||
synchronized (messages) {
|
||||
messagesToSend = messages.getAll(connection);
|
||||
}
|
||||
try {
|
||||
for (Message messageToSend : messagesToSend) {
|
||||
connection.sendStanza(messageToSend);
|
||||
}
|
||||
} catch (NotConnectedException | InterruptedException e) {
|
||||
sendExceptions.put(connection, e);
|
||||
} finally {
|
||||
sendSemaphore.release();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sendSemaphore.acquire();
|
||||
|
||||
if (waitStart < 0) {
|
||||
waitStart = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
boolean acquired;
|
||||
do {
|
||||
long acquireWait = waitStart + replyTimeoutMillis - System.currentTimeMillis();
|
||||
acquired = receivedSemaphore.tryAcquire(acquireWait, TimeUnit.MILLISECONDS);
|
||||
} while (!acquired && System.currentTimeMillis() < waitStart + replyTimeoutMillis);
|
||||
|
||||
if (!acquired && receiveExceptions.isEmpty() && sendExceptions.isEmpty()) {
|
||||
throw new StressTestFailedException.NotAllMessagesReceivedException(receiveMarkers);
|
||||
}
|
||||
|
||||
if (!receiveExceptions.isEmpty() || !sendExceptions.isEmpty()) {
|
||||
throw new StressTestFailedException.ErrorsWhileSendingOrReceivingException(sendExceptions,
|
||||
receiveExceptions);
|
||||
}
|
||||
|
||||
// Test successful.
|
||||
}
|
||||
|
||||
public abstract static class StressTestFailedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected StressTestFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public static final class NotAllMessagesReceivedException extends StressTestFailedException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final Map<XMPPConnection, Map<EntityFullJid, boolean[]>> receiveMarkers;
|
||||
|
||||
private NotAllMessagesReceivedException(Map<XMPPConnection, Map<EntityFullJid, boolean[]>> receiveMarkers) {
|
||||
super("Did not receive all messages");
|
||||
this.receiveMarkers = receiveMarkers;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ErrorsWhileSendingOrReceivingException extends StressTestFailedException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final Map<XMPPConnection, Exception> sendExceptions;
|
||||
public final Map<XMPPConnection, Exception> receiveExceptions;
|
||||
|
||||
private ErrorsWhileSendingOrReceivingException(Map<XMPPConnection, Exception> sendExceptions,
|
||||
Map<XMPPConnection, Exception> receiveExceptions) {
|
||||
super("Exceptions while sending and/or receiving");
|
||||
this.sendExceptions = sendExceptions;
|
||||
this.receiveExceptions = receiveExceptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2016 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -45,10 +45,10 @@ public abstract class AbstractSmackIntTest {
|
|||
|
||||
protected final Configuration sinttestConfiguration;
|
||||
|
||||
protected AbstractSmackIntTest(String testRunId, Configuration configuration) {
|
||||
this.testRunId = testRunId;
|
||||
this.sinttestConfiguration = configuration;
|
||||
this.timeout = configuration.replyTimeout;
|
||||
protected AbstractSmackIntTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
this.testRunId = environment.testRunId;
|
||||
this.sinttestConfiguration = environment.configuration;
|
||||
this.timeout = environment.configuration.replyTimeout;
|
||||
}
|
||||
|
||||
protected void performActionAndWaitUntilStanzaReceived(Runnable action, XMPPConnection connection, StanzaFilter filter)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,6 +16,10 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
||||
public abstract class AbstractSmackIntegrationTest extends AbstractSmackIntTest {
|
||||
|
@ -40,10 +44,18 @@ public abstract class AbstractSmackIntegrationTest extends AbstractSmackIntTest
|
|||
*/
|
||||
protected final XMPPConnection connection;
|
||||
|
||||
public AbstractSmackIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
super(environment.testRunId, environment.configuration);
|
||||
protected final List<XMPPConnection> connections;
|
||||
|
||||
public AbstractSmackIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
this.connection = this.conOne = environment.conOne;
|
||||
this.conTwo = environment.conTwo;
|
||||
this.conThree = environment.conThree;
|
||||
|
||||
final List<XMPPConnection> connectionsLocal = new ArrayList<>(3);
|
||||
connectionsLocal.add(conOne);
|
||||
connectionsLocal.add(conTwo);
|
||||
connectionsLocal.add(conThree);
|
||||
this.connections = Collections.unmodifiableList(connectionsLocal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,17 +16,22 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
|
||||
public abstract class AbstractSmackLowLevelIntegrationTest extends AbstractSmackIntTest {
|
||||
|
||||
private final SmackIntegrationTestEnvironment environment;
|
||||
private final SmackIntegrationTestEnvironment<?> environment;
|
||||
|
||||
/**
|
||||
* The configuration
|
||||
|
@ -35,33 +40,36 @@ public abstract class AbstractSmackLowLevelIntegrationTest extends AbstractSmack
|
|||
|
||||
protected final DomainBareJid service;
|
||||
|
||||
public AbstractSmackLowLevelIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
super(environment.testRunId, environment.configuration);
|
||||
protected AbstractSmackLowLevelIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
this.environment = environment;
|
||||
this.configuration = environment.configuration;
|
||||
this.service = configuration.service;
|
||||
}
|
||||
|
||||
public final XMPPTCPConnectionConfiguration.Builder getConnectionConfiguration() throws KeyManagementException, NoSuchAlgorithmException {
|
||||
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();
|
||||
if (configuration.tlsContext != null) {
|
||||
builder.setCustomSSLContext(configuration.tlsContext);
|
||||
}
|
||||
builder.setSecurityMode(configuration.securityMode);
|
||||
builder.setXmppDomain(service);
|
||||
return builder;
|
||||
protected AbstractXMPPConnection getConnectedConnection() throws InterruptedException, XMPPException, SmackException, IOException {
|
||||
AbstractXMPPConnection connection = getUnconnectedConnection();
|
||||
connection.connect().login();
|
||||
return connection;
|
||||
}
|
||||
|
||||
protected void performCheck(ConnectionCallback callback) throws Exception {
|
||||
XMPPTCPConnection connection = SmackIntegrationTestFramework.getConnectedConnection(environment, -1);
|
||||
try {
|
||||
callback.connectionCallback(connection);
|
||||
} finally {
|
||||
IntTestUtil.disconnectAndMaybeDelete(connection, configuration);
|
||||
}
|
||||
protected AbstractXMPPConnection getUnconnectedConnection()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return environment.connectionManager.constructConnection();
|
||||
}
|
||||
|
||||
public interface ConnectionCallback {
|
||||
void connectionCallback(XMPPTCPConnection connection) throws Exception;
|
||||
protected List<AbstractXMPPConnection> getUnconnectedConnections(int count)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
List<AbstractXMPPConnection> connections = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
AbstractXMPPConnection connection = getUnconnectedConnection();
|
||||
connections.add(connection);
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
protected void recycle(AbstractXMPPConnection connection) {
|
||||
environment.connectionManager.recycle(connection);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.igniterealtime.smack.inttest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
|
||||
public abstract class AbstractSmackSpecificLowLevelIntegrationTest<C extends AbstractXMPPConnection>
|
||||
extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
private final SmackIntegrationTestEnvironment<?> environment;
|
||||
|
||||
protected final Class<C> connectionClass;
|
||||
|
||||
private final XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor;
|
||||
|
||||
public AbstractSmackSpecificLowLevelIntegrationTest(SmackIntegrationTestEnvironment<?> environment,
|
||||
Class<C> connectionClass) {
|
||||
super(environment);
|
||||
this.environment = environment;
|
||||
this.connectionClass = connectionClass;
|
||||
|
||||
connectionDescriptor = environment.connectionManager.getConnectionDescriptorFor(connectionClass);
|
||||
}
|
||||
|
||||
public Class<C> getConnectionClass() {
|
||||
return connectionClass;
|
||||
}
|
||||
|
||||
protected C getSpecificUnconnectedConnection() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return environment.connectionManager.constructConnection(connectionDescriptor);
|
||||
}
|
||||
|
||||
protected List<C> getSpecificUnconnectedConnections(int count)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
List<C> connections = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
C connection = getSpecificUnconnectedConnection();
|
||||
connections.add(connection);
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 Florian Schmaus
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -32,14 +32,18 @@ import java.util.logging.Logger;
|
|||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
||||
import org.jivesoftware.smack.debugger.ConsoleDebugger;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.debugger.EnhancedDebugger;
|
||||
|
||||
import eu.geekplace.javapinning.java7.Java7Pinning;
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
// TODO: Rename to SinttestConfiguration.
|
||||
public final class Configuration {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Configuration.class.getName());
|
||||
|
@ -92,6 +96,8 @@ public final class Configuration {
|
|||
|
||||
public final Set<String> testPackages;
|
||||
|
||||
public final ConnectionConfigurationBuilderApplier configurationApplier;
|
||||
|
||||
private Configuration(DomainBareJid service, String serviceTlsPin, SecurityMode securityMode, int replyTimeout,
|
||||
Debugger debugger, String accountOneUsername, String accountOnePassword, String accountTwoUsername,
|
||||
String accountTwoPassword, String accountThreeUsername, String accountThreePassword, Set<String> enabledTests, Set<String> disabledTests,
|
||||
|
@ -126,6 +132,13 @@ public final class Configuration {
|
|||
this.adminAccountUsername = adminAccountUsername;
|
||||
this.adminAccountPassword = adminAccountPassword;
|
||||
|
||||
boolean accountOnePasswordSet = StringUtils.isNotEmpty(accountOnePassword);
|
||||
if (accountOnePasswordSet != StringUtils.isNotEmpty(accountTwoPassword) ||
|
||||
accountOnePasswordSet != StringUtils.isNotEmpty(accountThreePassword)) {
|
||||
// Ensure the invariant that either all main accounts have a password set, or none.
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
this.accountOneUsername = accountOneUsername;
|
||||
this.accountOnePassword = accountOnePassword;
|
||||
this.accountTwoUsername = accountTwoUsername;
|
||||
|
@ -135,6 +148,26 @@ public final class Configuration {
|
|||
this.enabledTests = enabledTests;
|
||||
this.disabledTests = disabledTests;
|
||||
this.testPackages = testPackages;
|
||||
|
||||
this.configurationApplier = (builder) -> {
|
||||
if (tlsContext != null) {
|
||||
builder.setCustomSSLContext(tlsContext);
|
||||
}
|
||||
builder.setSecurityMode(securityMode);
|
||||
builder.setXmppDomain(service);
|
||||
|
||||
switch (debugger) {
|
||||
case enhanced:
|
||||
builder.setDebuggerFactory(EnhancedDebugger.Factory.INSTANCE);
|
||||
break;
|
||||
case console:
|
||||
builder.setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE);
|
||||
break;
|
||||
case none:
|
||||
// Nothing to do :).
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isAccountRegistrationPossible() {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018 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.igniterealtime.smack.inttest;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
|
||||
public interface ConnectionConfigurationBuilderApplier {
|
||||
void applyConfigurationTo(ConnectionConfiguration.Builder<?, ?> connectionConfigurationBuilder);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,15 +16,14 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class FailedTest extends TestResult {
|
||||
|
||||
public final Throwable failureReason;
|
||||
|
||||
public FailedTest(Method testMethod, long startTime, long endTime, List<String> logMessages, Throwable failureReason) {
|
||||
super(testMethod, startTime, endTime, logMessages);
|
||||
public FailedTest(SmackIntegrationTestFramework.ConcreteTest concreteTest, long startTime, long endTime, List<String> logMessages, Throwable failureReason) {
|
||||
super(concreteTest, startTime, endTime, logMessages);
|
||||
this.failureReason = failureReason;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 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.igniterealtime.smack.inttest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.admin.ServiceAdministrationManager;
|
||||
import org.jivesoftware.smackx.iqregister.AccountManager;
|
||||
|
||||
import org.igniterealtime.smack.inttest.Configuration.AccountRegistration;
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.jid.parts.Localpart;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
public class IntTestUtil {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IntTestUtil.class.getName());
|
||||
|
||||
|
||||
public static UsernameAndPassword registerAccount(XMPPTCPConnection connection, SmackIntegrationTestEnvironment environment, int connectionId) throws InterruptedException, XMPPException, SmackException, IOException {
|
||||
String username = "sinttest-" + environment.testRunId + "-" + connectionId;
|
||||
return registerAccount(connection, username, StringUtils.insecureRandomString(12), environment.configuration);
|
||||
}
|
||||
|
||||
public static UsernameAndPassword registerAccount(XMPPTCPConnection connection, String accountUsername, String accountPassword,
|
||||
Configuration config) throws InterruptedException, XMPPException, SmackException, IOException {
|
||||
switch (config.accountRegistration) {
|
||||
case inBandRegistration:
|
||||
return registerAccountViaIbr(connection, accountUsername, accountPassword);
|
||||
case serviceAdministration:
|
||||
return registerAccountViaAdmin(connection, accountUsername, accountPassword, config.adminAccountUsername, config.adminAccountPassword);
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
// public static UsernameAndPassword registerAccountViaAdmin(XMPPTCPConnection connection) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
// return registerAccountViaAdmin(connection, StringUtils.insecureRandomString(12),
|
||||
// StringUtils.insecureRandomString(12));
|
||||
// }
|
||||
|
||||
public static UsernameAndPassword registerAccountViaAdmin(XMPPTCPConnection connection, String username,
|
||||
String password, String adminAccountUsername, String adminAccountPassword) throws InterruptedException, XMPPException, SmackException, IOException {
|
||||
connection.login(adminAccountUsername, adminAccountPassword);
|
||||
|
||||
ServiceAdministrationManager adminManager = ServiceAdministrationManager.getInstanceFor(connection);
|
||||
|
||||
EntityBareJid userJid = JidCreate.entityBareFrom(Localpart.from(username), connection.getXMPPServiceDomain());
|
||||
adminManager.addUser(userJid, password);
|
||||
|
||||
connection.disconnect();
|
||||
connection.connect();
|
||||
|
||||
return new UsernameAndPassword(username, password);
|
||||
|
||||
}
|
||||
|
||||
public static UsernameAndPassword registerAccountViaIbr(XMPPConnection connection)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException,
|
||||
InterruptedException {
|
||||
return registerAccountViaIbr(connection, StringUtils.insecureRandomString(12),
|
||||
StringUtils.insecureRandomString(12));
|
||||
}
|
||||
|
||||
public static UsernameAndPassword registerAccountViaIbr(XMPPConnection connection, String username,
|
||||
String password) throws NoResponseException, XMPPErrorException,
|
||||
NotConnectedException, InterruptedException {
|
||||
AccountManager accountManager = AccountManager.getInstance(connection);
|
||||
if (!accountManager.supportsAccountCreation()) {
|
||||
throw new UnsupportedOperationException("Account creation/registation is not supported");
|
||||
}
|
||||
Set<String> requiredAttributes = accountManager.getAccountAttributes();
|
||||
if (requiredAttributes.size() > 4) {
|
||||
throw new IllegalStateException("Unkown required attributes");
|
||||
}
|
||||
Map<String, String> additionalAttributes = new HashMap<>();
|
||||
additionalAttributes.put("name", "Smack Integration Test");
|
||||
additionalAttributes.put("email", "flow@igniterealtime.org");
|
||||
Localpart usernameLocalpart;
|
||||
try {
|
||||
usernameLocalpart = Localpart.from(username);
|
||||
}
|
||||
catch (XmppStringprepException e) {
|
||||
throw new IllegalArgumentException("Invalid username: " + username, e);
|
||||
}
|
||||
accountManager.createAccount(usernameLocalpart, password, additionalAttributes);
|
||||
|
||||
return new UsernameAndPassword(username, password);
|
||||
}
|
||||
|
||||
public static final class UsernameAndPassword {
|
||||
public final String username;
|
||||
public final String password;
|
||||
|
||||
private UsernameAndPassword(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void disconnectAndMaybeDelete(XMPPTCPConnection connection, Configuration config) throws InterruptedException {
|
||||
try {
|
||||
if (!config.isAccountRegistrationPossible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration.AccountRegistration accountDeletionMethod = config.accountRegistration;
|
||||
|
||||
AccountManager accountManager = AccountManager.getInstance(connection);
|
||||
try {
|
||||
if (accountManager.isSupported()) {
|
||||
accountDeletionMethod = AccountRegistration.inBandRegistration;
|
||||
}
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not test if XEP-0077 account deletion is possible", e);
|
||||
}
|
||||
|
||||
switch (accountDeletionMethod) {
|
||||
case inBandRegistration:
|
||||
deleteViaIbr(connection);
|
||||
break;
|
||||
case serviceAdministration:
|
||||
deleteViaServiceAdministration(connection, config);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteViaServiceAdministration(XMPPTCPConnection connection, Configuration config) {
|
||||
EntityBareJid accountToDelete = connection.getUser().asEntityBareJid();
|
||||
|
||||
final int maxAttempts = 3;
|
||||
|
||||
int attempts;
|
||||
for (attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
connection.disconnect();
|
||||
|
||||
try {
|
||||
connection.connect().login(config.adminAccountUsername, config.adminAccountPassword);
|
||||
}
|
||||
catch (XMPPException | SmackException | IOException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Exception deleting account for " + connection, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
ServiceAdministrationManager adminManager = ServiceAdministrationManager.getInstanceFor(connection);
|
||||
try {
|
||||
adminManager.deleteUser(accountToDelete);
|
||||
break;
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Exception deleting account for " + connection, e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (attempts > maxAttempts) {
|
||||
LOGGER.log(Level.SEVERE, "Could not delete account for connection: " + connection);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteViaIbr(XMPPTCPConnection connection)
|
||||
throws InterruptedException {
|
||||
// If the connection is disconnected, then re-reconnect and login. This could happen when
|
||||
// (low-level) integration tests disconnect the connection, e.g. to test disconnection
|
||||
// mechanisms
|
||||
if (!connection.isConnected()) {
|
||||
try {
|
||||
connection.connect().login();
|
||||
}
|
||||
catch (XMPPException | SmackException | IOException e) {
|
||||
LOGGER.log(Level.WARNING, "Exception reconnection account for deletion", e);
|
||||
}
|
||||
}
|
||||
|
||||
final int maxAttempts = 3;
|
||||
AccountManager am = AccountManager.getInstance(connection);
|
||||
int attempts;
|
||||
for (attempts = 0; attempts < maxAttempts; attempts++) {
|
||||
try {
|
||||
am.deleteAccount();
|
||||
}
|
||||
catch (XMPPErrorException | NoResponseException e) {
|
||||
LOGGER.log(Level.WARNING, "Exception deleting account for " + connection, e);
|
||||
continue;
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
LOGGER.log(Level.WARNING, "Exception deleting account for " + connection, e);
|
||||
try {
|
||||
connection.connect().login();
|
||||
}
|
||||
catch (XMPPException | SmackException | IOException e2) {
|
||||
LOGGER.log(Level.WARNING, "Exception while trying to re-connect " + connection, e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
LOGGER.info("Successfully deleted account of " + connection);
|
||||
break;
|
||||
}
|
||||
if (attempts > maxAttempts) {
|
||||
LOGGER.log(Level.SEVERE, "Could not delete account for connection: " + connection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,13 +16,19 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface SmackIntegrationTest {
|
||||
|
||||
boolean onlyDefaultConnectionType() default false;
|
||||
|
||||
int connectionCount() default -1;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,26 +16,25 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
|
||||
public class SmackIntegrationTestEnvironment {
|
||||
public class SmackIntegrationTestEnvironment<C extends AbstractXMPPConnection> {
|
||||
|
||||
public final XMPPTCPConnection conOne;
|
||||
|
||||
public final XMPPTCPConnection conTwo;
|
||||
|
||||
public final XMPPTCPConnection conThree;
|
||||
public final C conOne, conTwo, conThree;
|
||||
|
||||
public final String testRunId;
|
||||
|
||||
public final Configuration configuration;
|
||||
|
||||
SmackIntegrationTestEnvironment(XMPPTCPConnection conOne, XMPPTCPConnection conTwo, XMPPTCPConnection conThree, String testRunId,
|
||||
Configuration configuration) {
|
||||
public final XmppConnectionManager<C> connectionManager;
|
||||
|
||||
SmackIntegrationTestEnvironment(C conOne, C conTwo, C conThree, String testRunId,
|
||||
Configuration configuration, XmppConnectionManager<C> connectionManager) {
|
||||
this.conOne = conOne;
|
||||
this.conTwo = conTwo;
|
||||
this.conThree = conThree;
|
||||
this.testRunId = testRunId;
|
||||
this.configuration = configuration;
|
||||
this.connectionManager = connectionManager;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -27,8 +27,12 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -43,21 +47,20 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.debugger.ConsoleDebugger;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.debugger.EnhancedDebugger;
|
||||
import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow;
|
||||
import org.jivesoftware.smackx.iqregister.AccountManager;
|
||||
|
||||
import org.igniterealtime.smack.inttest.IntTestUtil.UsernameAndPassword;
|
||||
import org.igniterealtime.smack.inttest.Configuration.AccountRegistration;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.reflections.Reflections;
|
||||
|
@ -66,51 +69,60 @@ import org.reflections.scanners.MethodParameterScanner;
|
|||
import org.reflections.scanners.SubTypesScanner;
|
||||
import org.reflections.scanners.TypeAnnotationsScanner;
|
||||
|
||||
public class SmackIntegrationTestFramework {
|
||||
public class SmackIntegrationTestFramework<DC extends AbstractXMPPConnection> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(SmackIntegrationTestFramework.class.getName());
|
||||
private static final char CLASS_METHOD_SEP = '#';
|
||||
|
||||
public static boolean SINTTEST_UNIT_TEST = false;
|
||||
|
||||
private final Class<DC> defaultConnectionClass;
|
||||
|
||||
protected final Configuration config;
|
||||
|
||||
protected TestRunResult testRunResult;
|
||||
private SmackIntegrationTestEnvironment environment;
|
||||
|
||||
private SmackIntegrationTestEnvironment<DC> environment;
|
||||
protected XmppConnectionManager<DC> connectionManager;
|
||||
|
||||
public enum TestType {
|
||||
Normal,
|
||||
LowLevel,
|
||||
SpecificLowLevel,
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, KeyManagementException,
|
||||
NoSuchAlgorithmException, SmackException, XMPPException, InterruptedException {
|
||||
NoSuchAlgorithmException, SmackException, XMPPException, InterruptedException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
Configuration config = Configuration.newConfiguration(args);
|
||||
|
||||
SmackIntegrationTestFramework sinttest = new SmackIntegrationTestFramework(config);
|
||||
SmackIntegrationTestFramework<XMPPTCPConnection> sinttest = new SmackIntegrationTestFramework<>(config, XMPPTCPConnection.class);
|
||||
TestRunResult testRunResult = sinttest.run();
|
||||
|
||||
for (Entry<Class<? extends AbstractSmackIntTest>, String> entry : testRunResult.impossibleTestClasses.entrySet()) {
|
||||
for (Entry<Class<? extends AbstractSmackIntTest>, Throwable> entry : testRunResult.impossibleTestClasses.entrySet()) {
|
||||
LOGGER.info("Could not run " + entry.getKey().getName() + " because: "
|
||||
+ entry.getValue());
|
||||
+ entry.getValue().getLocalizedMessage());
|
||||
}
|
||||
for (TestNotPossible testNotPossible : testRunResult.impossibleTestMethods) {
|
||||
LOGGER.info("Could not run " + testNotPossible.testMethod.getName() + " because: "
|
||||
for (TestNotPossible testNotPossible : testRunResult.impossibleIntegrationTests) {
|
||||
LOGGER.info("Could not run " + testNotPossible.concreteTest + " because: "
|
||||
+ testNotPossible.testNotPossibleException.getMessage());
|
||||
}
|
||||
final int successfulTests = testRunResult.successfulTests.size();
|
||||
for (SuccessfulTest successfulTest : testRunResult.successfulIntegrationTests) {
|
||||
LOGGER.info(successfulTest.concreteTest + " ✔");
|
||||
}
|
||||
final int successfulTests = testRunResult.successfulIntegrationTests.size();
|
||||
final int failedTests = testRunResult.failedIntegrationTests.size();
|
||||
final int totalIntegrationTests = successfulTests + failedTests;
|
||||
final int availableTests = testRunResult.getNumberOfAvailableTests();
|
||||
final int possibleTests = testRunResult.getNumberOfPossibleTests();
|
||||
LOGGER.info("SmackIntegrationTestFramework[" + testRunResult.testRunId + ']' + ": Finished ["
|
||||
+ successfulTests + '/' + possibleTests + "] (of " + availableTests + " available tests)");
|
||||
+ successfulTests + '/' + totalIntegrationTests + "] (" + possibleTests + " test methods of " + availableTests + " where possible)");
|
||||
|
||||
int exitStatus;
|
||||
if (!testRunResult.failedIntegrationTests.isEmpty()) {
|
||||
final int failedTests = testRunResult.failedIntegrationTests.size();
|
||||
LOGGER.warning("The following " + failedTests + " tests failed!");
|
||||
final int exitStatus;
|
||||
if (failedTests > 0) {
|
||||
LOGGER.warning("💀 The following " + failedTests + " tests failed! 💀");
|
||||
for (FailedTest failedTest : testRunResult.failedIntegrationTests) {
|
||||
final Method method = failedTest.testMethod;
|
||||
final String className = method.getDeclaringClass().getName();
|
||||
final String methodName = method.getName();
|
||||
final Throwable cause = failedTest.failureReason;
|
||||
LOGGER.severe(className + CLASS_METHOD_SEP + methodName + " failed: " + cause);
|
||||
LOGGER.log(Level.SEVERE, failedTest.concreteTest + " failed: " + cause, cause);
|
||||
}
|
||||
exitStatus = 2;
|
||||
} else {
|
||||
|
@ -129,13 +141,22 @@ public class SmackIntegrationTestFramework {
|
|||
System.exit(exitStatus);
|
||||
}
|
||||
|
||||
public SmackIntegrationTestFramework(Configuration configuration) {
|
||||
public SmackIntegrationTestFramework(Configuration configuration, Class<DC> defaultConnectionClass)
|
||||
throws KeyManagementException, InstantiationException, IllegalAccessException, IllegalArgumentException,
|
||||
InvocationTargetException, NoSuchAlgorithmException, SmackException, IOException, XMPPException,
|
||||
InterruptedException {
|
||||
this.config = configuration;
|
||||
this.defaultConnectionClass = defaultConnectionClass;
|
||||
}
|
||||
|
||||
public synchronized TestRunResult run() throws KeyManagementException, NoSuchAlgorithmException, SmackException,
|
||||
IOException, XMPPException, InterruptedException {
|
||||
public synchronized TestRunResult run()
|
||||
throws KeyManagementException, NoSuchAlgorithmException, SmackException, IOException, XMPPException,
|
||||
InterruptedException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
testRunResult = new TestRunResult();
|
||||
|
||||
// Create a connection manager *after* we created the testRunId (in testRunResult).
|
||||
this.connectionManager = new XmppConnectionManager<>(this, defaultConnectionClass);
|
||||
|
||||
LOGGER.info("SmackIntegrationTestFramework [" + testRunResult.testRunId + ']' + ": Starting");
|
||||
if (config.debugger != Configuration.Debugger.none) {
|
||||
// JUL Debugger will not print any information until configured to print log messages of
|
||||
|
@ -147,7 +168,7 @@ public class SmackIntegrationTestFramework {
|
|||
if (config.replyTimeout > 0) {
|
||||
SmackConfiguration.setDefaultReplyTimeout(config.replyTimeout);
|
||||
}
|
||||
if (config.securityMode != SecurityMode.required) {
|
||||
if (config.securityMode != SecurityMode.required && config.accountRegistration == AccountRegistration.inBandRegistration) {
|
||||
AccountManager.sensitiveOperationOverInsecureConnectionDefault(true);
|
||||
}
|
||||
// TODO print effective configuration
|
||||
|
@ -169,6 +190,18 @@ public class SmackIntegrationTestFramework {
|
|||
classes.addAll(inttestClasses);
|
||||
classes.addAll(lowLevelInttestClasses);
|
||||
|
||||
{
|
||||
// Remove all abstract classes.
|
||||
// TODO: This may be a good candidate for Java stream filtering once Smack is Android API 24 or higher.
|
||||
Iterator<Class<? extends AbstractSmackIntTest>> it = classes.iterator();
|
||||
while (it.hasNext()) {
|
||||
Class<? extends AbstractSmackIntTest> clazz = it.next();
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classes.isEmpty()) {
|
||||
throw new IllegalStateException("No test classes found");
|
||||
}
|
||||
|
@ -182,9 +215,7 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
finally {
|
||||
// Ensure that the accounts are deleted and disconnected before we continue
|
||||
disconnectAndMaybeDelete(environment.conOne);
|
||||
disconnectAndMaybeDelete(environment.conTwo);
|
||||
disconnectAndMaybeDelete(environment.conThree);
|
||||
connectionManager.disconnectAndCleanup();
|
||||
}
|
||||
|
||||
return testRunResult;
|
||||
|
@ -192,10 +223,42 @@ public class SmackIntegrationTestFramework {
|
|||
|
||||
@SuppressWarnings({"unchecked", "Finally"})
|
||||
private void runTests(Set<Class<? extends AbstractSmackIntTest>> classes)
|
||||
throws NoResponseException, InterruptedException {
|
||||
throws InterruptedException, InstantiationException, IllegalAccessException,
|
||||
IllegalArgumentException, SmackException, IOException, XMPPException {
|
||||
for (Class<? extends AbstractSmackIntTest> testClass : classes) {
|
||||
final String testClassName = testClass.getName();
|
||||
|
||||
// TODO: Move the whole "skipping section" below one layer up?
|
||||
|
||||
// Skip pseudo integration tests from src/test
|
||||
// Although Smack's gradle build files do not state that the 'main' sources classpath also contains the
|
||||
// 'test' classes. Some IDEs like Eclipse include them. As result, a real integration test run encounters
|
||||
// pseudo integration tests like the DummySmackIntegrationTest which always throws from src/test.
|
||||
// It is unclear why this apparently does not happen in the 4.3 branch, one likely cause is
|
||||
// compile project(path: ":smack-omemo", configuration: "testRuntime")
|
||||
// in
|
||||
// smack-integration-test/build.gradle:17
|
||||
// added after 4.3 was branched out with
|
||||
// 1f731f6318785a84b9741280d586a61dc37ecb2e
|
||||
// Now "gradle integrationTest" appear to be never affected by this, i.e., they are executed with the
|
||||
// correct classpath. Plain Eclipse, i.e. Smack imported into Eclipse after "gradle eclipse", appear
|
||||
// to include *all* classes. Which means those runs sooner or later try to execute
|
||||
// DummySmackIntegrationTest. Eclipse with buildship, the gradle plugin for Eclipse, always excludes
|
||||
// *all* src/test classes, which means they do not encounter DummySmackIntegrationTest, but this means
|
||||
// that the "compile project(path: ":smack-omemo", configuration: "testRuntime")" is not respected,
|
||||
// which leads to
|
||||
// Exception in thread "main" java.lang.NoClassDefFoundError: org/jivesoftware/smack/test/util/FileTestUtil
|
||||
// at org.jivesoftware.smackx.ox.OXSecretKeyBackupIntegrationTest.<clinit>(OXSecretKeyBackupIntegrationTest.java:66)
|
||||
// See
|
||||
// - https://github.com/eclipse/buildship/issues/354 (Remove test dependencies from runtime classpath)
|
||||
// - https://bugs.eclipse.org/bugs/show_bug.cgi?id=482315 (Runtime classpath includes test dependencies)
|
||||
// - https://discuss.gradle.org/t/main-vs-test-compile-vs-runtime-classpaths-in-eclipse-once-and-for-all-how/17403
|
||||
// - https://bugs.eclipse.org/bugs/show_bug.cgi?id=376616 (Scope of dependencies has no effect on Eclipse compilation)
|
||||
if (!SINTTEST_UNIT_TEST && testClassName.startsWith("org.igniterealtime.smack.inttest.unittest")) {
|
||||
LOGGER.finer("Skipping integration test '" + testClassName + "' from src/test classpath");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.enabledTests != null && !isInSet(testClass, config.enabledTests)) {
|
||||
LOGGER.info("Skipping test class " + testClassName + " because it is not enabled");
|
||||
continue;
|
||||
|
@ -206,46 +269,84 @@ public class SmackIntegrationTestFramework {
|
|||
continue;
|
||||
}
|
||||
|
||||
TestType testType;
|
||||
if (AbstractSmackLowLevelIntegrationTest.class.isAssignableFrom(testClass)) {
|
||||
final Constructor<? extends AbstractSmackIntTest> cons;
|
||||
try {
|
||||
cons = testClass.getConstructor(SmackIntegrationTestEnvironment.class);
|
||||
}
|
||||
catch (NoSuchMethodException | SecurityException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Smack Integration Test class does not declare the correct constructor. Is a public Constructor(SmackIntegrationTestEnvironment) missing?",
|
||||
e);
|
||||
}
|
||||
|
||||
final List<Method> smackIntegrationTestMethods;
|
||||
{
|
||||
Method[] testClassMethods = testClass.getMethods();
|
||||
smackIntegrationTestMethods = new ArrayList<>(testClassMethods.length);
|
||||
for (Method method : testClassMethods) {
|
||||
if (!method.isAnnotationPresent(SmackIntegrationTest.class)) {
|
||||
continue;
|
||||
}
|
||||
smackIntegrationTestMethods.add(method);
|
||||
}
|
||||
}
|
||||
|
||||
if (smackIntegrationTestMethods.isEmpty()) {
|
||||
LOGGER.warning("No Smack integration test methods found in " + testClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
testRunResult.numberOfAvailableTestMethods.addAndGet(smackIntegrationTestMethods.size());
|
||||
|
||||
final AbstractSmackIntTest test;
|
||||
try {
|
||||
test = cons.newInstance(environment);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
|
||||
throwFatalException(cause);
|
||||
|
||||
testRunResult.impossibleTestClasses.put(testClass, cause);
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<? extends AbstractXMPPConnection> specificLowLevelConnectionClass = null;
|
||||
final TestType testType;
|
||||
if (test instanceof AbstractSmackSpecificLowLevelIntegrationTest) {
|
||||
AbstractSmackSpecificLowLevelIntegrationTest<?> specificLowLevelTest = (AbstractSmackSpecificLowLevelIntegrationTest<?>) test;
|
||||
specificLowLevelConnectionClass = specificLowLevelTest.getConnectionClass();
|
||||
testType = TestType.SpecificLowLevel;
|
||||
} else if (test instanceof AbstractSmackLowLevelIntegrationTest) {
|
||||
testType = TestType.LowLevel;
|
||||
} else if (AbstractSmackIntegrationTest.class.isAssignableFrom(testClass)) {
|
||||
} else if (test instanceof AbstractSmackIntegrationTest) {
|
||||
testType = TestType.Normal;
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
List<Method> smackIntegrationTestMethods = new LinkedList<>();
|
||||
for (Method method : testClass.getMethods()) {
|
||||
if (!method.isAnnotationPresent(SmackIntegrationTest.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify the method signatures, throw in case a signature is incorrect.
|
||||
for (Method method : smackIntegrationTestMethods) {
|
||||
Class<?> retClass = method.getReturnType();
|
||||
if (!retClass.equals(Void.TYPE)) {
|
||||
LOGGER.warning("SmackIntegrationTest annotation on method that does not return void");
|
||||
continue;
|
||||
throw new IllegalStateException(
|
||||
"SmackIntegrationTest annotation on" + method + " that does not return void");
|
||||
}
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
switch (testType) {
|
||||
case Normal:
|
||||
if (method.getParameterTypes().length > 0) {
|
||||
LOGGER.warning("SmackIntegrationTest annotaton on method that takes arguments ");
|
||||
continue;
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length > 0) {
|
||||
throw new IllegalStateException(
|
||||
"SmackIntegrationTest annotaton on " + method + " that takes arguments ");
|
||||
}
|
||||
break;
|
||||
case LowLevel:
|
||||
for (Class<?> parameterType : parameterTypes) {
|
||||
if (!parameterType.isAssignableFrom(XMPPTCPConnection.class)) {
|
||||
LOGGER.warning("SmackIntegrationTest low-level test method declares parameter that is not of type XMPPTCPConnection");
|
||||
}
|
||||
}
|
||||
verifyLowLevelTestMethod(method, AbstractXMPPConnection.class);
|
||||
break;
|
||||
case SpecificLowLevel:
|
||||
verifyLowLevelTestMethod(method, specificLowLevelConnectionClass);
|
||||
break;
|
||||
}
|
||||
smackIntegrationTestMethods.add(method);
|
||||
}
|
||||
|
||||
if (smackIntegrationTestMethods.isEmpty()) {
|
||||
LOGGER.warning("No integration test methods found");
|
||||
continue;
|
||||
}
|
||||
|
||||
Iterator<Method> it = smackIntegrationTestMethods.iterator();
|
||||
|
@ -271,75 +372,7 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
|
||||
final int detectedTestMethodsCount = smackIntegrationTestMethods.size();
|
||||
testRunResult.numberOfAvailableTests.addAndGet(detectedTestMethodsCount);
|
||||
testRunResult.numberOfPossibleTests.addAndGet(detectedTestMethodsCount);
|
||||
|
||||
AbstractSmackIntTest test;
|
||||
switch (testType) {
|
||||
case Normal: {
|
||||
Constructor<? extends AbstractSmackIntegrationTest> cons;
|
||||
try {
|
||||
cons = ((Class<? extends AbstractSmackIntegrationTest>) testClass).getConstructor(SmackIntegrationTestEnvironment.class);
|
||||
}
|
||||
catch (NoSuchMethodException | SecurityException e) {
|
||||
LOGGER.log(Level.WARNING,
|
||||
"Smack Integration Test class could not get constructed (public Con)structor(SmackIntegrationTestEnvironment) missing?)",
|
||||
e);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
test = cons.newInstance(environment);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
throwFatalException(cause);
|
||||
|
||||
testRunResult.impossibleTestClasses.put(testClass, cause.getMessage());
|
||||
testRunResult.numberOfPossibleTests.addAndGet(-detectedTestMethodsCount);
|
||||
continue;
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | IllegalArgumentException e) {
|
||||
LOGGER.log(Level.WARNING, "todo", e);
|
||||
continue;
|
||||
}
|
||||
} break;
|
||||
case LowLevel: {
|
||||
Constructor<? extends AbstractSmackLowLevelIntegrationTest> cons;
|
||||
try {
|
||||
cons = ((Class<? extends AbstractSmackLowLevelIntegrationTest>) testClass).getConstructor(
|
||||
SmackIntegrationTestEnvironment.class);
|
||||
}
|
||||
catch (NoSuchMethodException | SecurityException e) {
|
||||
LOGGER.log(Level.WARNING,
|
||||
"Smack Integration Test class could not get constructed (public Con)structor(SmackIntegrationTestEnvironment) missing?)",
|
||||
e);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
test = cons.newInstance(environment);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof TestNotPossibleException) {
|
||||
testRunResult.impossibleTestClasses.put(testClass, cause.getMessage());
|
||||
testRunResult.numberOfPossibleTests.addAndGet(-detectedTestMethodsCount);
|
||||
}
|
||||
else {
|
||||
throwFatalException(cause);
|
||||
LOGGER.log(Level.WARNING, "Could not construct test class", e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | IllegalArgumentException e) {
|
||||
LOGGER.log(Level.WARNING, "todo", e);
|
||||
continue;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
testRunResult.numberOfPossibleTestMethods.addAndGet(detectedTestMethodsCount);
|
||||
|
||||
try {
|
||||
// Run the @BeforeClass methods (if any)
|
||||
|
@ -373,48 +406,36 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
|
||||
for (Method testMethod : smackIntegrationTestMethods) {
|
||||
final String testPrefix = testClass.getSimpleName() + '.'
|
||||
+ testMethod.getName() + " (" + testType + "): ";
|
||||
// Invoke all test methods on the test instance
|
||||
LOGGER.info(testPrefix + "Start");
|
||||
long testStart = System.currentTimeMillis();
|
||||
try {
|
||||
List<ConcreteTest> concreteTests = null;
|
||||
switch (testType) {
|
||||
case Normal: {
|
||||
ConcreteTest.Executor concreteTestExecutor = () -> testMethod.invoke(test);
|
||||
ConcreteTest concreteTest = new ConcreteTest(testType, testMethod, concreteTestExecutor);
|
||||
concreteTests = Collections.singletonList(concreteTest);
|
||||
}
|
||||
break;
|
||||
case LowLevel:
|
||||
case SpecificLowLevel:
|
||||
LowLevelTestMethod lowLevelTestMethod = new LowLevelTestMethod(testMethod);
|
||||
switch (testType) {
|
||||
case Normal:
|
||||
testMethod.invoke(test);
|
||||
break;
|
||||
case LowLevel:
|
||||
invokeLowLevel(testMethod, test);
|
||||
concreteTests = invokeLowLevel(lowLevelTestMethod, (AbstractSmackLowLevelIntegrationTest) test);
|
||||
break;
|
||||
case SpecificLowLevel: {
|
||||
ConcreteTest.Executor concreteTestExecutor = () -> invokeSpecificLowLevel(
|
||||
lowLevelTestMethod, (AbstractSmackSpecificLowLevelIntegrationTest<?>) test);
|
||||
ConcreteTest concreteTest = new ConcreteTest(testType, testMethod, concreteTestExecutor);
|
||||
concreteTests = Collections.singletonList(concreteTest);
|
||||
break;
|
||||
}
|
||||
LOGGER.info(testPrefix + "Success");
|
||||
long testEnd = System.currentTimeMillis();
|
||||
testRunResult.successfulTests.add(new SuccessfulTest(testMethod, testStart, testEnd, null));
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
long testEnd = System.currentTimeMillis();
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof TestNotPossibleException) {
|
||||
LOGGER.info(testPrefix + "Not possible");
|
||||
testRunResult.impossibleTestMethods.add(new TestNotPossible(testMethod, testStart, testEnd,
|
||||
null, (TestNotPossibleException) cause));
|
||||
continue;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
Throwable nonFatalFailureReason;
|
||||
// junit assert's throw an AssertionError if they fail, those should not be
|
||||
// thrown up, as it would be done by throwFatalException()
|
||||
if (cause instanceof AssertionError) {
|
||||
nonFatalFailureReason = cause;
|
||||
} else {
|
||||
nonFatalFailureReason = throwFatalException(cause);
|
||||
}
|
||||
// An integration test failed
|
||||
testRunResult.failedIntegrationTests.add(new FailedTest(testMethod, testStart, testEnd, null,
|
||||
nonFatalFailureReason));
|
||||
LOGGER.log(Level.SEVERE, testPrefix + "Failed", e);
|
||||
break;
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
|
||||
for (ConcreteTest concreteTest : concreteTests) {
|
||||
runConcreteTest(concreteTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,67 +473,86 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
}
|
||||
|
||||
private void invokeLowLevel(Method testMethod, AbstractSmackIntTest test) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InterruptedException {
|
||||
// We have checked before that every parameter, if any, is of type XMPPTCPConnection
|
||||
final int numberOfConnections = testMethod.getParameterTypes().length;
|
||||
XMPPTCPConnection[] connections = null;
|
||||
private void runConcreteTest(ConcreteTest concreteTest)
|
||||
throws InterruptedException, XMPPException, IOException, SmackException {
|
||||
LOGGER.info(concreteTest + " Start");
|
||||
long testStart = System.currentTimeMillis();
|
||||
try {
|
||||
if (numberOfConnections > 0 && !config.isAccountRegistrationPossible()) {
|
||||
throw new TestNotPossibleException(
|
||||
"Must create accounts for this test, but it's not enabled");
|
||||
}
|
||||
connections = new XMPPTCPConnection[numberOfConnections];
|
||||
for (int i = 0; i < numberOfConnections; ++i) {
|
||||
connections[i] = getConnectedConnection(environment, i);
|
||||
}
|
||||
concreteTest.executor.execute();
|
||||
long testEnd = System.currentTimeMillis();
|
||||
LOGGER.info(concreteTest + " Success");
|
||||
testRunResult.successfulIntegrationTests.add(new SuccessfulTest(concreteTest, testStart, testEnd, null));
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
catch (InvocationTargetException e) {
|
||||
long testEnd = System.currentTimeMillis();
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof TestNotPossibleException) {
|
||||
LOGGER.info(concreteTest + " is not possible");
|
||||
testRunResult.impossibleIntegrationTests.add(new TestNotPossible(concreteTest, testStart, testEnd,
|
||||
null, (TestNotPossibleException) cause));
|
||||
return;
|
||||
}
|
||||
// Behave like this was an InvocationTargetException
|
||||
throw new InvocationTargetException(e);
|
||||
}
|
||||
try {
|
||||
testMethod.invoke(test, (Object[]) connections);
|
||||
}
|
||||
finally {
|
||||
for (int i = 0; i < numberOfConnections; ++i) {
|
||||
IntTestUtil.disconnectAndMaybeDelete(connections[i], config);
|
||||
Throwable nonFatalFailureReason;
|
||||
// junit assert's throw an AssertionError if they fail, those should not be
|
||||
// thrown up, as it would be done by throwFatalException()
|
||||
if (cause instanceof AssertionError) {
|
||||
nonFatalFailureReason = cause;
|
||||
} else {
|
||||
nonFatalFailureReason = throwFatalException(cause);
|
||||
}
|
||||
// An integration test failed
|
||||
testRunResult.failedIntegrationTests.add(new FailedTest(concreteTest, testStart, testEnd, null,
|
||||
nonFatalFailureReason));
|
||||
LOGGER.log(Level.SEVERE, concreteTest + " Failed", e);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void disconnectAndMaybeDelete(XMPPTCPConnection connection) throws InterruptedException {
|
||||
IntTestUtil.disconnectAndMaybeDelete(connection, config);
|
||||
private static void verifyLowLevelTestMethod(Method method,
|
||||
Class<? extends AbstractXMPPConnection> connectionClass) {
|
||||
if (!testMethodParametersIsListOfConnections(method, connectionClass)
|
||||
&& !testMethodParametersVarargsConnections(method, connectionClass)) {
|
||||
throw new IllegalArgumentException(method + " is not a valid low level test method");
|
||||
}
|
||||
}
|
||||
|
||||
protected SmackIntegrationTestEnvironment prepareEnvironment() throws SmackException,
|
||||
private List<ConcreteTest> invokeLowLevel(LowLevelTestMethod lowLevelTestMethod, AbstractSmackLowLevelIntegrationTest test) {
|
||||
Set<Class<? extends AbstractXMPPConnection>> connectionClasses;
|
||||
if (lowLevelTestMethod.smackIntegrationTestAnnotation.onlyDefaultConnectionType()) {
|
||||
Class<? extends AbstractXMPPConnection> defaultConnectionClass = connectionManager.getDefaultConnectionClass();
|
||||
connectionClasses = Collections.singleton(defaultConnectionClass);
|
||||
} else {
|
||||
connectionClasses = connectionManager.getConnectionClasses();
|
||||
}
|
||||
|
||||
List<ConcreteTest> resultingConcreteTests = new ArrayList<>(connectionClasses.size());
|
||||
|
||||
for (Class<? extends AbstractXMPPConnection> connectionClass : connectionClasses) {
|
||||
ConcreteTest.Executor executor = () -> lowLevelTestMethod.invoke(test, connectionClass);
|
||||
ConcreteTest concreteTest = new ConcreteTest(TestType.LowLevel, lowLevelTestMethod.testMethod, executor, connectionClass.getSimpleName());
|
||||
resultingConcreteTests.add(concreteTest);
|
||||
}
|
||||
|
||||
return resultingConcreteTests;
|
||||
}
|
||||
|
||||
private <C extends AbstractXMPPConnection> void invokeSpecificLowLevel(LowLevelTestMethod testMethod,
|
||||
AbstractSmackSpecificLowLevelIntegrationTest<C> test)
|
||||
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InterruptedException,
|
||||
SmackException, IOException, XMPPException {
|
||||
if (testMethod.smackIntegrationTestAnnotation.onlyDefaultConnectionType()) {
|
||||
throw new IllegalArgumentException("SpecificLowLevelTests must not have set onlyDefaultConnectionType");
|
||||
}
|
||||
Class<C> connectionClass = test.getConnectionClass();
|
||||
testMethod.invoke(test, connectionClass);
|
||||
}
|
||||
|
||||
protected SmackIntegrationTestEnvironment<DC> prepareEnvironment() throws SmackException,
|
||||
IOException, XMPPException, InterruptedException, KeyManagementException,
|
||||
NoSuchAlgorithmException {
|
||||
XMPPTCPConnection conOne = null;
|
||||
XMPPTCPConnection conTwo = null;
|
||||
XMPPTCPConnection conThree = null;
|
||||
try {
|
||||
conOne = getConnectedConnectionFor(AccountNum.One);
|
||||
conTwo = getConnectedConnectionFor(AccountNum.Two);
|
||||
conThree = getConnectedConnectionFor(AccountNum.Three);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO Reverse the order, i.e. conThree should be disconnected first.
|
||||
if (conOne != null) {
|
||||
conOne.disconnect();
|
||||
}
|
||||
if (conTwo != null) {
|
||||
conTwo.disconnect();
|
||||
}
|
||||
if (conThree != null) {
|
||||
conThree.disconnect();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
return new SmackIntegrationTestEnvironment(conOne, conTwo, conThree, testRunResult.testRunId, config);
|
||||
NoSuchAlgorithmException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
return connectionManager.prepareEnvironment();
|
||||
}
|
||||
|
||||
enum AccountNum {
|
||||
|
@ -521,99 +561,14 @@ public class SmackIntegrationTestFramework {
|
|||
Three,
|
||||
}
|
||||
|
||||
private static final String USERNAME_PREFIX = "smack-inttest";
|
||||
|
||||
private XMPPTCPConnection getConnectedConnectionFor(AccountNum accountNum)
|
||||
throws SmackException, IOException, XMPPException, InterruptedException,
|
||||
KeyManagementException, NoSuchAlgorithmException {
|
||||
String middlefix;
|
||||
String accountUsername;
|
||||
String accountPassword;
|
||||
switch (accountNum) {
|
||||
case One:
|
||||
accountUsername = config.accountOneUsername;
|
||||
accountPassword = config.accountOnePassword;
|
||||
middlefix = "one";
|
||||
break;
|
||||
case Two:
|
||||
accountUsername = config.accountTwoUsername;
|
||||
accountPassword = config.accountTwoPassword;
|
||||
middlefix = "two";
|
||||
break;
|
||||
case Three:
|
||||
accountUsername = config.accountThreeUsername;
|
||||
accountPassword = config.accountThreePassword;
|
||||
middlefix = "three";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (StringUtils.isNullOrEmpty(accountUsername)) {
|
||||
accountUsername = USERNAME_PREFIX + '-' + middlefix + '-' + testRunResult.testRunId;
|
||||
}
|
||||
if (StringUtils.isNullOrEmpty(accountPassword)) {
|
||||
accountPassword = StringUtils.insecureRandomString(16);
|
||||
}
|
||||
|
||||
XMPPTCPConnectionConfiguration.Builder builder = getConnectionConfigurationBuilder(config);
|
||||
builder.setUsernameAndPassword(accountUsername, accountPassword)
|
||||
.setResource(middlefix + '-' + testRunResult.testRunId);
|
||||
|
||||
XMPPTCPConnection connection = new XMPPTCPConnection(builder.build());
|
||||
connection.connect();
|
||||
if (config.isAccountRegistrationPossible()) {
|
||||
UsernameAndPassword uap = IntTestUtil.registerAccount(connection, accountUsername, accountPassword, config);
|
||||
|
||||
// TODO is this still required?
|
||||
// Some servers, e.g. Openfire, do not support a login right after the account was
|
||||
// created, so disconnect and re-connection the connection first.
|
||||
connection.disconnect();
|
||||
connection.connect();
|
||||
|
||||
connection.login(uap.username, uap.password);
|
||||
} else {
|
||||
connection.login();
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
static XMPPTCPConnectionConfiguration.Builder getConnectionConfigurationBuilder(Configuration config) {
|
||||
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();
|
||||
if (config.tlsContext != null) {
|
||||
builder.setCustomSSLContext(config.tlsContext);
|
||||
}
|
||||
builder.setSecurityMode(config.securityMode);
|
||||
builder.setXmppDomain(config.service);
|
||||
|
||||
switch (config.debugger) {
|
||||
case enhanced:
|
||||
builder.setDebuggerFactory(EnhancedDebugger.Factory.INSTANCE);
|
||||
break;
|
||||
case console:
|
||||
builder.setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE);
|
||||
break;
|
||||
case none:
|
||||
// Nothing to do :).
|
||||
break;
|
||||
}
|
||||
config.configurationApplier.applyConfigurationTo(builder);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
static XMPPTCPConnection getConnectedConnection(SmackIntegrationTestEnvironment environment, int connectionId)
|
||||
throws KeyManagementException, NoSuchAlgorithmException, InterruptedException,
|
||||
SmackException, IOException, XMPPException {
|
||||
Configuration config = environment.configuration;
|
||||
XMPPTCPConnectionConfiguration.Builder builder = getConnectionConfigurationBuilder(config);
|
||||
|
||||
XMPPTCPConnection connection = new XMPPTCPConnection(builder.build());
|
||||
connection.connect();
|
||||
UsernameAndPassword uap = IntTestUtil.registerAccount(connection, environment, connectionId);
|
||||
connection.login(uap.username, uap.password);
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static Exception throwFatalException(Throwable e) throws Error, NoResponseException,
|
||||
InterruptedException {
|
||||
if (e instanceof NoResponseException) {
|
||||
|
@ -649,14 +604,14 @@ public class SmackIntegrationTestFramework {
|
|||
*/
|
||||
public final String testRunId = StringUtils.insecureRandomString(5).toLowerCase(Locale.US);
|
||||
|
||||
private final List<SuccessfulTest> successfulTests = Collections.synchronizedList(new LinkedList<SuccessfulTest>());
|
||||
private final List<SuccessfulTest> successfulIntegrationTests = Collections.synchronizedList(new LinkedList<SuccessfulTest>());
|
||||
private final List<FailedTest> failedIntegrationTests = Collections.synchronizedList(new LinkedList<FailedTest>());
|
||||
private final List<TestNotPossible> impossibleTestMethods = Collections.synchronizedList(new LinkedList<TestNotPossible>());
|
||||
private final Map<Class<? extends AbstractSmackIntTest>, String> impossibleTestClasses = new HashMap<>();
|
||||
private final AtomicInteger numberOfAvailableTests = new AtomicInteger();
|
||||
private final AtomicInteger numberOfPossibleTests = new AtomicInteger();
|
||||
private final List<TestNotPossible> impossibleIntegrationTests = Collections.synchronizedList(new LinkedList<TestNotPossible>());
|
||||
private final Map<Class<? extends AbstractSmackIntTest>, Throwable> impossibleTestClasses = new HashMap<>();
|
||||
private final AtomicInteger numberOfAvailableTestMethods = new AtomicInteger();
|
||||
private final AtomicInteger numberOfPossibleTestMethods = new AtomicInteger();
|
||||
|
||||
private TestRunResult() {
|
||||
TestRunResult() {
|
||||
}
|
||||
|
||||
public String getTestRunId() {
|
||||
|
@ -664,15 +619,15 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
|
||||
public int getNumberOfAvailableTests() {
|
||||
return numberOfAvailableTests.get();
|
||||
return numberOfAvailableTestMethods.get();
|
||||
}
|
||||
|
||||
public int getNumberOfPossibleTests() {
|
||||
return numberOfPossibleTests.get();
|
||||
return numberOfPossibleTestMethods.get();
|
||||
}
|
||||
|
||||
public List<SuccessfulTest> getSuccessfulTests() {
|
||||
return Collections.unmodifiableList(successfulTests);
|
||||
return Collections.unmodifiableList(successfulIntegrationTests);
|
||||
}
|
||||
|
||||
public List<FailedTest> getFailedTests() {
|
||||
|
@ -680,11 +635,154 @@ public class SmackIntegrationTestFramework {
|
|||
}
|
||||
|
||||
public List<TestNotPossible> getNotPossibleTests() {
|
||||
return Collections.unmodifiableList(impossibleTestMethods);
|
||||
return Collections.unmodifiableList(impossibleIntegrationTests);
|
||||
}
|
||||
|
||||
public Map<Class<? extends AbstractSmackIntTest>, String> getImpossibleTestClasses() {
|
||||
public Map<Class<? extends AbstractSmackIntTest>, Throwable> getImpossibleTestClasses() {
|
||||
return Collections.unmodifiableMap(impossibleTestClasses);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ConcreteTest {
|
||||
private final TestType testType;
|
||||
private final Method method;
|
||||
private final Executor executor;
|
||||
private final String[] subdescriptons;
|
||||
|
||||
private ConcreteTest(TestType testType, Method method, Executor executor, String... subdescriptions) {
|
||||
this.testType = testType;
|
||||
this.method = method;
|
||||
this.executor = executor;
|
||||
this.subdescriptons = subdescriptions;
|
||||
}
|
||||
|
||||
private transient String stringCache;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (stringCache != null) {
|
||||
return stringCache;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(method.getDeclaringClass().getSimpleName())
|
||||
.append('.')
|
||||
.append(method.getName())
|
||||
.append(" (")
|
||||
.append(testType.name());
|
||||
final String SUBDESCRIPTION_DELIMITER = ", ";
|
||||
sb.append(SUBDESCRIPTION_DELIMITER);
|
||||
|
||||
for (String subdescripton : subdescriptons) {
|
||||
sb.append(subdescripton).append(SUBDESCRIPTION_DELIMITER);
|
||||
}
|
||||
sb.setLength(sb.length() - SUBDESCRIPTION_DELIMITER.length());
|
||||
sb.append(')');
|
||||
|
||||
stringCache = sb.toString();
|
||||
return stringCache;
|
||||
}
|
||||
|
||||
private interface Executor {
|
||||
|
||||
/**
|
||||
* Execute the test.
|
||||
*
|
||||
* @throws IllegalAccessException
|
||||
* @throws InterruptedException
|
||||
* @throws InvocationTargetException if the reflective invoked test throws an exception.
|
||||
* @throws XMPPException in case an XMPPException happens when <em>preparing</em> the test.
|
||||
* @throws IOException in case an IOException happens when <em>preparing</em> the test.
|
||||
* @throws SmackException in case an SmackException happens when <em>preparing</em> the test.
|
||||
*/
|
||||
void execute() throws IllegalAccessException, InterruptedException, InvocationTargetException,
|
||||
XMPPException, IOException, SmackException;
|
||||
}
|
||||
}
|
||||
|
||||
private final class LowLevelTestMethod {
|
||||
private final Method testMethod;
|
||||
private final SmackIntegrationTest smackIntegrationTestAnnotation;
|
||||
private final boolean parameterListOfConnections;
|
||||
|
||||
private LowLevelTestMethod(Method testMethod) {
|
||||
this.testMethod = testMethod;
|
||||
|
||||
smackIntegrationTestAnnotation = testMethod.getAnnotation(SmackIntegrationTest.class);
|
||||
assert (smackIntegrationTestAnnotation != null);
|
||||
parameterListOfConnections = testMethodParametersIsListOfConnections(testMethod);
|
||||
}
|
||||
|
||||
private void invoke(AbstractSmackLowLevelIntegrationTest test,
|
||||
Class<? extends AbstractXMPPConnection> connectionClass)
|
||||
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
|
||||
InterruptedException, SmackException, IOException, XMPPException {
|
||||
final int connectionCount;
|
||||
if (parameterListOfConnections) {
|
||||
connectionCount = smackIntegrationTestAnnotation.connectionCount();
|
||||
if (connectionCount < 1) {
|
||||
throw new IllegalArgumentException(testMethod + " is annotated to use less than one connection ('"
|
||||
+ connectionCount + ')');
|
||||
}
|
||||
} else {
|
||||
connectionCount = testMethod.getParameterCount();
|
||||
}
|
||||
|
||||
List<? extends AbstractXMPPConnection> connections = connectionManager.constructConnectedConnections(
|
||||
connectionClass, connectionCount);
|
||||
|
||||
if (parameterListOfConnections) {
|
||||
testMethod.invoke(test, connections);
|
||||
} else {
|
||||
Object[] connectionsArray = new Object[connectionCount];
|
||||
for (int i = 0; i < connectionsArray.length; i++) {
|
||||
connectionsArray[i] = connections.remove(0);
|
||||
}
|
||||
testMethod.invoke(test, connectionsArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean testMethodParametersIsListOfConnections(Method testMethod) {
|
||||
return testMethodParametersIsListOfConnections(testMethod, AbstractXMPPConnection.class);
|
||||
}
|
||||
|
||||
static boolean testMethodParametersIsListOfConnections(Method testMethod, Class<? extends AbstractXMPPConnection> connectionClass) {
|
||||
Type[] parameterTypes = testMethod.getGenericParameterTypes();
|
||||
if (parameterTypes.length != 1) {
|
||||
return false;
|
||||
}
|
||||
Class<?> soleParameter = testMethod.getParameterTypes()[0];
|
||||
if (!Collection.class.isAssignableFrom(soleParameter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ParameterizedType soleParameterizedType = (ParameterizedType) parameterTypes[0];
|
||||
Type[] actualTypeArguments = soleParameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type soleActualTypeArgument = actualTypeArguments[0];
|
||||
if (!(soleActualTypeArgument instanceof Class<?>)) {
|
||||
return false;
|
||||
}
|
||||
Class<?> soleActualTypeArgumentAsClass = (Class<?>) soleActualTypeArgument;
|
||||
if (!connectionClass.isAssignableFrom(soleActualTypeArgumentAsClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean testMethodParametersVarargsConnections(Method testMethod, Class<? extends AbstractXMPPConnection> connectionClass) {
|
||||
Class<?>[] parameterTypes = testMethod.getParameterTypes();
|
||||
for (Class<?> parameterType : parameterTypes) {
|
||||
if (!parameterType.isAssignableFrom(connectionClass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,13 +16,12 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class SuccessfulTest extends TestResult {
|
||||
|
||||
public SuccessfulTest(Method testMethod, long startTime, long endTime, List<String> logMessages) {
|
||||
super(testMethod, startTime, endTime, logMessages);
|
||||
public SuccessfulTest(SmackIntegrationTestFramework.ConcreteTest concreteTest, long startTime, long endTime, List<String> logMessages) {
|
||||
super(concreteTest, startTime, endTime, logMessages);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,16 +16,15 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class TestNotPossible extends TestResult {
|
||||
|
||||
public final TestNotPossibleException testNotPossibleException;
|
||||
|
||||
public TestNotPossible(Method testMethod, long startTime, long endTime, List<String> logMessages,
|
||||
public TestNotPossible(SmackIntegrationTestFramework.ConcreteTest concreteTest, long startTime, long endTime, List<String> logMessages,
|
||||
TestNotPossibleException testNotPossibleException) {
|
||||
super(testMethod, startTime, endTime, logMessages);
|
||||
super(concreteTest, startTime, endTime, logMessages);
|
||||
this.testNotPossibleException = testNotPossibleException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,19 +16,18 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class TestResult {
|
||||
|
||||
public final Method testMethod;
|
||||
public final SmackIntegrationTestFramework.ConcreteTest concreteTest;
|
||||
public final long startTime;
|
||||
public final long endTime;
|
||||
public final long duration;
|
||||
public final List<String> logMessages;
|
||||
|
||||
public TestResult(Method testMethod, long startTime, long endTime, List<String> logMessages) {
|
||||
this.testMethod = testMethod;
|
||||
public TestResult(SmackIntegrationTestFramework.ConcreteTest concreteTest, long startTime, long endTime, List<String> logMessages) {
|
||||
this.concreteTest = concreteTest;
|
||||
assert (endTime >= startTime);
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.igniterealtime.smack.inttest;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
||||
public class XmppConnectionDescriptor<C extends AbstractXMPPConnection, CC extends ConnectionConfiguration, CCB extends ConnectionConfiguration.Builder<?, CC>> {
|
||||
|
||||
private final Class<C> connectionClass;
|
||||
private final Class<CC> connectionConfigurationClass;
|
||||
|
||||
private final Constructor<C> connectionConstructor;
|
||||
private final Method builderMethod;
|
||||
|
||||
public XmppConnectionDescriptor(Class<C> connectionClass, Class<CC> connectionConfigurationClass)
|
||||
throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
this.connectionClass = connectionClass;
|
||||
this.connectionConfigurationClass = connectionConfigurationClass;
|
||||
|
||||
this.connectionConstructor = getConstructor(connectionClass, connectionConfigurationClass);
|
||||
this.builderMethod = getBuilderMethod(connectionConfigurationClass);
|
||||
}
|
||||
|
||||
public C construct(Configuration sinttestConfiguration)
|
||||
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
return construct(sinttestConfiguration, Collections.emptyList());
|
||||
}
|
||||
|
||||
public C construct(Configuration sinttestConfiguration,
|
||||
ConnectionConfigurationBuilderApplier... customConnectionConfigurationAppliers)
|
||||
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
|
||||
InvocationTargetException {
|
||||
List<ConnectionConfigurationBuilderApplier> customConnectionConfigurationAppliersList = new ArrayList<ConnectionConfigurationBuilderApplier>(
|
||||
Arrays.asList(customConnectionConfigurationAppliers));
|
||||
return construct(sinttestConfiguration, customConnectionConfigurationAppliersList);
|
||||
}
|
||||
|
||||
public C construct(Configuration sinttestConfiguration,
|
||||
Collection<ConnectionConfigurationBuilderApplier> customConnectionConfigurationAppliers)
|
||||
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
CCB connectionConfigurationBuilder = getNewBuilder();
|
||||
for (ConnectionConfigurationBuilderApplier customConnectionConfigurationApplier : customConnectionConfigurationAppliers) {
|
||||
customConnectionConfigurationApplier.applyConfigurationTo(connectionConfigurationBuilder);
|
||||
}
|
||||
sinttestConfiguration.configurationApplier.applyConfigurationTo(connectionConfigurationBuilder);
|
||||
ConnectionConfiguration connectionConfiguration = connectionConfigurationBuilder.build();
|
||||
CC concreteConnectionConfiguration = connectionConfigurationClass.cast(connectionConfiguration);
|
||||
return connectionConstructor.newInstance(concreteConnectionConfiguration);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public CCB getNewBuilder() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
return (CCB) builderMethod.invoke(null);
|
||||
}
|
||||
|
||||
public Class<C> getConnectionClass() {
|
||||
return connectionClass;
|
||||
}
|
||||
|
||||
private static <C extends XMPPConnection> Constructor<C> getConstructor(Class<C> connectionClass,
|
||||
Class<? extends ConnectionConfiguration> connectionConfigurationClass)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
return connectionClass.getConstructor(connectionConfigurationClass);
|
||||
}
|
||||
|
||||
private static <CC extends ConnectionConfiguration> Method getBuilderMethod(Class<CC> connectionConfigurationClass)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
Method builderMethod = connectionConfigurationClass.getMethod("builder");
|
||||
if (!Modifier.isStatic(builderMethod.getModifiers())) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
Class<?> returnType = builderMethod.getReturnType();
|
||||
if (!ConnectionConfiguration.Builder.class.isAssignableFrom(returnType)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return builderMethod;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,441 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.igniterealtime.smack.inttest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.tcp.XmppNioTcpConnection;
|
||||
import org.jivesoftware.smack.util.MultiMap;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.admin.ServiceAdministrationManager;
|
||||
import org.jivesoftware.smackx.iqregister.AccountManager;
|
||||
|
||||
import org.igniterealtime.smack.inttest.Configuration.AccountRegistration;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.AccountNum;
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.jid.parts.Localpart;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
public class XmppConnectionManager<DC extends AbstractXMPPConnection> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(XmppConnectionManager.class.getName());
|
||||
|
||||
private static final Map<Class<? extends AbstractXMPPConnection>, XmppConnectionDescriptor<? extends AbstractXMPPConnection, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>>> CONNECTION_DESCRIPTORS = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
try {
|
||||
addConnectionDescriptor(XmppNioTcpConnection.class, XMPPTCPConnectionConfiguration.class);
|
||||
addConnectionDescriptor(XMPPTCPConnection.class, XMPPTCPConnectionConfiguration.class);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addConnectionDescriptor(Class<? extends AbstractXMPPConnection> connectionClass,
|
||||
Class<? extends ConnectionConfiguration> connectionConfigurationClass) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
|
||||
XmppConnectionDescriptor<? extends AbstractXMPPConnection, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor = new XmppConnectionDescriptor<>(
|
||||
connectionClass, connectionConfigurationClass);
|
||||
addConnectionDescriptor(connectionDescriptor);
|
||||
}
|
||||
|
||||
public static void addConnectionDescriptor(
|
||||
XmppConnectionDescriptor<? extends AbstractXMPPConnection, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor) {
|
||||
Class<? extends AbstractXMPPConnection> connectionClass = connectionDescriptor.getConnectionClass();
|
||||
CONNECTION_DESCRIPTORS.put(connectionClass, connectionDescriptor);
|
||||
}
|
||||
|
||||
public static void removeConnectionDescriptor(Class<? extends AbstractXMPPConnection> connectionClass) {
|
||||
CONNECTION_DESCRIPTORS.remove(connectionClass);
|
||||
}
|
||||
|
||||
private final XmppConnectionDescriptor<DC, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> defaultConnectionDescriptor;
|
||||
|
||||
private final Map<Class<? extends AbstractXMPPConnection>, XmppConnectionDescriptor<? extends AbstractXMPPConnection, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>>> connectionDescriptors = new HashMap<>(
|
||||
CONNECTION_DESCRIPTORS.size());
|
||||
|
||||
private final SmackIntegrationTestFramework<?> sinttestFramework;
|
||||
private final Configuration sinttestConfiguration;
|
||||
private final String testRunId;
|
||||
|
||||
private final DC accountRegistrationConnection;
|
||||
private final ServiceAdministrationManager adminManager;
|
||||
private final AccountManager accountManager;
|
||||
|
||||
/**
|
||||
* One of the three main connections. The type of the main connections is the default connection type.
|
||||
*/
|
||||
DC conOne, conTwo, conThree;
|
||||
|
||||
/**
|
||||
* A pool of authenticated and free to use connections.
|
||||
*/
|
||||
private final MultiMap<Class<? extends AbstractXMPPConnection>, AbstractXMPPConnection> connectionPool = new MultiMap<>();
|
||||
|
||||
/**
|
||||
* A list of all ever created connections.
|
||||
*/
|
||||
private final List<AbstractXMPPConnection> connections = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
XmppConnectionManager(SmackIntegrationTestFramework<?> sinttestFramework,
|
||||
Class<? extends DC> defaultConnectionClass)
|
||||
throws SmackException, IOException, XMPPException, InterruptedException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
this.sinttestFramework = sinttestFramework;
|
||||
this.sinttestConfiguration = sinttestFramework.config;
|
||||
this.testRunId = sinttestFramework.testRunResult.testRunId;
|
||||
|
||||
connectionDescriptors.putAll(CONNECTION_DESCRIPTORS);
|
||||
|
||||
defaultConnectionDescriptor = (XmppConnectionDescriptor<DC, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>>) connectionDescriptors.get(
|
||||
defaultConnectionClass);
|
||||
if (defaultConnectionDescriptor == null) {
|
||||
throw new IllegalArgumentException("Could not find a connection descriptor for " + defaultConnectionClass);
|
||||
}
|
||||
|
||||
switch (sinttestConfiguration.accountRegistration) {
|
||||
case serviceAdministration:
|
||||
case inBandRegistration:
|
||||
accountRegistrationConnection = defaultConnectionDescriptor.construct(sinttestConfiguration);
|
||||
accountRegistrationConnection.connect();
|
||||
accountRegistrationConnection.login(sinttestConfiguration.adminAccountUsername,
|
||||
sinttestConfiguration.adminAccountPassword);
|
||||
|
||||
if (sinttestConfiguration.accountRegistration == AccountRegistration.inBandRegistration) {
|
||||
|
||||
adminManager = null;
|
||||
accountManager = AccountManager.getInstance(accountRegistrationConnection);
|
||||
} else {
|
||||
adminManager = ServiceAdministrationManager.getInstanceFor(accountRegistrationConnection);
|
||||
accountManager = null;
|
||||
}
|
||||
break;
|
||||
case disabled:
|
||||
accountRegistrationConnection = null;
|
||||
adminManager = null;
|
||||
accountManager = null;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
SmackIntegrationTestEnvironment<DC> prepareEnvironment() throws KeyManagementException, NoSuchAlgorithmException,
|
||||
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
|
||||
SmackException, IOException, XMPPException, InterruptedException {
|
||||
prepareMainConnections();
|
||||
return new SmackIntegrationTestEnvironment<DC>(conOne, conTwo, conThree,
|
||||
sinttestFramework.testRunResult.testRunId, sinttestConfiguration, this);
|
||||
}
|
||||
|
||||
private void prepareMainConnections() throws KeyManagementException, NoSuchAlgorithmException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException, SmackException, IOException,
|
||||
XMPPException, InterruptedException {
|
||||
final int mainAccountCount = AccountNum.values().length;
|
||||
List<DC> connections = new ArrayList<>(mainAccountCount);
|
||||
for (AccountNum mainAccountNum : AccountNum.values()) {
|
||||
DC mainConnection = getConnectedMainConnectionFor(mainAccountNum);
|
||||
connections.add(mainConnection);
|
||||
}
|
||||
conOne = connections.get(0);
|
||||
conTwo = connections.get(1);
|
||||
conThree = connections.get(2);
|
||||
}
|
||||
|
||||
public Class<? extends AbstractXMPPConnection> getDefaultConnectionClass() {
|
||||
return defaultConnectionDescriptor.getConnectionClass();
|
||||
}
|
||||
|
||||
public Set<Class<? extends AbstractXMPPConnection>> getConnectionClasses() {
|
||||
return Collections.unmodifiableSet(connectionDescriptors.keySet());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <C extends AbstractXMPPConnection> XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> getConnectionDescriptorFor(
|
||||
Class<C> connectionClass) {
|
||||
return (XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>>) connectionDescriptors.get(
|
||||
connectionClass);
|
||||
}
|
||||
|
||||
void disconnectAndCleanup() throws InterruptedException {
|
||||
int successfullyDeletedAccountsCount = 0;
|
||||
for (AbstractXMPPConnection connection : connections) {
|
||||
if (sinttestConfiguration.accountRegistration == AccountRegistration.inBandRegistration) {
|
||||
// Note that we use the account manager from the to-be-deleted connection.
|
||||
AccountManager accountManager = AccountManager.getInstance(connection);
|
||||
try {
|
||||
accountManager.deleteAccount();
|
||||
successfullyDeletedAccountsCount++;
|
||||
} catch (NoResponseException | XMPPErrorException | NotConnectedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not delete dynamically registered account", e);
|
||||
}
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
|
||||
if (sinttestConfiguration.accountRegistration == AccountRegistration.serviceAdministration) {
|
||||
String username = connection.getConfiguration().getUsername().toString();
|
||||
Localpart usernameAsLocalpart;
|
||||
try {
|
||||
usernameAsLocalpart = Localpart.from(username);
|
||||
} catch (XmppStringprepException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
EntityBareJid connectionAddress = JidCreate.entityBareFrom(usernameAsLocalpart, sinttestConfiguration.service);
|
||||
|
||||
try {
|
||||
adminManager.deleteUser(connectionAddress);
|
||||
successfullyDeletedAccountsCount++;
|
||||
} catch (NoResponseException | XMPPErrorException | NotConnectedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not delete dynamically registered account", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sinttestConfiguration.isAccountRegistrationPossible()) {
|
||||
int unsuccessfullyDeletedAccountsCount = connections.size() - successfullyDeletedAccountsCount;
|
||||
if (unsuccessfullyDeletedAccountsCount == 0) {
|
||||
LOGGER.info("Successsfully deleted all created accounts ✔");
|
||||
} else {
|
||||
LOGGER.warning("Could not delete all created accounts, " + unsuccessfullyDeletedAccountsCount + " remainaing");
|
||||
}
|
||||
}
|
||||
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
|
||||
private static final String USERNAME_PREFIX = "smack-inttest";
|
||||
|
||||
private DC getConnectedMainConnectionFor(AccountNum accountNum) throws SmackException, IOException, XMPPException,
|
||||
InterruptedException, KeyManagementException, NoSuchAlgorithmException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
String middlefix;
|
||||
String accountUsername;
|
||||
String accountPassword;
|
||||
switch (accountNum) {
|
||||
case One:
|
||||
accountUsername = sinttestConfiguration.accountOneUsername;
|
||||
accountPassword = sinttestConfiguration.accountOnePassword;
|
||||
middlefix = "one";
|
||||
break;
|
||||
case Two:
|
||||
accountUsername = sinttestConfiguration.accountTwoUsername;
|
||||
accountPassword = sinttestConfiguration.accountTwoPassword;
|
||||
middlefix = "two";
|
||||
break;
|
||||
case Three:
|
||||
accountUsername = sinttestConfiguration.accountThreeUsername;
|
||||
accountPassword = sinttestConfiguration.accountThreePassword;
|
||||
middlefix = "three";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Note that it is perfectly fine for account(Username|Password) to be 'null' at this point.
|
||||
final String finalAccountUsername = StringUtils.isNullOrEmpty(accountUsername) ? USERNAME_PREFIX + '-' + middlefix + '-' + testRunId : accountUsername;
|
||||
final String finalAccountPassword = StringUtils.isNullOrEmpty(accountPassword) ? StringUtils.insecureRandomString(16) : accountPassword;
|
||||
|
||||
if (sinttestConfiguration.isAccountRegistrationPossible()) {
|
||||
registerAccount(finalAccountUsername, finalAccountPassword);
|
||||
}
|
||||
|
||||
DC mainConnection = defaultConnectionDescriptor.construct(sinttestConfiguration, (builder) -> {
|
||||
try {
|
||||
builder.setUsernameAndPassword(finalAccountUsername, finalAccountPassword)
|
||||
.setResource(middlefix + '-' + testRunId);
|
||||
} catch (XmppStringprepException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
});
|
||||
|
||||
connections.add(mainConnection);
|
||||
|
||||
mainConnection.connect();
|
||||
mainConnection.login();
|
||||
|
||||
return mainConnection;
|
||||
}
|
||||
|
||||
private void registerAccount(String username, String password) throws NoResponseException, XMPPErrorException,
|
||||
NotConnectedException, InterruptedException, XmppStringprepException {
|
||||
if (accountRegistrationConnection == null) {
|
||||
throw new IllegalStateException("Account registration not configured");
|
||||
}
|
||||
|
||||
switch (sinttestConfiguration.accountRegistration) {
|
||||
case serviceAdministration:
|
||||
EntityBareJid userJid = JidCreate.entityBareFrom(Localpart.from(username),
|
||||
accountRegistrationConnection.getXMPPServiceDomain());
|
||||
adminManager.addUser(userJid, password);
|
||||
break;
|
||||
case inBandRegistration:
|
||||
if (!accountManager.supportsAccountCreation()) {
|
||||
throw new UnsupportedOperationException("Account creation/registation is not supported");
|
||||
}
|
||||
Set<String> requiredAttributes = accountManager.getAccountAttributes();
|
||||
if (requiredAttributes.size() > 4) {
|
||||
throw new IllegalStateException("Unkown required attributes");
|
||||
}
|
||||
Map<String, String> additionalAttributes = new HashMap<>();
|
||||
additionalAttributes.put("name", "Smack Integration Test");
|
||||
additionalAttributes.put("email", "flow@igniterealtime.org");
|
||||
Localpart usernameLocalpart = Localpart.from(username);
|
||||
accountManager.createAccount(usernameLocalpart, password, additionalAttributes);
|
||||
break;
|
||||
case disabled:
|
||||
throw new IllegalStateException("Account creation no possible");
|
||||
}
|
||||
}
|
||||
|
||||
<C extends AbstractXMPPConnection> List<C> constructConnectedConnections(Class<C> connectionClass, int count)
|
||||
throws InterruptedException, SmackException, IOException, XMPPException {
|
||||
List<C> connections = new ArrayList<>(count);
|
||||
|
||||
synchronized (connectionPool) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<C> pooledConnections = (List<C>) connectionPool.getAll(connectionClass);
|
||||
while (count > 0 && !pooledConnections.isEmpty()) {
|
||||
C connection = pooledConnections.remove(pooledConnections.size() - 1);
|
||||
connections.add(connection);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor = (XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>>) connectionDescriptors
|
||||
.get(connectionClass);
|
||||
for (int i = 0; i < count; i++) {
|
||||
C connection = constructConnectedConnection(connectionDescriptor);
|
||||
connections.add(connection);
|
||||
}
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
private <C extends AbstractXMPPConnection> C constructConnectedConnection(
|
||||
XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor)
|
||||
throws InterruptedException, SmackException, IOException, XMPPException {
|
||||
C connection = constructConnection(connectionDescriptor, null);
|
||||
|
||||
connection.connect();
|
||||
connection.login();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
DC constructConnection()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return constructConnection(defaultConnectionDescriptor);
|
||||
}
|
||||
|
||||
<C extends AbstractXMPPConnection> C constructConnection(
|
||||
XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return constructConnection(connectionDescriptor, null);
|
||||
}
|
||||
|
||||
private <C extends AbstractXMPPConnection> C constructConnection(
|
||||
XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor,
|
||||
Collection<ConnectionConfigurationBuilderApplier> customConnectionConfigurationAppliers)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
String username = "sinttest-" + testRunId + '-' + (connections.size() + 1);
|
||||
String password = StringUtils.randomString(24);
|
||||
|
||||
return constructConnection(username, password, connectionDescriptor, customConnectionConfigurationAppliers);
|
||||
}
|
||||
|
||||
private <C extends AbstractXMPPConnection> C constructConnection(final String username, final String password,
|
||||
XmppConnectionDescriptor<C, ? extends ConnectionConfiguration, ? extends ConnectionConfiguration.Builder<?, ?>> connectionDescriptor,
|
||||
Collection<ConnectionConfigurationBuilderApplier> customConnectionConfigurationAppliers)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
try {
|
||||
registerAccount(username, password);
|
||||
} catch (XmppStringprepException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
|
||||
ConnectionConfigurationBuilderApplier usernameAndPasswordApplier = (configurationBuilder) -> {
|
||||
configurationBuilder.setUsernameAndPassword(username, password);
|
||||
};
|
||||
|
||||
if (customConnectionConfigurationAppliers == null) {
|
||||
customConnectionConfigurationAppliers = Collections.singleton(usernameAndPasswordApplier);
|
||||
} else {
|
||||
customConnectionConfigurationAppliers.add(usernameAndPasswordApplier);
|
||||
}
|
||||
|
||||
C connection;
|
||||
try {
|
||||
connection = connectionDescriptor.construct(sinttestConfiguration, customConnectionConfigurationAppliers);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
connections.add(connection);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
void recycle(Collection<? extends AbstractXMPPConnection> connections) {
|
||||
for (AbstractXMPPConnection connection : connections) {
|
||||
recycle(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void recycle(AbstractXMPPConnection connection) {
|
||||
Class<? extends AbstractXMPPConnection> connectionClass = connection.getClass();
|
||||
if (!connectionDescriptors.containsKey(connectionClass)) {
|
||||
throw new IllegalStateException("Attempt to recycle unknown connection of class '" + connectionClass + "'");
|
||||
}
|
||||
|
||||
if (connection.isAuthenticated()) {
|
||||
synchronized (connectionPool) {
|
||||
connectionPool.put(connectionClass, connection);
|
||||
}
|
||||
}
|
||||
// Note that we do not delete the account of the unauthenticated connection here, as it is done at the end of
|
||||
// the test run together with all other dynamically created accounts.
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -48,7 +48,7 @@ public class ChatTest extends AbstractSmackIntegrationTest {
|
|||
private boolean invoked;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ChatTest(SmackIntegrationTestEnvironment environment) {
|
||||
public ChatTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
chatManagerOne = org.jivesoftware.smack.chat.ChatManager.getInstanceFor(conOne);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,8 +25,6 @@ import java.security.NoSuchAlgorithmException;
|
|||
|
||||
import org.jivesoftware.smack.sasl.SASLError;
|
||||
import org.jivesoftware.smack.sasl.SASLErrorException;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest;
|
||||
|
@ -35,7 +33,7 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
|||
|
||||
public class LoginIntegrationTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
public LoginIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public LoginIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
@ -54,14 +52,13 @@ public class LoginIntegrationTest extends AbstractSmackLowLevelIntegrationTest {
|
|||
public void testInvalidLogin() throws SmackException, IOException, XMPPException,
|
||||
InterruptedException, KeyManagementException, NoSuchAlgorithmException {
|
||||
final String nonExistentUserString = StringUtils.insecureRandomString(24);
|
||||
XMPPTCPConnectionConfiguration conf = getConnectionConfiguration().setUsernameAndPassword(
|
||||
nonExistentUserString, "invalidPassword").build();
|
||||
final String invalidPassword = "invalidPassword";
|
||||
|
||||
XMPPTCPConnection connection = new XMPPTCPConnection(conf);
|
||||
AbstractXMPPConnection connection = getUnconnectedConnection();
|
||||
connection.connect();
|
||||
|
||||
try {
|
||||
connection.login();
|
||||
connection.login(nonExistentUserString, invalidPassword);
|
||||
fail("Exception expected");
|
||||
}
|
||||
catch (SASLErrorException e) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -28,23 +28,20 @@ import org.jivesoftware.smack.filter.MessageWithBodiesFilter;
|
|||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackSpecificLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||
import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
||||
|
||||
public class StreamManagementTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrationTest<XMPPTCPConnection> {
|
||||
|
||||
public StreamManagementTest(SmackIntegrationTestEnvironment environment) throws Exception {
|
||||
super(environment);
|
||||
performCheck(new ConnectionCallback() {
|
||||
@Override
|
||||
public void connectionCallback(XMPPTCPConnection connection) throws Exception {
|
||||
if (!connection.isSmAvailable()) {
|
||||
throw new TestNotPossibleException("XEP-198: Stream Mangement not supported by service");
|
||||
}
|
||||
}
|
||||
});
|
||||
public StreamManagementTest(SmackIntegrationTestEnvironment<?> environment) throws Exception {
|
||||
super(environment, XMPPTCPConnection.class);
|
||||
XMPPTCPConnection connection = getSpecificUnconnectedConnection();
|
||||
connection.connect().login();
|
||||
if (!connection.isSmAvailable()) {
|
||||
throw new TestNotPossibleException("XEP-198: Stream Mangement not supported by service");
|
||||
}
|
||||
}
|
||||
|
||||
@SmackIntegrationTest
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,25 +20,23 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||
|
||||
public class WaitForClosingStreamElementTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
public WaitForClosingStreamElementTest(SmackIntegrationTestEnvironment environment) {
|
||||
public WaitForClosingStreamElementTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@SmackIntegrationTest
|
||||
public void waitForClosingStreamElementTest(XMPPTCPConnection connection)
|
||||
public void waitForClosingStreamElementTest(AbstractXMPPConnection connection)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
connection.disconnect();
|
||||
|
||||
Field closingStreamReceivedField = connection.getClass().getDeclaredField("closingStreamReceived");
|
||||
Field closingStreamReceivedField = AbstractXMPPConnection.class.getDeclaredField("closingStreamReceived");
|
||||
closingStreamReceivedField.setAccessible(true);
|
||||
SynchronizationPoint<?> closingStreamReceived = (SynchronizationPoint<?>) closingStreamReceivedField.get(connection);
|
||||
Exception failureException = closingStreamReceived.getFailureException();
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.smack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XmppNioTcpConnection;
|
||||
|
||||
import org.igniterealtime.smack.XmppConnectionStressTest;
|
||||
import org.igniterealtime.smack.XmppConnectionStressTest.StressTestFailedException.ErrorsWhileSendingOrReceivingException;
|
||||
import org.igniterealtime.smack.XmppConnectionStressTest.StressTestFailedException.NotAllMessagesReceivedException;
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||
|
||||
public class XmppConnectionIntegrationTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
public XmppConnectionIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@SmackIntegrationTest(connectionCount = 4)
|
||||
public void allToAllMessageSendTest(List<AbstractXMPPConnection> connections)
|
||||
throws InterruptedException, NotAllMessagesReceivedException, ErrorsWhileSendingOrReceivingException {
|
||||
final long seed = 42;
|
||||
final int messagesPerConnection = 3; // 100
|
||||
final int maxPayloadChunkSize = 16; // 512
|
||||
final int maxPayloadChunks = 4; // 32
|
||||
final boolean intermixMessages = false; // true
|
||||
|
||||
XmppConnectionStressTest.Configuration stressTestConfiguration = new XmppConnectionStressTest.Configuration(
|
||||
seed, messagesPerConnection, maxPayloadChunkSize, maxPayloadChunks, intermixMessages);
|
||||
|
||||
XmppConnectionStressTest stressTest = new XmppConnectionStressTest(stressTestConfiguration);
|
||||
|
||||
stressTest.run(connections, timeout);
|
||||
|
||||
final Level connectionStatsLogLevel = Level.FINE;
|
||||
if (LOGGER.isLoggable(connectionStatsLogLevel)) {
|
||||
if (connections.get(0) instanceof XmppNioTcpConnection) {
|
||||
for (XMPPConnection connection : connections) {
|
||||
XmppNioTcpConnection xmppNioTcpConnection = (XmppNioTcpConnection) connection;
|
||||
XmppNioTcpConnection.Stats stats = xmppNioTcpConnection.getStats();
|
||||
LOGGER.log(connectionStatsLogLevel,
|
||||
"Connections stats for " + xmppNioTcpConnection + ":\n{}",
|
||||
stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ public abstract class AbstractChatIntegrationTest extends AbstractSmackIntegrati
|
|||
protected final ChatManager chatManagerTwo;
|
||||
protected final ChatManager chatManagerThree;
|
||||
|
||||
protected AbstractChatIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
protected AbstractChatIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
chatManagerOne = ChatManager.getInstanceFor(conOne);
|
||||
chatManagerTwo = ChatManager.getInstanceFor(conTwo);
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.jxmpp.jid.EntityBareJid;
|
|||
|
||||
public class IncomingMessageListenerIntegrationTest extends AbstractChatIntegrationTest {
|
||||
|
||||
public IncomingMessageListenerIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public IncomingMessageListenerIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.jxmpp.jid.EntityBareJid;
|
|||
|
||||
public class OutgoingMessageListenerIntegrationTest extends AbstractChatIntegrationTest {
|
||||
|
||||
public OutgoingMessageListenerIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public OutgoingMessageListenerIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016-2018 Florian Schmaus
|
||||
* Copyright 2016-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,8 +18,8 @@ package org.jivesoftware.smack.roster;
|
|||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
|
@ -30,12 +30,13 @@ import org.jxmpp.jid.FullJid;
|
|||
|
||||
public class LowLevelRosterIntegrationTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
public LowLevelRosterIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public LowLevelRosterIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@SmackIntegrationTest
|
||||
public void testPresenceEventListenersOffline(final XMPPTCPConnection conOne, final XMPPTCPConnection conTwo) throws TimeoutException, Exception {
|
||||
public void testPresenceEventListenersOffline(final AbstractXMPPConnection conOne,
|
||||
final AbstractXMPPConnection conTwo) throws TimeoutException, Exception {
|
||||
IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo);
|
||||
|
||||
final Roster rosterOne = Roster.getInstanceFor(conOne);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -38,7 +38,7 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
private final Roster rosterOne;
|
||||
private final Roster rosterTwo;
|
||||
|
||||
public RosterIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public RosterIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
rosterOne = Roster.getInstanceFor(conOne);
|
||||
rosterTwo = Roster.getInstanceFor(conTwo);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.smack.tcp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
|
||||
import org.igniterealtime.smack.inttest.AbstractSmackSpecificLowLevelIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||
|
||||
public class XmppNioTcpConnectionLowLevelIntegrationTest extends AbstractSmackSpecificLowLevelIntegrationTest<XmppNioTcpConnection> {
|
||||
|
||||
public XmppNioTcpConnectionLowLevelIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment, XmppNioTcpConnection.class);
|
||||
}
|
||||
|
||||
@SmackIntegrationTest
|
||||
public void testDisconnectAfterConnect() throws KeyManagementException, NoSuchAlgorithmException, SmackException,
|
||||
IOException, XMPPException, InterruptedException {
|
||||
XmppNioTcpConnection connection = getSpecificUnconnectedConnection();
|
||||
|
||||
connection.connect();
|
||||
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TCP-IP related classes for Smack.
|
||||
*/
|
||||
package org.jivesoftware.smack.tcp;
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013-2018 Florian Schmaus
|
||||
* Copyright 2013-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -57,7 +57,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest {
|
|||
private final ServiceDiscoveryManager sdmOne;
|
||||
private final ServiceDiscoveryManager sdmTwo;
|
||||
|
||||
public EntityCapsTest(SmackIntegrationTestEnvironment environment) {
|
||||
public EntityCapsTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
ecmTwo = EntityCapsManager.getInstanceFor(environment.conTwo);
|
||||
sdmOne = ServiceDiscoveryManager.getInstanceFor(environment.conOne);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
};
|
||||
|
||||
|
||||
public ChatStateIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public ChatStateIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -39,7 +39,7 @@ public class FileTransferIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
private final FileTransferManager ftManagerOne;
|
||||
private final FileTransferManager ftManagerTwo;
|
||||
|
||||
public FileTransferIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public FileTransferIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
ftManagerOne = FileTransferManager.getInstanceFor(conOne);
|
||||
ftManagerTwo = FileTransferManager.getInstanceFor(conTwo);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Florian Schmaus
|
||||
* Copyright 2017-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -43,7 +43,7 @@ public class HttpFileUploadIntegrationTest extends AbstractSmackIntegrationTest
|
|||
|
||||
private final HttpFileUploadManager hfumOne;
|
||||
|
||||
public HttpFileUploadIntegrationTest(SmackIntegrationTestEnvironment environment) throws XMPPErrorException,
|
||||
public HttpFileUploadIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws XMPPErrorException,
|
||||
NotConnectedException, NoResponseException, InterruptedException, TestNotPossibleException {
|
||||
super(environment);
|
||||
hfumOne = HttpFileUploadManager.getInstanceFor(conOne);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016-2018 Florian Schmaus
|
||||
* Copyright 2016-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -43,7 +43,7 @@ public class IoTControlIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
|
||||
private final IoTControlManager IoTControlManagerTwo;
|
||||
|
||||
public IoTControlIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public IoTControlIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
IoTControlManagerOne = IoTControlManager.getInstanceFor(conOne);
|
||||
IoTControlManagerTwo = IoTControlManager.getInstanceFor(conTwo);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016-2018 Florian Schmaus
|
||||
* Copyright 2016-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -45,7 +45,7 @@ public class IoTDataIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
|
||||
private final IoTDataManager iotDataManagerTwo;
|
||||
|
||||
public IoTDataIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public IoTDataIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
iotDataManagerOne = IoTDataManager.getInstanceFor(conOne);
|
||||
iotDataManagerTwo = IoTDataManager.getInstanceFor(conTwo);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Florian Schmaus
|
||||
* Copyright 2016-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -41,7 +41,7 @@ public class IoTDiscoveryIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
private final IoTDiscoveryManager discoveryManagerOne;
|
||||
private final IoTDiscoveryManager discoveryManagerTwo;
|
||||
|
||||
public IoTDiscoveryIntegrationTest(SmackIntegrationTestEnvironment environment) throws NoResponseException,
|
||||
public IoTDiscoveryIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws NoResponseException,
|
||||
XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException {
|
||||
super(environment);
|
||||
discoveryManagerOne = IoTDiscoveryManager.getInstanceFor(conOne);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -31,7 +31,7 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
|||
|
||||
public class VersionIntegrationTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public VersionIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public VersionIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2016 Fernando Ramirez, 2018 Florian Schmaus
|
||||
* Copyright 2016 Fernando Ramirez, 2018-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -47,7 +47,7 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
|
||||
private final MamManager mamManagerConTwo;
|
||||
|
||||
public MamIntegrationTest(SmackIntegrationTestEnvironment environment) throws NoResponseException,
|
||||
public MamIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws NoResponseException,
|
||||
XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException, NotLoggedInException {
|
||||
super(environment);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public class MoodIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
private final MoodManager mm1;
|
||||
private final MoodManager mm2;
|
||||
|
||||
public MoodIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public MoodIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
mm1 = MoodManager.getInstanceFor(conOne);
|
||||
mm2 = MoodManager.getInstanceFor(conTwo);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -53,7 +53,7 @@ public class MultiUserChatIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
private final MultiUserChatManager mucManagerTwo;
|
||||
private final DomainBareJid mucService;
|
||||
|
||||
public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException,
|
||||
InterruptedException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,9 +20,9 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.bookmarks.BookmarkManager;
|
||||
|
@ -40,20 +40,20 @@ import org.jxmpp.jid.parts.Resourcepart;
|
|||
|
||||
public class MultiUserChatLowLevelIntegrationTest extends AbstractSmackLowLevelIntegrationTest {
|
||||
|
||||
public MultiUserChatLowLevelIntegrationTest(SmackIntegrationTestEnvironment environment) throws Exception {
|
||||
public MultiUserChatLowLevelIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws Exception {
|
||||
super(environment);
|
||||
performCheck(new ConnectionCallback() {
|
||||
@Override
|
||||
public void connectionCallback(XMPPTCPConnection connection) throws Exception {
|
||||
if (MultiUserChatManager.getInstanceFor(connection).getMucServiceDomains().isEmpty()) {
|
||||
throw new TestNotPossibleException("MUC component not offered by service");
|
||||
}
|
||||
AbstractXMPPConnection connection = getConnectedConnection();
|
||||
try {
|
||||
if (MultiUserChatManager.getInstanceFor(connection).getMucServiceDomains().isEmpty()) {
|
||||
throw new TestNotPossibleException("MUC component not offered by service");
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
recycle(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@SmackIntegrationTest
|
||||
public void testMucBookmarksAutojoin(XMPPTCPConnection connection) throws InterruptedException,
|
||||
public void testMucBookmarksAutojoin(AbstractXMPPConnection connection) throws InterruptedException,
|
||||
TestNotPossibleException, XMPPException, SmackException, IOException {
|
||||
final BookmarkManager bookmarkManager = BookmarkManager.getBookmarkManager(connection);
|
||||
if (!bookmarkManager.isSupported()) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Florian Schmaus, Paul Schaub
|
||||
* Copyright 2017-2018 Florian Schmaus, Paul Schaub
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -28,7 +28,7 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
|||
*/
|
||||
public abstract class AbstractOmemoIntegrationTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public AbstractOmemoIntegrationTest(SmackIntegrationTestEnvironment environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, TestNotPossibleException {
|
||||
public AbstractOmemoIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
||||
// Test for server support
|
||||
|
|
|
@ -39,7 +39,7 @@ public abstract class AbstractTwoUsersOmemoIntegrationTest extends AbstractOmemo
|
|||
|
||||
protected OmemoManager alice, bob;
|
||||
|
||||
public AbstractTwoUsersOmemoIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public AbstractTwoUsersOmemoIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
|||
*/
|
||||
public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest {
|
||||
|
||||
public MessageEncryptionIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public MessageEncryptionIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
|||
* Then Bob fetches his Mam archive and decrypts the result.
|
||||
*/
|
||||
public class OmemoMamDecryptionTest extends AbstractTwoUsersOmemoIntegrationTest {
|
||||
public OmemoMamDecryptionTest(SmackIntegrationTestEnvironment environment)
|
||||
public OmemoMamDecryptionTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
|||
|
||||
public class ReadOnlyDeviceIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest {
|
||||
|
||||
public ReadOnlyDeviceIntegrationTest(SmackIntegrationTestEnvironment environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, TestNotPossibleException {
|
||||
public ReadOnlyDeviceIntegrationTest(SmackIntegrationTestEnvironment<?> environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
|||
|
||||
public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest {
|
||||
|
||||
public SessionRenegotiationIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public SessionRenegotiationIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||
SmackException.NoResponseException, TestNotPossibleException {
|
||||
super(environment);
|
||||
|
|
|
@ -41,7 +41,7 @@ public abstract class AbstractOpenPgpIntegrationTest extends AbstractSmackIntegr
|
|||
protected final PepManager bobPepManager;
|
||||
protected final PepManager chloePepManager;
|
||||
|
||||
protected AbstractOpenPgpIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
protected AbstractOpenPgpIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, TestNotPossibleException, SmackException.NotConnectedException,
|
||||
InterruptedException, SmackException.NoResponseException {
|
||||
super(environment);
|
||||
|
|
|
@ -97,7 +97,7 @@ public class OXSecretKeyBackupIntegrationTest extends AbstractOpenPgpIntegration
|
|||
* @throws InterruptedException
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
public OXSecretKeyBackupIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public OXSecretKeyBackupIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, TestNotPossibleException, SmackException.NotConnectedException,
|
||||
InterruptedException, SmackException.NoResponseException {
|
||||
super(environment);
|
||||
|
|
|
@ -87,7 +87,7 @@ public class OXInstantMessagingIntegrationTest extends AbstractOpenPgpIntegratio
|
|||
* @throws TestNotPossibleException if the test is not possible due to lacking server support for PEP.
|
||||
* @throws SmackException.NoResponseException
|
||||
*/
|
||||
public OXInstantMessagingIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public OXInstantMessagingIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException,
|
||||
TestNotPossibleException, SmackException.NoResponseException {
|
||||
super(environment);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2017 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -39,7 +39,7 @@ import org.jxmpp.jid.Jid;
|
|||
|
||||
public class PingIntegrationTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public PingIntegrationTest(SmackIntegrationTestEnvironment environment) {
|
||||
public PingIntegrationTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2018 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -34,7 +34,7 @@ public class PubSubIntegrationTest extends AbstractSmackIntegrationTest {
|
|||
|
||||
private final PubSubManager pubSubManagerOne;
|
||||
|
||||
public PubSubIntegrationTest(SmackIntegrationTestEnvironment environment)
|
||||
public PubSubIntegrationTest(SmackIntegrationTestEnvironment<?> environment)
|
||||
throws TestNotPossibleException, NoResponseException, XMPPErrorException,
|
||||
NotConnectedException, InterruptedException {
|
||||
super(environment);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2004 Jive Software, 2017 Florian Schmaus.
|
||||
* Copyright 2004 Jive Software, 2017-2019 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -39,7 +39,7 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
|||
*/
|
||||
public class FormTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public FormTest(SmackIntegrationTestEnvironment environment) {
|
||||
public FormTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,21 +16,39 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class DummySmackIntegrationTestFramework extends SmackIntegrationTestFramework {
|
||||
import org.jivesoftware.smack.DummyConnection;
|
||||
import org.jivesoftware.smack.DummyConnection.DummyConnectionConfiguration;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
|
||||
public DummySmackIntegrationTestFramework(Configuration configuration) {
|
||||
super(configuration);
|
||||
public class DummySmackIntegrationTestFramework extends SmackIntegrationTestFramework<DummyConnection> {
|
||||
|
||||
static {
|
||||
try {
|
||||
XmppConnectionManager.addConnectionDescriptor(DummyConnection.class, DummyConnectionConfiguration.class);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public DummySmackIntegrationTestFramework(Configuration configuration) throws KeyManagementException,
|
||||
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
|
||||
NoSuchAlgorithmException, SmackException, IOException, XMPPException, InterruptedException {
|
||||
super(configuration, DummyConnection.class);
|
||||
testRunResult = new TestRunResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmackIntegrationTestEnvironment prepareEnvironment() {
|
||||
return new SmackIntegrationTestEnvironment(null, null, null, testRunResult.getTestRunId(), config);
|
||||
protected SmackIntegrationTestEnvironment<DummyConnection> prepareEnvironment() {
|
||||
DummyConnection dummyConnection = new DummyConnection();
|
||||
connectionManager.conOne = connectionManager.conTwo = connectionManager.conThree = dummyConnection;
|
||||
return new SmackIntegrationTestEnvironment<DummyConnection>(dummyConnection, dummyConnection, dummyConnection,
|
||||
testRunResult.getTestRunId(), config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disconnectAndMaybeDelete(XMPPTCPConnection connection) {
|
||||
// This method is a no-op in DummySmackIntegrationTestFramework
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2019 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.igniterealtime.smack.inttest;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SmackIntegrationTestFrameWorkTest {
|
||||
|
||||
private static class ValidLowLevelList {
|
||||
@SuppressWarnings("unused")
|
||||
public void test(List<AbstractXMPPConnection> connections) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvalidLowLevelList {
|
||||
@SuppressWarnings("unused")
|
||||
public void test(List<AbstractXMPPConnection> connections, boolean invalid) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ValidLowLevelVarargs {
|
||||
@SuppressWarnings("unused")
|
||||
public void test(AbstractXMPPConnection connectionOne, AbstractXMPPConnection connectionTwo,
|
||||
AbstractXMPPConnection connectionThree) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvalidLowLevelVarargs {
|
||||
@SuppressWarnings("unused")
|
||||
public void test(AbstractXMPPConnection connectionOne, Integer invalid, AbstractXMPPConnection connectionTwo,
|
||||
AbstractXMPPConnection connectionThree) {
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getTestMethod(Class<?> testClass) {
|
||||
Method[] methods = testClass.getDeclaredMethods();
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals("test")) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("No test method found in " + testClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidLowLevelList() {
|
||||
Method testMethod = getTestMethod(ValidLowLevelList.class);
|
||||
assertTrue(SmackIntegrationTestFramework.testMethodParametersIsListOfConnections(testMethod,
|
||||
AbstractXMPPConnection.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidLowLevelList() {
|
||||
Method testMethod = getTestMethod(InvalidLowLevelList.class);
|
||||
assertFalse(SmackIntegrationTestFramework.testMethodParametersIsListOfConnections(testMethod,
|
||||
AbstractXMPPConnection.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidLowLevelVarargs() {
|
||||
Method testMethod = getTestMethod(ValidLowLevelVarargs.class);
|
||||
assertTrue(SmackIntegrationTestFramework.testMethodParametersVarargsConnections(testMethod,
|
||||
AbstractXMPPConnection.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidLowLevelVargs() {
|
||||
Method testMethod = getTestMethod(InvalidLowLevelVarargs.class);
|
||||
assertFalse(SmackIntegrationTestFramework.testMethodParametersVarargsConnections(testMethod,
|
||||
AbstractXMPPConnection.class));
|
||||
}
|
||||
}
|
|
@ -16,9 +16,14 @@
|
|||
*/
|
||||
package org.igniterealtime.smack.inttest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
|
||||
import org.jxmpp.jid.JidTestUtil;
|
||||
|
||||
public class SmackIntegrationTestUnitTestUtil {
|
||||
|
@ -32,7 +37,12 @@ public class SmackIntegrationTestUnitTestUtil {
|
|||
.setUsernamesAndPassword("dummy1", "dummy1pass", "dummy2", "dummy2pass", "dummy3", "dummy3pass")
|
||||
.addEnabledTest(unitTest).build();
|
||||
// @formatter:on
|
||||
return new DummySmackIntegrationTestFramework(configuration);
|
||||
try {
|
||||
return new DummySmackIntegrationTestFramework(configuration);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
|
||||
| SmackException | IOException | XMPPException | InterruptedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2018-2019 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.igniterealtime.smack.inttest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jivesoftware.smack.tcp.XmppNioTcpConnection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
public class SmackIntegrationTestXmppConnectionManagerTest {
|
||||
|
||||
@Test
|
||||
public void simpleXmppConnectionDescriptorTest() throws ClassNotFoundException, NoSuchMethodException,
|
||||
SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
|
||||
KeyManagementException, NoSuchAlgorithmException, XmppStringprepException, InstantiationException {
|
||||
XmppConnectionDescriptor<XmppNioTcpConnection, XMPPTCPConnectionConfiguration, XMPPTCPConnectionConfiguration.Builder> descriptor
|
||||
= new XmppConnectionDescriptor<>(XmppNioTcpConnection.class, XMPPTCPConnectionConfiguration.class);
|
||||
|
||||
Configuration sinttestConfiguration = Configuration.builder().setService("example.org").build();
|
||||
XmppNioTcpConnection connection = descriptor.construct(sinttestConfiguration);
|
||||
|
||||
assertEquals("example.org", connection.getXMPPServiceDomain().toString());
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus
|
||||
* Copyright 2015-2019 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
@ -37,6 +38,7 @@ import org.igniterealtime.smack.inttest.DummySmackIntegrationTestFramework;
|
|||
import org.igniterealtime.smack.inttest.FailedTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestFramework;
|
||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.TestRunResult;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -52,9 +54,19 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
private static boolean beforeClassInvoked;
|
||||
private static boolean afterClassInvoked;
|
||||
|
||||
@BeforeClass
|
||||
public static void prepareSinttestUnitTest() {
|
||||
SmackIntegrationTestFramework.SINTTEST_UNIT_TEST = true;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void disallowSinntestUnitTest() {
|
||||
SmackIntegrationTestFramework.SINTTEST_UNIT_TEST = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsRuntimeExceptionsTest() throws KeyManagementException, NoSuchAlgorithmException, SmackException,
|
||||
IOException, XMPPException, InterruptedException {
|
||||
IOException, XMPPException, InterruptedException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
expectedException.expect(RuntimeException.class);
|
||||
expectedException.expectMessage(ThrowsRuntimeExceptionDummyTest.RUNTIME_EXCEPTION_MESSAGE);
|
||||
DummySmackIntegrationTestFramework sinttest = getFrameworkForUnitTest(ThrowsRuntimeExceptionDummyTest.class);
|
||||
|
@ -63,7 +75,7 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
|
||||
public static class ThrowsRuntimeExceptionDummyTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public ThrowsRuntimeExceptionDummyTest(SmackIntegrationTestEnvironment environment) {
|
||||
public ThrowsRuntimeExceptionDummyTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
@ -77,7 +89,8 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
|
||||
@Test
|
||||
public void logsNonFatalExceptionTest() throws KeyManagementException, NoSuchAlgorithmException, SmackException,
|
||||
IOException, XMPPException, InterruptedException {
|
||||
IOException, XMPPException, InterruptedException, InstantiationException, IllegalAccessException,
|
||||
IllegalArgumentException, InvocationTargetException {
|
||||
DummySmackIntegrationTestFramework sinttest = getFrameworkForUnitTest(ThrowsNonFatalExceptionDummyTest.class);
|
||||
TestRunResult testRunResult = sinttest.run();
|
||||
List<FailedTest> failedTests = testRunResult.getFailedTests();
|
||||
|
@ -93,7 +106,7 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
|
||||
public static final String DESCRIPTIVE_TEXT = "I'm not fatal";
|
||||
|
||||
public ThrowsNonFatalExceptionDummyTest(SmackIntegrationTestEnvironment environment) {
|
||||
public ThrowsNonFatalExceptionDummyTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
@ -107,7 +120,8 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
|
||||
@Test
|
||||
public void testInvoking() throws KeyManagementException, NoSuchAlgorithmException, SmackException, IOException,
|
||||
XMPPException, InterruptedException {
|
||||
XMPPException, InterruptedException, InstantiationException, IllegalAccessException,
|
||||
IllegalArgumentException, InvocationTargetException {
|
||||
beforeClassInvoked = false;
|
||||
afterClassInvoked = false;
|
||||
|
||||
|
@ -120,7 +134,7 @@ public class SmackIntegrationTestFrameworkUnitTest {
|
|||
|
||||
public static class BeforeAfterClassTest extends AbstractSmackIntegrationTest {
|
||||
|
||||
public BeforeAfterClassTest(SmackIntegrationTestEnvironment environment) {
|
||||
public BeforeAfterClassTest(SmackIntegrationTestEnvironment<?> environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue