summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Clayton <alex.clayton@isode.com>2016-02-15 17:24:49 (GMT)
committerAlex Clayton <alex.clayton@isode.com>2016-02-29 10:39:49 (GMT)
commit3bfe54c141dd3fa20e391312a0a84c75731e2b2a (patch)
tree4de10e954ff540fa6e1b70c8735ac5da14b19743 /test/com/isode/stroke/network/BoshConnectionTest.java
parent2ebf488dfee7156fbbe0b3d3eccebe13d86a8634 (diff)
downloadstroke-3bfe54c141dd3fa20e391312a0a84c75731e2b2a.zip
stroke-3bfe54c141dd3fa20e391312a0a84c75731e2b2a.tar.bz2
Add Network Bosh Classes
Add the missing Bosh classes to the network packages (BoshConnection and BoshConnectionPool), plus tests for the classes and any other classes required by the new classes. Test-information: Units tests all pass ok. Change-Id: I5c2e05bae9e678ac10d2601c7fdbdccd68d66b71
Diffstat (limited to 'test/com/isode/stroke/network/BoshConnectionTest.java')
-rw-r--r--test/com/isode/stroke/network/BoshConnectionTest.java352
1 files changed, 352 insertions, 0 deletions
diff --git a/test/com/isode/stroke/network/BoshConnectionTest.java b/test/com/isode/stroke/network/BoshConnectionTest.java
new file mode 100644
index 0000000..0fa4020
--- /dev/null
+++ b/test/com/isode/stroke/network/BoshConnectionTest.java
@@ -0,0 +1,352 @@
+/* Copyright (c) 2016, Isode Limited, London, England.
+ * All rights reserved.
+ *
+ * Acquisition and use of this software and related materials for any
+ * purpose requires a written license agreement from Isode Limited,
+ * or a written license from an organisation licensed by Isode Limited
+ * to grant such a license.
+ *
+ */
+package com.isode.stroke.network;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Test;
+
+import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.base.SafeByteArray;
+import com.isode.stroke.base.URL;
+import com.isode.stroke.eventloop.DummyEventLoop;
+import com.isode.stroke.eventloop.Event.Callback;
+import com.isode.stroke.eventloop.EventLoop;
+import com.isode.stroke.network.BOSHConnection.Pair;
+import com.isode.stroke.parser.PlatformXMLParserFactory;
+import com.isode.stroke.signals.Slot1;
+import com.isode.stroke.signals.Slot2;
+import com.isode.stroke.tls.TLSContextFactory;
+import com.isode.stroke.tls.TLSOptions;
+
+/**
+ * Test for {@link BoshConnection}
+ */
+public class BoshConnectionTest {
+
+ private final DummyEventLoop eventLoop = new DummyEventLoop();
+ private final MockConnectionFactory connectionFactory = new MockConnectionFactory(eventLoop);
+ private boolean connectFinished = false;
+ private boolean connectFinishedWithError = false;
+ private boolean disconnected = false;
+ private boolean disconnectedError = false;
+ private final ByteArray dataRead = new ByteArray();
+ private final PlatformXMLParserFactory parserFactory = new PlatformXMLParserFactory();
+ private final StaticDomainNameResolver resolver = new StaticDomainNameResolver(eventLoop);
+ private final TimerFactory timerFactory = new DummyTimerFactory();
+ private final TLSContextFactory tlsContextFactory = null;
+ private String sid;
+
+ @After
+ public void tearDown() {
+ eventLoop.processEvents();
+ }
+
+ @Test
+ public void testHeader() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.startStream("wonderland.lit",1);
+ String initial = "<body wait='60' "
+ +"inactivity='30' "
+ +"polling='5' "
+ +"requests='2' "
+ +"hold='1' "
+ +"maxpause='120' "
+ +"sid='MyShinySID' "
+ +"ver='1.6' "
+ +"from='wonderland.lit' "
+ +"xmlns='http://jabber.org/protocol/httpbind'/>";
+ readResponse(initial, connectionFactory.connections.get(0));
+ assertEquals("MyShinySID",sid);
+ assertTrue(testling.isReadyToSend());
+ }
+
+ @Test
+ public void testReadiness_ok() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.setSID("blahhhh");
+ assertTrue(testling.isReadyToSend());
+ }
+
+ @Test
+ public void testReadiness_pending() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.setSID("mySID");
+ assertTrue(testling.isReadyToSend());
+ testling.write(new SafeByteArray("<mypayload/>"));
+ assertFalse(testling.isReadyToSend());
+ readResponse("<body><blah/></body>", connectionFactory.connections.get(0));
+ assertTrue(testling.isReadyToSend());
+ }
+
+ @Test
+ public void testReadiness_disconnect() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.setSID("mySID");
+ assertTrue(testling.isReadyToSend());
+ connectionFactory.connections.get(0).onDisconnected.emit(null);
+ assertFalse(testling.isReadyToSend());
+ }
+
+ @Test
+ public void testReadiness_noSID() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ assertFalse(testling.isReadyToSend());
+ }
+
+ @Test
+ public void testWrite_Receive() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.setSID("mySID");
+ testling.write(new SafeByteArray("<mypayload/>"));
+ readResponse("<body><blah/></body>", connectionFactory.connections.get(0));
+ assertEquals("<blah/>",dataRead.toString());
+ }
+
+ @Test
+ public void testWrite_ReceiveTwice() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ testling.setSID("mySID");
+ testling.write(new SafeByteArray("<mypayload/>"));
+ readResponse("<body><blah/></body>", connectionFactory.connections.get(0));
+ assertEquals("<blah/>",dataRead.toString());
+ dataRead.clear();
+ testling.write(new SafeByteArray("<mypayload2/>"));
+ readResponse("<body><bleh/></body>", connectionFactory.connections.get(0));
+ assertEquals("<bleh/>",dataRead.toString());
+ }
+
+ @Test
+ public void testRead_Fragment() {
+ BOSHConnection testling = createTestling();
+ testling.connect();
+ eventLoop.processEvents();
+ assertEquals(1, connectionFactory.connections.size());
+ MockConnection connection = connectionFactory.connections.get(0);
+ SafeByteArray data1 = new SafeByteArray(
+ "HTTP/1.1 200 OK\r\n"+
+ "Content-Type: text/xml; charset=utf-8\r\n"+
+ "Access-Control-Allow-Origin: *\r\n"+
+ "Access-Control-Allow-Headers: Content-Type\r\n"+
+ "Content-Length: 64\r\n");
+ SafeByteArray data2 = new SafeByteArray(
+ "\r\n<body xmlns='http://jabber.org/protocol/httpbind'>"+
+ "<bl");
+ SafeByteArray data3 = new SafeByteArray(
+ "ah/>"+
+ "</body>");
+ connection.onDataRead.emit(data1);
+ connection.onDataRead.emit(data2);
+ assertTrue(dataRead.isEmpty());
+ connection.onDataRead.emit(data3);
+ assertEquals("<blah/>",dataRead.toString());
+ }
+
+ @Test
+ public void testHTTPRequest() {
+ String data = "<blah/>";
+ String sid = "wigglebloom";
+ String fullBody = "<body xmlns='http://jabber.org/protocol/httpbind' sid='" + sid + "' rid='20'>" + data + "</body>";
+ Pair<SafeByteArray, Integer> http =
+ BOSHConnection.createHTTPRequest(new SafeByteArray(data), false, false,
+ 20, sid, new URL());
+ assertEquals(fullBody.length(),http.second.intValue());
+ }
+
+ @Test
+ public void testHTTPRequest_Empty() {
+ String data = "";
+ String sid = "wigglebloomsickle";
+ String fullBody = "<body rid='42' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'>" + data + "</body>";
+ Pair<SafeByteArray, Integer> http =
+ BOSHConnection.createHTTPRequest(new SafeByteArray(data), false, false,
+ 42, sid, new URL());
+ assertEquals(fullBody.length(),http.second.intValue());
+ String response = http.first.toString();
+ int bodyPosition = response.indexOf("\r\n\r\n");
+ assertFalse("bodyPosition is equal to -1",-1 == bodyPosition);
+ assertEquals(fullBody,response.substring(bodyPosition+4));
+ }
+
+ private BOSHConnection createTestling() {
+ resolver.addAddress("wonderland.lit", new HostAddress("127.0.0.1"));
+ Connector connector = Connector.create("wonderland.lit", 5280, null, resolver, connectionFactory, timerFactory);
+ BOSHConnection connection = BOSHConnection.create(new URL(), connector, parserFactory,
+ tlsContextFactory, new TLSOptions());
+ connection.onConnectionFinished.connect(new Slot1<Boolean>() {
+
+ @Override
+ public void call(Boolean hadError) {
+ handleConnectFinished(hadError.booleanValue());
+ }
+
+ });
+ connection.onDisconnected.connect(new Slot1<Boolean>() {
+
+ @Override
+ public void call(Boolean hadError) {
+ handleDisconnected(hadError.booleanValue());
+ }
+
+ });
+ connection.onXMPPDataRead.connect(new Slot1<SafeByteArray>() {
+
+ @Override
+ public void call(SafeByteArray p1) {
+ handleDataRead(p1);
+ }
+
+ });
+ connection.onSessionStarted.connect(new Slot2<String, Integer>() {
+
+ @Override
+ public void call(String sid, Integer requests) {
+ handleSID(sid);
+ }
+
+ });
+ connection.setRID(42);
+ return connection;
+ }
+
+ private void handleConnectFinished(boolean hadError) {
+ connectFinished = true;
+ connectFinishedWithError = hadError;
+ }
+
+ private void handleDisconnected(boolean hadError) {
+ disconnected = true;
+ disconnectedError = hadError;
+ }
+
+ private void handleDataRead(SafeByteArray data) {
+ dataRead.append(data);
+ }
+
+ private void handleSID(String s) {
+ sid = s;
+ }
+
+ private void readResponse(String response,MockConnection connection) {
+ SafeByteArray data1 = new SafeByteArray(
+ "HTTP/1.1 200 OK\r\n"+
+ "Content-Type: text/xml; charset=utf-8\r\n"+
+ "Access-Control-Allow-Origin: *\r\n"+
+ "Access-Control-Allow-Headers: Content-Type\r\n"+
+ "Content-Length: "
+ );
+ connection.onDataRead.emit(data1);
+ SafeByteArray data2 = new SafeByteArray(Integer.toString(response.length()));
+ connection.onDataRead.emit(data2);
+ SafeByteArray data3 = new SafeByteArray("\r\n\r\n");
+ connection.onDataRead.emit(data3);
+ SafeByteArray data4 = new SafeByteArray(response);
+ connection.onDataRead.emit(data4);
+ }
+
+ private static class MockConnection extends Connection {
+
+ public MockConnection(Collection<HostAddressPort> failingPorts,
+ EventLoop eventLoop) {
+ this.failingPorts = new ArrayList<HostAddressPort>(failingPorts);
+ this.eventLoop = eventLoop;
+ }
+
+ @Override
+ public void listen() {
+ fail();
+ }
+
+ @Override
+ public void connect(HostAddressPort address) {
+ hostAddressPort = address;
+ final boolean fail = failingPorts.contains(address);
+ eventLoop.postEvent(new Callback() {
+
+ @Override
+ public void run() {
+ onConnectFinished.emit(fail);
+ }
+
+ });
+ }
+
+ @Override
+ public void disconnect() {
+ disconnected = true;
+ onDisconnected.emit(null);
+ }
+
+ @Override
+ public void write(SafeByteArray data) {
+ dataWritten.append(data);
+ }
+
+ /* (non-Javadoc)
+ * @see com.isode.stroke.network.Connection#getLocalAddress()
+ */
+ @Override
+ public HostAddressPort getLocalAddress() {
+ return new HostAddressPort();
+ }
+
+ public HostAddressPort getRemoteAddress() {
+ return new HostAddressPort();
+ }
+
+ private final EventLoop eventLoop;
+ private HostAddressPort hostAddressPort;
+ private final List<HostAddressPort> failingPorts;
+ private final ByteArray dataWritten = new ByteArray();
+ private boolean disconnected;
+
+ }
+
+ private static class MockConnectionFactory implements ConnectionFactory {
+
+ public MockConnectionFactory(EventLoop eventLoop) {
+ this.eventLoop = eventLoop;
+ }
+
+ @Override
+ public Connection createConnection() {
+ MockConnection connection = new MockConnection(failingPorts, eventLoop);
+ connections.add(connection);
+ return connection;
+ }
+
+ private final EventLoop eventLoop;
+ private List<MockConnection> connections = new ArrayList<MockConnection>();
+ private List<HostAddressPort> failingPorts = new ArrayList<HostAddressPort>();
+ }
+
+}