/***********************************************************************************
*
* Copyright (c) 2015 Kamil Baczkowicz
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*
* Kamil Baczkowicz - initial API and implementation and/or initial documentation
*
*/
package pl.baczkowicz.mqttspy.connectivity;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.junit.Test;
import pl.baczkowicz.mqttspy.common.generated.MqttConnectionDetails;
import pl.baczkowicz.mqttspy.common.generated.ProtocolVersionEnum;
import pl.baczkowicz.mqttspy.common.generated.SecureSocketSettings;
import pl.baczkowicz.mqttspy.connectivity.reconnection.ReconnectionManager;
import pl.baczkowicz.spy.common.generated.UserCredentials;
import pl.baczkowicz.spy.common.generated.SecureSocketModeEnum;
import pl.baczkowicz.spy.exceptions.SpyException;
import pl.baczkowicz.spy.utils.ConversionUtils;
/**
* Unit and integration tests for connections. Some of the tests assume
* 'mosquitto' is available on the path, and is a version 1.4 or later.
*
* Also, some tests assume availability of the network and 'test.mosquitto.org'.
*
*/
public class ConnectionTestingWithMosquitto
{
private final ReconnectionManager reconnectionManager = new ReconnectionManager();
private Process startMosquitto(final String configurationFile) throws IOException
{
String execStr = "mosquitto -c " + configurationFile;
Process proc = Runtime.getRuntime().exec(execStr);
System.out.println("Proc: " + proc);
return proc;
}
private void stopProcess(final Process mosquitto)
{
System.out.println("Destroying");
mosquitto.destroy();
System.out.println("Destroyed");
}
private MqttCallback createTestCallback(final String connection)
{
return new MqttCallback()
{
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception
{
System.out.println("Got a message for "
+ connection
+ " on " + topic
+ " with content "
+ new String(message.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken arg0)
{
// Not used
}
@Override
public void connectionLost(Throwable arg0)
{
// Not used
}
};
}
private MqttConnectionDetails createMqttConnectionDetails(final String brokerAddress, final UserCredentials uc, final SecureSocketSettings ssl)
{
return new MqttConnectionDetails(
"id",
"test",
ProtocolVersionEnum.MQTT_DEFAULT,
Arrays.asList(brokerAddress),
false,
"mqtt-spy-test",
uc,
null,
true,
10,
10,
ssl,
null);
}
@Test
public void testAnonConnection() throws IOException, SpyException, InterruptedException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_allow_anon.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails("tcp://localhost:10001", null, null);
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("tcp://localhost:10001"));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over TCP", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(1000);
connection.disconnect();
System.out.println("Disconnected");
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testRejectingAnonConnection() throws IOException, SpyException, InterruptedException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_specified_users.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails("tcp://localhost:10002", null, null);
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("tcp://localhost:10002"));
assertFalse(connection.connect());
Thread.sleep(1000);
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testUserConnection() throws IOException, SpyException, InterruptedException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_specified_users.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails(
"tcp://localhost:10002",
new UserCredentials("nopassword", ""),
null);
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("tcp://localhost:10002"));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over TCP", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(1000);
connection.disconnect();
System.out.println("Disconnected");
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testUserConnectionWithPassword() throws IOException, SpyException, InterruptedException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_specified_users.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails(
"tcp://localhost:10002",
new UserCredentials("test1", ConversionUtils.stringToBase64("t1")),
null);
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("tcp://localhost:10002"));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over TCP", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(1000);
connection.disconnect();
System.out.println("Disconnected");
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testUserConnectionWithInvalidPassword() throws IOException, SpyException, InterruptedException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_specified_users.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails("tcp://localhost:10002", new UserCredentials("test1", "blabla"), null);
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("tcp://localhost:10002"));
assertFalse(connection.connect());
Thread.sleep(1000);
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testServerOnlyAuthenticationWithLocalMosquitto() throws SpyException, InterruptedException, IOException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_ssl_server_only.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails(
"ssl://localhost:10010",
new UserCredentials("nopassword", ""),
new SecureSocketSettings(SecureSocketModeEnum.SERVER_ONLY, "TLSv1",
"src/test/resources/mosquitto/ssl/ca.crt",
null, null, null, null, null, null, null, null, null));
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("ssl://localhost:10010"));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over SSL", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(11000);
connection.disconnect();
System.out.println("Disconnected");
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testServerAndClientAuthenticationWithLocalMosquitto() throws SpyException, InterruptedException, IOException
{
final Process mosquitto = startMosquitto("src/test/resources/mosquitto/mosquitto_ssl_server_and_client.conf");
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails(
"ssl://localhost:10011",
new UserCredentials("nopassword", ""),
new SecureSocketSettings(SecureSocketModeEnum.SERVER_AND_CLIENT, "TLSv1.1",
"src/test/resources/mosquitto/ssl/ca.crt",
"src/test/resources/mosquitto/ssl/bouncy_castle/client.crt",
"src/test/resources/mosquitto/ssl/bouncy_castle/client.key",
"", null, null, null, null, null, null));
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback("ssl://localhost:10011"));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over SSL", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(1000);
connection.disconnect();
System.out.println("Disconnected");
stopProcess(mosquitto);
Thread.sleep(2000);
}
@Test
public void testServerOnlyAuthenticationWithLiveMosquitto() throws SpyException, InterruptedException
{
testServerOnlyAuthentication("ssl://test.mosquitto.org", "/certificates/certificate_authority_files/mosquitto.org.crt");
}
@Test
public void testServerOnlyAuthenticationWithLiveEclipseServer() throws SpyException, InterruptedException
{
testServerOnlyAuthentication("ssl://iot.eclipse.org", "/certificates/certificate_authority_files/iot.eclipse.org.crt");
}
private void testServerOnlyAuthentication(final String server, final String certificateAuthorityFile)
throws InterruptedException, SpyException
{
final MqttConnectionDetails connectionDetails = createMqttConnectionDetails(server, null,
new SecureSocketSettings(SecureSocketModeEnum.SERVER_ONLY, "TLSv1.2",
certificateAuthorityFile,
null, null, null, null, null, null, null, null, null));
final SimpleMqttConnection connection = new SimpleMqttConnection(reconnectionManager, "0", connectionDetails);
connection.createClient(createTestCallback(server));
assertTrue(connection.connect());
System.out.println("Connected...");
assertTrue(connection.subscribe("/mqtt-spy/test/", 0));
System.out.println("Subscribed...");
connection.publish("/mqtt-spy/test/", "message over SSL", 0, false);
System.out.println("Published...");
// Waiting for message to be received now...
Thread.sleep(1000);
connection.disconnect();
System.out.println("Disconnected");
}
}