summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Network/UnitTest')
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp860
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionTest.cpp540
-rw-r--r--Swiften/Network/UnitTest/ChainedConnectorTest.cpp320
-rw-r--r--Swiften/Network/UnitTest/ConnectorTest.cpp704
-rw-r--r--Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp102
-rw-r--r--Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp784
-rw-r--r--Swiften/Network/UnitTest/HostAddressTest.cpp72
7 files changed, 1691 insertions, 1691 deletions
diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
index e8d8c4a..e781742 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
@@ -33,436 +33,436 @@ typedef boost::shared_ptr<BOSHConnectionPool> PoolRef;
class BOSHConnectionPoolTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(BOSHConnectionPoolTest);
- CPPUNIT_TEST(testConnectionCount_OneWrite);
- CPPUNIT_TEST(testConnectionCount_TwoWrites);
- CPPUNIT_TEST(testConnectionCount_ThreeWrites);
- CPPUNIT_TEST(testConnectionCount_ThreeWrites_ManualConnect);
- CPPUNIT_TEST(testConnectionCount_ThreeWritesTwoReads);
- CPPUNIT_TEST(testSession);
- CPPUNIT_TEST(testWrite_Empty);
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- to = "wonderland.lit";
- path = "/http-bind";
- port = "5280";
- sid = "MyShinySID";
- initial = "<body wait='60' "
- "inactivity='30' "
- "polling='5' "
- "requests='2' "
- "hold='1' "
- "maxpause='120' "
- "sid='" + sid + "' "
- "ver='1.6' "
- "from='wonderland.lit' "
- "xmlns='http://jabber.org/protocol/httpbind'/>";
- eventLoop = new DummyEventLoop();
- connectionFactory = new MockConnectionFactory(eventLoop);
- boshURL = URL("http", to, 5280, path);
- sessionTerminated = 0;
- sessionStarted = 0;
- initialRID = 2349876;
- xmppDataRead.clear();
- boshDataRead.clear();
- boshDataWritten.clear();
- resolver = new StaticDomainNameResolver(eventLoop);
- resolver->addAddress(to, HostAddress("127.0.0.1"));
- timerFactory = new DummyTimerFactory();
- }
-
- void tearDown() {
- eventLoop->processEvents();
- delete connectionFactory;
- delete resolver;
- delete timerFactory;
- delete eventLoop;
- }
-
- void testConnectionCount_OneWrite() {
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(0, sessionStarted);
- readResponse(initial, connectionFactory->connections[0]);
- CPPUNIT_ASSERT_EQUAL(1, sessionStarted);
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- testling->write(createSafeByteArray("<blah/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- CPPUNIT_ASSERT_EQUAL(1, sessionStarted);
- }
-
- void testConnectionCount_TwoWrites() {
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- eventLoop->processEvents();
- readResponse(initial, connectionFactory->connections[0]);
- eventLoop->processEvents();
- testling->write(createSafeByteArray("<blah/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- testling->write(createSafeByteArray("<bleh/>"));
- eventLoop->processEvents();
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
- }
-
- void testConnectionCount_ThreeWrites() {
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- eventLoop->processEvents();
- readResponse(initial, connectionFactory->connections[0]);
- testling->restartStream();
- readResponse("<body/>", connectionFactory->connections[0]);
- testling->restartStream();
- readResponse("<body/>", connectionFactory->connections[0]);
- testling->write(createSafeByteArray("<blah/>"));
- testling->write(createSafeByteArray("<bleh/>"));
- testling->write(createSafeByteArray("<bluh/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size());
- }
-
- void testConnectionCount_ThreeWrites_ManualConnect() {
- connectionFactory->autoFinishConnect = false;
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- CPPUNIT_ASSERT_EQUAL(st(0), boshDataWritten.size()); /* Connection not connected yet, can't send data */
-
- connectionFactory->connections[0]->onConnectFinished(false);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Connection finished, stream header sent */
-
- readResponse(initial, connectionFactory->connections[0]);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Don't respond to initial data with a holding call */
-
- testling->restartStream();
- eventLoop->processEvents();
- readResponse("<body/>", connectionFactory->connections[0]);
- eventLoop->processEvents();
- testling->restartStream();
- eventLoop->processEvents();
-
-
- testling->write(createSafeByteArray("<blah/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
- CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); /* New connection isn't up yet. */
-
- connectionFactory->connections[1]->onConnectFinished(false);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New connection ready. */
-
- testling->write(createSafeByteArray("<bleh/>"));
- eventLoop->processEvents();
- testling->write(createSafeByteArray("<bluh/>"));
- CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New data can't be sent, no free connections. */
- eventLoop->processEvents();
- CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size());
- }
-
- void testConnectionCount_ThreeWritesTwoReads() {
- boost::shared_ptr<MockConnection> c0;
- boost::shared_ptr<MockConnection> c1;
- unsigned long long rid = initialRID;
-
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- c0 = connectionFactory->connections[0];
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/
-
- rid++;
- readResponse(initial, c0);
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- CPPUNIT_ASSERT(!c0->pending);
-
- rid++;
- testling->restartStream();
- eventLoop->processEvents();
- readResponse("<body/>", connectionFactory->connections[0]);
-
- rid++;
- testling->write(createSafeByteArray("<blah/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* 0 was waiting for response, open and send on 1 */
- CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* data */
- c1 = connectionFactory->connections[1];
- std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(rid) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'><blah/></body>"; /* check empty write */
- CPPUNIT_ASSERT_EQUAL(fullBody, lastBody());
- CPPUNIT_ASSERT(c0->pending);
- CPPUNIT_ASSERT(c1->pending);
-
-
- rid++;
- readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing/></message></body>", c0); /* Doesn't include necessary attributes - as the support is improved this'll start to fail */
- eventLoop->processEvents();
- CPPUNIT_ASSERT(!c0->pending);
- CPPUNIT_ASSERT(c1->pending);
- CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* don't send empty in [0], still have [1] waiting */
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
-
- rid++;
- readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing><blittlebarg/></splatploing></message></body>", c1);
- eventLoop->processEvents();
- CPPUNIT_ASSERT(!c1->pending);
- CPPUNIT_ASSERT(c0->pending);
- CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* empty to make room */
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
-
- rid++;
- testling->write(createSafeByteArray("<bleh/>"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT(c0->pending);
- CPPUNIT_ASSERT(c1->pending);
- CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* data */
-
- rid++;
- testling->write(createSafeByteArray("<bluh/>"));
- CPPUNIT_ASSERT(c0->pending);
- CPPUNIT_ASSERT(c1->pending);
- CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* Don't send data, no room */
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
- }
-
- void testSession() {
- to = "prosody.doomsong.co.uk";
- resolver->addAddress("prosody.doomsong.co.uk", HostAddress("127.0.0.1"));
- path = "/http-bind/";
- boshURL = URL("http", to, 5280, path);
-
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- std::string response = "<body authid='743da605-4c2e-4de1-afac-ac040dd4a940' xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>SCRAM-SHA-1</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features></body>";
- readResponse(response, connectionFactory->connections[0]);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- std::string send = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"SCRAM-SHA-1\">biwsbj1hZG1pbixyPWZhOWE5ZDhiLWZmMDctNGE4Yy04N2E3LTg4YWRiNDQxZGUwYg==</auth>";
- testling->write(createSafeByteArray(send));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj1mYTlhOWQ4Yi1mZjA3LTRhOGMtODdhNy04OGFkYjQ0MWRlMGJhZmZlMWNhMy1mMDJkLTQ5NzEtYjkyNS0yM2NlNWQ2MDQyMjYscz1OVGd5WkdWaFptTXRaVE15WXkwMFpXUmhMV0ZqTURRdFpqYzRNbUppWmpGa1pqWXgsaT00MDk2</challenge></body>";
- readResponse(response, connectionFactory->connections[0]);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- send = "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">Yz1iaXdzLHI9ZmE5YTlkOGItZmYwNy00YThjLTg3YTctODhhZGI0NDFkZTBiYWZmZTFjYTMtZjAyZC00OTcxLWI5MjUtMjNjZTVkNjA0MjI2LHA9aU11NWt3dDN2VWplU2RqL01Jb3VIRldkZjBnPQ==</response>";
- testling->write(createSafeByteArray(send));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dj1YNmNBY3BBOWxHNjNOOXF2bVQ5S0FacERrVm89</success></body>";
- readResponse(response, connectionFactory->connections[0]);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- testling->restartStream();
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- response = "<body xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind><session xmlns='urn:ietf:params:xml:ns:xmpp-session'><optional/></session><sm xmlns='urn:xmpp:sm:2'><optional/></sm></stream:features></body>";
- readResponse(response, connectionFactory->connections[0]);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* Now we've authed (restarted) we should be keeping one query in flight so the server can reply to us at any time it wants. */
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
-
- send = "<body rid='2821988967416214' sid='cf663f6b94279d4f' xmlns='http://jabber.org/protocol/httpbind'><iq id='session-bind' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>d5a9744036cd20a0</resource></bind></iq></body>";
- testling->write(createSafeByteArray(send));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size());
- CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* and as it keeps one in flight, it's needed to open a second to send these data */
-
- }
-
- void testWrite_Empty() {
- boost::shared_ptr<MockConnection> c0;
-
- PoolRef testling = createTestling();
- CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
- c0 = connectionFactory->connections[0];
-
- readResponse(initial, c0);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Shouldn't have sent anything extra */
- eventLoop->processEvents();
- testling->restartStream();
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
- readResponse("<body></body>", c0);
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
- std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(initialRID + 2) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'></body>";
- std::string response = boshDataWritten[2];
- size_t bodyPosition = response.find("\r\n\r\n");
- CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4));
-
-
- }
-
- private:
-
- PoolRef createTestling() {
- // make_shared is limited to 9 arguments; instead new is used here.
- PoolRef pool = PoolRef(new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions()));
- pool->open();
- pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1));
- pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1));
- pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1));
- pool->onSessionStarted.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionStarted, this));
- pool->onSessionTerminated.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionTerminated, this));
- eventLoop->processEvents();
- eventLoop->processEvents();
- return pool;
- }
-
- std::string lastBody() {
- std::string response = boshDataWritten[boshDataWritten.size() - 1];
- size_t bodyPosition = response.find("\r\n\r\n");
- return response.substr(bodyPosition+4);
- }
-
- size_t st(int val) {
- return static_cast<size_t>(val);
- }
-
- void handleXMPPDataRead(const SafeByteArray& d) {
- xmppDataRead.push_back(safeByteArrayToString(d));
- }
-
- void handleBOSHDataRead(const SafeByteArray& d) {
- boshDataRead.push_back(safeByteArrayToString(d));
- }
-
- void handleBOSHDataWritten(const SafeByteArray& d) {
- boshDataWritten.push_back(safeByteArrayToString(d));
- }
-
-
- void handleSessionStarted() {
- sessionStarted++;
- }
-
- void handleSessionTerminated() {
- sessionTerminated++;
- }
-
- struct MockConnection : public Connection {
- public:
- MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop, bool autoFinishConnect) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false), pending(false), autoFinishConnect(autoFinishConnect) {
- }
-
- void listen() { assert(false); }
-
- void connect(const HostAddressPort& address) {
- hostAddressPort = address;
- bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
- if (autoFinishConnect) {
- eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
- }
- }
-
- HostAddressPort getLocalAddress() const { return HostAddressPort(); }
- HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
-
- void disconnect() {
- disconnected = true;
- onDisconnected(boost::optional<Connection::Error>());
- }
-
- void write(const SafeByteArray& d) {
- append(dataWritten, d);
- pending = true;
- }
-
- EventLoop* eventLoop;
- boost::optional<HostAddressPort> hostAddressPort;
- std::vector<HostAddressPort> failingPorts;
- ByteArray dataWritten;
- bool disconnected;
- bool pending;
- bool autoFinishConnect;
- };
-
- struct MockConnectionFactory : public ConnectionFactory {
- MockConnectionFactory(EventLoop* eventLoop, bool autoFinishConnect = true) : eventLoop(eventLoop), autoFinishConnect(autoFinishConnect) {
- }
-
- boost::shared_ptr<Connection> createConnection() {
- boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop, autoFinishConnect);
- connections.push_back(connection);
- return connection;
- }
-
- EventLoop* eventLoop;
- std::vector< boost::shared_ptr<MockConnection> > connections;
- std::vector<HostAddressPort> failingPorts;
- bool autoFinishConnect;
- };
-
- void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) {
- connection->pending = false;
- boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
- "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(data1);
- boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size())));
- connection->onDataRead(data2);
- boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n"));
- connection->onDataRead(data3);
- boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response));
- connection->onDataRead(data4);
- }
-
- std::string fullRequestFor(const std::string& data) {
- std::string body = data;
- std::string result = "POST /" + path + " HTTP/1.1\r\n"
- + "Host: " + to + ":" + port + "\r\n"
- + "Content-Type: text/xml; charset=utf-8\r\n"
- + "Content-Length: " + boost::lexical_cast<std::string>(body.size()) + "\r\n\r\n"
- + body;
- return result;
- }
-
- private:
- URL boshURL;
- DummyEventLoop* eventLoop;
- MockConnectionFactory* connectionFactory;
- std::vector<std::string> xmppDataRead;
- std::vector<std::string> boshDataRead;
- std::vector<std::string> boshDataWritten;
- PlatformXMLParserFactory parserFactory;
- StaticDomainNameResolver* resolver;
- TimerFactory* timerFactory;
- std::string to;
- std::string path;
- std::string port;
- std::string sid;
- std::string initial;
- unsigned long long initialRID;
- int sessionStarted;
- int sessionTerminated;
+ CPPUNIT_TEST_SUITE(BOSHConnectionPoolTest);
+ CPPUNIT_TEST(testConnectionCount_OneWrite);
+ CPPUNIT_TEST(testConnectionCount_TwoWrites);
+ CPPUNIT_TEST(testConnectionCount_ThreeWrites);
+ CPPUNIT_TEST(testConnectionCount_ThreeWrites_ManualConnect);
+ CPPUNIT_TEST(testConnectionCount_ThreeWritesTwoReads);
+ CPPUNIT_TEST(testSession);
+ CPPUNIT_TEST(testWrite_Empty);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ to = "wonderland.lit";
+ path = "/http-bind";
+ port = "5280";
+ sid = "MyShinySID";
+ initial = "<body wait='60' "
+ "inactivity='30' "
+ "polling='5' "
+ "requests='2' "
+ "hold='1' "
+ "maxpause='120' "
+ "sid='" + sid + "' "
+ "ver='1.6' "
+ "from='wonderland.lit' "
+ "xmlns='http://jabber.org/protocol/httpbind'/>";
+ eventLoop = new DummyEventLoop();
+ connectionFactory = new MockConnectionFactory(eventLoop);
+ boshURL = URL("http", to, 5280, path);
+ sessionTerminated = 0;
+ sessionStarted = 0;
+ initialRID = 2349876;
+ xmppDataRead.clear();
+ boshDataRead.clear();
+ boshDataWritten.clear();
+ resolver = new StaticDomainNameResolver(eventLoop);
+ resolver->addAddress(to, HostAddress("127.0.0.1"));
+ timerFactory = new DummyTimerFactory();
+ }
+
+ void tearDown() {
+ eventLoop->processEvents();
+ delete connectionFactory;
+ delete resolver;
+ delete timerFactory;
+ delete eventLoop;
+ }
+
+ void testConnectionCount_OneWrite() {
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(0, sessionStarted);
+ readResponse(initial, connectionFactory->connections[0]);
+ CPPUNIT_ASSERT_EQUAL(1, sessionStarted);
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ testling->write(createSafeByteArray("<blah/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ CPPUNIT_ASSERT_EQUAL(1, sessionStarted);
+ }
+
+ void testConnectionCount_TwoWrites() {
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ eventLoop->processEvents();
+ readResponse(initial, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ testling->write(createSafeByteArray("<blah/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ testling->write(createSafeByteArray("<bleh/>"));
+ eventLoop->processEvents();
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
+ }
+
+ void testConnectionCount_ThreeWrites() {
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ eventLoop->processEvents();
+ readResponse(initial, connectionFactory->connections[0]);
+ testling->restartStream();
+ readResponse("<body/>", connectionFactory->connections[0]);
+ testling->restartStream();
+ readResponse("<body/>", connectionFactory->connections[0]);
+ testling->write(createSafeByteArray("<blah/>"));
+ testling->write(createSafeByteArray("<bleh/>"));
+ testling->write(createSafeByteArray("<bluh/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size());
+ }
+
+ void testConnectionCount_ThreeWrites_ManualConnect() {
+ connectionFactory->autoFinishConnect = false;
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ CPPUNIT_ASSERT_EQUAL(st(0), boshDataWritten.size()); /* Connection not connected yet, can't send data */
+
+ connectionFactory->connections[0]->onConnectFinished(false);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Connection finished, stream header sent */
+
+ readResponse(initial, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Don't respond to initial data with a holding call */
+
+ testling->restartStream();
+ eventLoop->processEvents();
+ readResponse("<body/>", connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ testling->restartStream();
+ eventLoop->processEvents();
+
+
+ testling->write(createSafeByteArray("<blah/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
+ CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); /* New connection isn't up yet. */
+
+ connectionFactory->connections[1]->onConnectFinished(false);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New connection ready. */
+
+ testling->write(createSafeByteArray("<bleh/>"));
+ eventLoop->processEvents();
+ testling->write(createSafeByteArray("<bluh/>"));
+ CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New data can't be sent, no free connections. */
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size());
+ }
+
+ void testConnectionCount_ThreeWritesTwoReads() {
+ boost::shared_ptr<MockConnection> c0;
+ boost::shared_ptr<MockConnection> c1;
+ unsigned long long rid = initialRID;
+
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ c0 = connectionFactory->connections[0];
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/
+
+ rid++;
+ readResponse(initial, c0);
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ CPPUNIT_ASSERT(!c0->pending);
+
+ rid++;
+ testling->restartStream();
+ eventLoop->processEvents();
+ readResponse("<body/>", connectionFactory->connections[0]);
+
+ rid++;
+ testling->write(createSafeByteArray("<blah/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* 0 was waiting for response, open and send on 1 */
+ CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* data */
+ c1 = connectionFactory->connections[1];
+ std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(rid) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'><blah/></body>"; /* check empty write */
+ CPPUNIT_ASSERT_EQUAL(fullBody, lastBody());
+ CPPUNIT_ASSERT(c0->pending);
+ CPPUNIT_ASSERT(c1->pending);
+
+
+ rid++;
+ readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing/></message></body>", c0); /* Doesn't include necessary attributes - as the support is improved this'll start to fail */
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(!c0->pending);
+ CPPUNIT_ASSERT(c1->pending);
+ CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* don't send empty in [0], still have [1] waiting */
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
+
+ rid++;
+ readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing><blittlebarg/></splatploing></message></body>", c1);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(!c1->pending);
+ CPPUNIT_ASSERT(c0->pending);
+ CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* empty to make room */
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
+
+ rid++;
+ testling->write(createSafeByteArray("<bleh/>"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(c0->pending);
+ CPPUNIT_ASSERT(c1->pending);
+ CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* data */
+
+ rid++;
+ testling->write(createSafeByteArray("<bluh/>"));
+ CPPUNIT_ASSERT(c0->pending);
+ CPPUNIT_ASSERT(c1->pending);
+ CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* Don't send data, no room */
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size());
+ }
+
+ void testSession() {
+ to = "prosody.doomsong.co.uk";
+ resolver->addAddress("prosody.doomsong.co.uk", HostAddress("127.0.0.1"));
+ path = "/http-bind/";
+ boshURL = URL("http", to, 5280, path);
+
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ std::string response = "<body authid='743da605-4c2e-4de1-afac-ac040dd4a940' xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>SCRAM-SHA-1</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features></body>";
+ readResponse(response, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ std::string send = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"SCRAM-SHA-1\">biwsbj1hZG1pbixyPWZhOWE5ZDhiLWZmMDctNGE4Yy04N2E3LTg4YWRiNDQxZGUwYg==</auth>";
+ testling->write(createSafeByteArray(send));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj1mYTlhOWQ4Yi1mZjA3LTRhOGMtODdhNy04OGFkYjQ0MWRlMGJhZmZlMWNhMy1mMDJkLTQ5NzEtYjkyNS0yM2NlNWQ2MDQyMjYscz1OVGd5WkdWaFptTXRaVE15WXkwMFpXUmhMV0ZqTURRdFpqYzRNbUppWmpGa1pqWXgsaT00MDk2</challenge></body>";
+ readResponse(response, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ send = "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">Yz1iaXdzLHI9ZmE5YTlkOGItZmYwNy00YThjLTg3YTctODhhZGI0NDFkZTBiYWZmZTFjYTMtZjAyZC00OTcxLWI5MjUtMjNjZTVkNjA0MjI2LHA9aU11NWt3dDN2VWplU2RqL01Jb3VIRldkZjBnPQ==</response>";
+ testling->write(createSafeByteArray(send));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dj1YNmNBY3BBOWxHNjNOOXF2bVQ5S0FacERrVm89</success></body>";
+ readResponse(response, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ testling->restartStream();
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ response = "<body xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind><session xmlns='urn:ietf:params:xml:ns:xmpp-session'><optional/></session><sm xmlns='urn:xmpp:sm:2'><optional/></sm></stream:features></body>";
+ readResponse(response, connectionFactory->connections[0]);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* Now we've authed (restarted) we should be keeping one query in flight so the server can reply to us at any time it wants. */
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+
+ send = "<body rid='2821988967416214' sid='cf663f6b94279d4f' xmlns='http://jabber.org/protocol/httpbind'><iq id='session-bind' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>d5a9744036cd20a0</resource></bind></iq></body>";
+ testling->write(createSafeByteArray(send));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size());
+ CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* and as it keeps one in flight, it's needed to open a second to send these data */
+
+ }
+
+ void testWrite_Empty() {
+ boost::shared_ptr<MockConnection> c0;
+
+ PoolRef testling = createTestling();
+ CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size());
+ c0 = connectionFactory->connections[0];
+
+ readResponse(initial, c0);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Shouldn't have sent anything extra */
+ eventLoop->processEvents();
+ testling->restartStream();
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size());
+ readResponse("<body></body>", c0);
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size());
+ std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(initialRID + 2) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'></body>";
+ std::string response = boshDataWritten[2];
+ size_t bodyPosition = response.find("\r\n\r\n");
+ CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4));
+
+
+ }
+
+ private:
+
+ PoolRef createTestling() {
+ // make_shared is limited to 9 arguments; instead new is used here.
+ PoolRef pool = PoolRef(new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions()));
+ pool->open();
+ pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1));
+ pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1));
+ pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1));
+ pool->onSessionStarted.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionStarted, this));
+ pool->onSessionTerminated.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionTerminated, this));
+ eventLoop->processEvents();
+ eventLoop->processEvents();
+ return pool;
+ }
+
+ std::string lastBody() {
+ std::string response = boshDataWritten[boshDataWritten.size() - 1];
+ size_t bodyPosition = response.find("\r\n\r\n");
+ return response.substr(bodyPosition+4);
+ }
+
+ size_t st(int val) {
+ return static_cast<size_t>(val);
+ }
+
+ void handleXMPPDataRead(const SafeByteArray& d) {
+ xmppDataRead.push_back(safeByteArrayToString(d));
+ }
+
+ void handleBOSHDataRead(const SafeByteArray& d) {
+ boshDataRead.push_back(safeByteArrayToString(d));
+ }
+
+ void handleBOSHDataWritten(const SafeByteArray& d) {
+ boshDataWritten.push_back(safeByteArrayToString(d));
+ }
+
+
+ void handleSessionStarted() {
+ sessionStarted++;
+ }
+
+ void handleSessionTerminated() {
+ sessionTerminated++;
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop, bool autoFinishConnect) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false), pending(false), autoFinishConnect(autoFinishConnect) {
+ }
+
+ void listen() { assert(false); }
+
+ void connect(const HostAddressPort& address) {
+ hostAddressPort = address;
+ bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
+ if (autoFinishConnect) {
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
+ }
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+
+ void disconnect() {
+ disconnected = true;
+ onDisconnected(boost::optional<Connection::Error>());
+ }
+
+ void write(const SafeByteArray& d) {
+ append(dataWritten, d);
+ pending = true;
+ }
+
+ EventLoop* eventLoop;
+ boost::optional<HostAddressPort> hostAddressPort;
+ std::vector<HostAddressPort> failingPorts;
+ ByteArray dataWritten;
+ bool disconnected;
+ bool pending;
+ bool autoFinishConnect;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop, bool autoFinishConnect = true) : eventLoop(eventLoop), autoFinishConnect(autoFinishConnect) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop, autoFinishConnect);
+ connections.push_back(connection);
+ return connection;
+ }
+
+ EventLoop* eventLoop;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ std::vector<HostAddressPort> failingPorts;
+ bool autoFinishConnect;
+ };
+
+ void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) {
+ connection->pending = false;
+ boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
+ "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(data1);
+ boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size())));
+ connection->onDataRead(data2);
+ boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n"));
+ connection->onDataRead(data3);
+ boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response));
+ connection->onDataRead(data4);
+ }
+
+ std::string fullRequestFor(const std::string& data) {
+ std::string body = data;
+ std::string result = "POST /" + path + " HTTP/1.1\r\n"
+ + "Host: " + to + ":" + port + "\r\n"
+ + "Content-Type: text/xml; charset=utf-8\r\n"
+ + "Content-Length: " + boost::lexical_cast<std::string>(body.size()) + "\r\n\r\n"
+ + body;
+ return result;
+ }
+
+ private:
+ URL boshURL;
+ DummyEventLoop* eventLoop;
+ MockConnectionFactory* connectionFactory;
+ std::vector<std::string> xmppDataRead;
+ std::vector<std::string> boshDataRead;
+ std::vector<std::string> boshDataWritten;
+ PlatformXMLParserFactory parserFactory;
+ StaticDomainNameResolver* resolver;
+ TimerFactory* timerFactory;
+ std::string to;
+ std::string path;
+ std::string port;
+ std::string sid;
+ std::string initial;
+ unsigned long long initialRID;
+ int sessionStarted;
+ int sessionTerminated;
};
diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index 8d26a09..bae84fd 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -29,276 +29,276 @@
using namespace Swift;
class BOSHConnectionTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(BOSHConnectionTest);
- CPPUNIT_TEST(testHeader);
- CPPUNIT_TEST(testReadiness_ok);
- CPPUNIT_TEST(testReadiness_pending);
- CPPUNIT_TEST(testReadiness_disconnect);
- CPPUNIT_TEST(testReadiness_noSID);
- CPPUNIT_TEST(testWrite_Receive);
- CPPUNIT_TEST(testWrite_ReceiveTwice);
- CPPUNIT_TEST(testRead_Fragment);
- CPPUNIT_TEST(testHTTPRequest);
- CPPUNIT_TEST(testHTTPRequest_Empty);
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- eventLoop = new DummyEventLoop();
- connectionFactory = new MockConnectionFactory(eventLoop);
- resolver = new StaticDomainNameResolver(eventLoop);
- timerFactory = new DummyTimerFactory();
- tlsContextFactory = NULL;
- connectFinished = false;
- disconnected = false;
- disconnectedError = false;
- dataRead.clear();
- }
-
- void tearDown() {
- eventLoop->processEvents();
- delete connectionFactory;
- delete resolver;
- delete timerFactory;
- delete eventLoop;
- }
-
- void testHeader() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->startStream("wonderland.lit", 1);
- std::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[0]);
- CPPUNIT_ASSERT_EQUAL(std::string("MyShinySID"), sid);
- CPPUNIT_ASSERT(testling->isReadyToSend());
- }
-
- void testReadiness_ok() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->setSID("blahhhhh");
- CPPUNIT_ASSERT(testling->isReadyToSend());
- }
-
- void testReadiness_pending() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->setSID("mySID");
- CPPUNIT_ASSERT(testling->isReadyToSend());
- testling->write(createSafeByteArray("<mypayload/>"));
- CPPUNIT_ASSERT(!testling->isReadyToSend());
- readResponse("<body><blah/></body>", connectionFactory->connections[0]);
- CPPUNIT_ASSERT(testling->isReadyToSend());
- }
-
- void testReadiness_disconnect() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->setSID("mySID");
- CPPUNIT_ASSERT(testling->isReadyToSend());
- connectionFactory->connections[0]->onDisconnected(boost::optional<Connection::Error>());
- CPPUNIT_ASSERT(!testling->isReadyToSend());
- }
-
-
- void testReadiness_noSID() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- CPPUNIT_ASSERT(!testling->isReadyToSend());
- }
-
- void testWrite_Receive() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->setSID("mySID");
- testling->write(createSafeByteArray("<mypayload/>"));
- readResponse("<body><blah/></body>", connectionFactory->connections[0]);
- CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
-
- }
-
- void testWrite_ReceiveTwice() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- testling->setSID("mySID");
- testling->write(createSafeByteArray("<mypayload/>"));
- readResponse("<body><blah/></body>", connectionFactory->connections[0]);
- CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
- dataRead.clear();
- testling->write(createSafeByteArray("<mypayload2/>"));
- readResponse("<body><bleh/></body>", connectionFactory->connections[0]);
- CPPUNIT_ASSERT_EQUAL(std::string("<bleh/>"), byteArrayToString(dataRead));
- }
-
- void testRead_Fragment() {
- BOSHConnection::ref testling = createTestling();
- testling->connect();
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), connectionFactory->connections.size());
- boost::shared_ptr<MockConnection> connection = connectionFactory->connections[0];
- boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
- "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"));
- boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(
- "\r\n<body xmlns='http://jabber.org/protocol/httpbind'>"
- "<bl"));
- boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray(
- "ah/>"
- "</body>"));
- connection->onDataRead(data1);
- connection->onDataRead(data2);
- CPPUNIT_ASSERT(dataRead.empty());
- connection->onDataRead(data3);
- CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
- }
-
- void testHTTPRequest() {
- std::string data = "<blah/>";
- std::string sid = "wigglebloom";
- std::string fullBody = "<body xmlns='http://jabber.org/protocol/httpbind' sid='" + sid + "' rid='20'>" + data + "</body>";
- std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 20, sid, URL());
- CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second);
- }
-
- void testHTTPRequest_Empty() {
- std::string data = "";
- std::string sid = "wigglebloomsickle";
- std::string fullBody = "<body rid='42' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'>" + data + "</body>";
- std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 42, sid, URL());
- CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second);
- std::string response = safeByteArrayToString(http.first);
- size_t bodyPosition = response.find("\r\n\r\n");
- CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4));
- }
-
- private:
-
- BOSHConnection::ref createTestling() {
- resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1"));
- Connector::ref connector = Connector::create("wonderland.lit", 5280, boost::optional<std::string>(), resolver, connectionFactory, timerFactory);
- BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory, tlsContextFactory, TLSOptions());
- c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1));
- c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1));
- c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1));
- c->onSessionStarted.connect(boost::bind(&BOSHConnectionTest::handleSID, this, _1));
- c->setRID(42);
- return c;
- }
-
- void handleConnectFinished(bool error) {
- connectFinished = true;
- connectFinishedWithError = error;
- }
-
- void handleDisconnected(bool e) {
- disconnected = true;
- disconnectedError = e;
- }
-
- void handleDataRead(const SafeByteArray& d) {
- append(dataRead, d);
- }
-
- void handleSID(const std::string& s) {
- sid = s;
- }
-
- struct MockConnection : public Connection {
- public:
- MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) {
- }
-
- void listen() { assert(false); }
-
- void connect(const HostAddressPort& address) {
- hostAddressPort = address;
- bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
- eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
- }
-
- HostAddressPort getLocalAddress() const { return HostAddressPort(); }
- HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
-
- void disconnect() {
- disconnected = true;
- onDisconnected(boost::optional<Connection::Error>());
- }
-
- void write(const SafeByteArray& d) {
- append(dataWritten, d);
- }
-
- EventLoop* eventLoop;
- boost::optional<HostAddressPort> hostAddressPort;
- std::vector<HostAddressPort> failingPorts;
- ByteArray dataWritten;
- bool disconnected;
- };
-
- struct MockConnectionFactory : public ConnectionFactory {
- MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
- }
-
- boost::shared_ptr<Connection> createConnection() {
- boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop);
- connections.push_back(connection);
- return connection;
- }
-
- EventLoop* eventLoop;
- std::vector< boost::shared_ptr<MockConnection> > connections;
- std::vector<HostAddressPort> failingPorts;
- };
-
- void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) {
- boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
- "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(data1);
- boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size())));
- connection->onDataRead(data2);
- boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n"));
- connection->onDataRead(data3);
- boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response));
- connection->onDataRead(data4);
- }
-
-
- private:
- DummyEventLoop* eventLoop;
- MockConnectionFactory* connectionFactory;
- bool connectFinished;
- bool connectFinishedWithError;
- bool disconnected;
- bool disconnectedError;
- ByteArray dataRead;
- PlatformXMLParserFactory parserFactory;
- StaticDomainNameResolver* resolver;
- TimerFactory* timerFactory;
- TLSContextFactory* tlsContextFactory;
- std::string sid;
+ CPPUNIT_TEST_SUITE(BOSHConnectionTest);
+ CPPUNIT_TEST(testHeader);
+ CPPUNIT_TEST(testReadiness_ok);
+ CPPUNIT_TEST(testReadiness_pending);
+ CPPUNIT_TEST(testReadiness_disconnect);
+ CPPUNIT_TEST(testReadiness_noSID);
+ CPPUNIT_TEST(testWrite_Receive);
+ CPPUNIT_TEST(testWrite_ReceiveTwice);
+ CPPUNIT_TEST(testRead_Fragment);
+ CPPUNIT_TEST(testHTTPRequest);
+ CPPUNIT_TEST(testHTTPRequest_Empty);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ eventLoop = new DummyEventLoop();
+ connectionFactory = new MockConnectionFactory(eventLoop);
+ resolver = new StaticDomainNameResolver(eventLoop);
+ timerFactory = new DummyTimerFactory();
+ tlsContextFactory = NULL;
+ connectFinished = false;
+ disconnected = false;
+ disconnectedError = false;
+ dataRead.clear();
+ }
+
+ void tearDown() {
+ eventLoop->processEvents();
+ delete connectionFactory;
+ delete resolver;
+ delete timerFactory;
+ delete eventLoop;
+ }
+
+ void testHeader() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->startStream("wonderland.lit", 1);
+ std::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[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("MyShinySID"), sid);
+ CPPUNIT_ASSERT(testling->isReadyToSend());
+ }
+
+ void testReadiness_ok() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->setSID("blahhhhh");
+ CPPUNIT_ASSERT(testling->isReadyToSend());
+ }
+
+ void testReadiness_pending() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->setSID("mySID");
+ CPPUNIT_ASSERT(testling->isReadyToSend());
+ testling->write(createSafeByteArray("<mypayload/>"));
+ CPPUNIT_ASSERT(!testling->isReadyToSend());
+ readResponse("<body><blah/></body>", connectionFactory->connections[0]);
+ CPPUNIT_ASSERT(testling->isReadyToSend());
+ }
+
+ void testReadiness_disconnect() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->setSID("mySID");
+ CPPUNIT_ASSERT(testling->isReadyToSend());
+ connectionFactory->connections[0]->onDisconnected(boost::optional<Connection::Error>());
+ CPPUNIT_ASSERT(!testling->isReadyToSend());
+ }
+
+
+ void testReadiness_noSID() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT(!testling->isReadyToSend());
+ }
+
+ void testWrite_Receive() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->setSID("mySID");
+ testling->write(createSafeByteArray("<mypayload/>"));
+ readResponse("<body><blah/></body>", connectionFactory->connections[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
+
+ }
+
+ void testWrite_ReceiveTwice() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ testling->setSID("mySID");
+ testling->write(createSafeByteArray("<mypayload/>"));
+ readResponse("<body><blah/></body>", connectionFactory->connections[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
+ dataRead.clear();
+ testling->write(createSafeByteArray("<mypayload2/>"));
+ readResponse("<body><bleh/></body>", connectionFactory->connections[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("<bleh/>"), byteArrayToString(dataRead));
+ }
+
+ void testRead_Fragment() {
+ BOSHConnection::ref testling = createTestling();
+ testling->connect();
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), connectionFactory->connections.size());
+ boost::shared_ptr<MockConnection> connection = connectionFactory->connections[0];
+ boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
+ "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"));
+ boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(
+ "\r\n<body xmlns='http://jabber.org/protocol/httpbind'>"
+ "<bl"));
+ boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray(
+ "ah/>"
+ "</body>"));
+ connection->onDataRead(data1);
+ connection->onDataRead(data2);
+ CPPUNIT_ASSERT(dataRead.empty());
+ connection->onDataRead(data3);
+ CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
+ }
+
+ void testHTTPRequest() {
+ std::string data = "<blah/>";
+ std::string sid = "wigglebloom";
+ std::string fullBody = "<body xmlns='http://jabber.org/protocol/httpbind' sid='" + sid + "' rid='20'>" + data + "</body>";
+ std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 20, sid, URL());
+ CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second);
+ }
+
+ void testHTTPRequest_Empty() {
+ std::string data = "";
+ std::string sid = "wigglebloomsickle";
+ std::string fullBody = "<body rid='42' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'>" + data + "</body>";
+ std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 42, sid, URL());
+ CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second);
+ std::string response = safeByteArrayToString(http.first);
+ size_t bodyPosition = response.find("\r\n\r\n");
+ CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4));
+ }
+
+ private:
+
+ BOSHConnection::ref createTestling() {
+ resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1"));
+ Connector::ref connector = Connector::create("wonderland.lit", 5280, boost::optional<std::string>(), resolver, connectionFactory, timerFactory);
+ BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory, tlsContextFactory, TLSOptions());
+ c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1));
+ c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1));
+ c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1));
+ c->onSessionStarted.connect(boost::bind(&BOSHConnectionTest::handleSID, this, _1));
+ c->setRID(42);
+ return c;
+ }
+
+ void handleConnectFinished(bool error) {
+ connectFinished = true;
+ connectFinishedWithError = error;
+ }
+
+ void handleDisconnected(bool e) {
+ disconnected = true;
+ disconnectedError = e;
+ }
+
+ void handleDataRead(const SafeByteArray& d) {
+ append(dataRead, d);
+ }
+
+ void handleSID(const std::string& s) {
+ sid = s;
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) {
+ }
+
+ void listen() { assert(false); }
+
+ void connect(const HostAddressPort& address) {
+ hostAddressPort = address;
+ bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+
+ void disconnect() {
+ disconnected = true;
+ onDisconnected(boost::optional<Connection::Error>());
+ }
+
+ void write(const SafeByteArray& d) {
+ append(dataWritten, d);
+ }
+
+ EventLoop* eventLoop;
+ boost::optional<HostAddressPort> hostAddressPort;
+ std::vector<HostAddressPort> failingPorts;
+ ByteArray dataWritten;
+ bool disconnected;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop);
+ connections.push_back(connection);
+ return connection;
+ }
+
+ EventLoop* eventLoop;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ std::vector<HostAddressPort> failingPorts;
+ };
+
+ void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) {
+ boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
+ "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(data1);
+ boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size())));
+ connection->onDataRead(data2);
+ boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n"));
+ connection->onDataRead(data3);
+ boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response));
+ connection->onDataRead(data4);
+ }
+
+
+ private:
+ DummyEventLoop* eventLoop;
+ MockConnectionFactory* connectionFactory;
+ bool connectFinished;
+ bool connectFinishedWithError;
+ bool disconnected;
+ bool disconnectedError;
+ ByteArray dataRead;
+ PlatformXMLParserFactory parserFactory;
+ StaticDomainNameResolver* resolver;
+ TimerFactory* timerFactory;
+ TLSContextFactory* tlsContextFactory;
+ std::string sid;
};
diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
index 3bafbf1..9496e13 100644
--- a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
@@ -22,166 +22,166 @@
using namespace Swift;
class ChainedConnectorTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(ChainedConnectorTest);
- CPPUNIT_TEST(testConnect_FirstConnectorSucceeds);
- CPPUNIT_TEST(testConnect_SecondConnectorSucceeds);
- CPPUNIT_TEST(testConnect_NoConnectorSucceeds);
- CPPUNIT_TEST(testConnect_NoDNS);
- CPPUNIT_TEST(testStop);
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- error.reset();
- host = HostAddressPort(HostAddress("1.1.1.1"), 1234);
- eventLoop = new DummyEventLoop();
- resolver = new StaticDomainNameResolver(eventLoop);
- resolver->addXMPPClientService("foo.com", host);
- connectionFactory1 = new MockConnectionFactory(eventLoop, 1);
- connectionFactory2 = new MockConnectionFactory(eventLoop, 2);
- timerFactory = new DummyTimerFactory();
- }
-
- void tearDown() {
- delete timerFactory;
- delete connectionFactory2;
- delete connectionFactory1;
- delete resolver;
- delete eventLoop;
- }
-
- void testConnect_FirstConnectorSucceeds() {
- boost::shared_ptr<ChainedConnector> testling(createConnector());
- connectionFactory1->connects = true;
- connectionFactory2->connects = false;
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT_EQUAL(1, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_SecondConnectorSucceeds() {
- boost::shared_ptr<ChainedConnector> testling(createConnector());
- connectionFactory1->connects = false;
- connectionFactory2->connects = true;
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT_EQUAL(2, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoConnectorSucceeds() {
- boost::shared_ptr<ChainedConnector> testling(createConnector());
- connectionFactory1->connects = false;
- connectionFactory2->connects = false;
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoDNS() {
- /* Reset resolver so there's no record */
- delete resolver;
- resolver = new StaticDomainNameResolver(eventLoop);
- boost::shared_ptr<ChainedConnector> testling(createConnector());
- connectionFactory1->connects = false;
- connectionFactory2->connects = false;
-
- testling->start();
- //testling->stop();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testStop() {
- boost::shared_ptr<ChainedConnector> testling(createConnector());
- connectionFactory1->connects = true;
- connectionFactory2->connects = false;
-
- testling->start();
- testling->stop();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- }
-
- private:
- boost::shared_ptr<ChainedConnector> createConnector() {
- std::vector<ConnectionFactory*> factories;
- factories.push_back(connectionFactory1);
- factories.push_back(connectionFactory2);
- boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", -1, boost::optional<std::string>("_xmpp-client._tcp."), resolver, factories, timerFactory);
- connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1, _2));
- return connector;
- }
-
- void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) {
- error = resultError;
- boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection));
- if (connection) {
- assert(c);
- }
- connections.push_back(c);
- }
-
- struct MockConnection : public Connection {
- public:
- MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) {
- }
-
- void listen() { assert(false); }
- void connect(const HostAddressPort&) {
- eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects));
- }
-
- HostAddressPort getLocalAddress() const { return HostAddressPort(); }
- HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
- void disconnect() { assert(false); }
- void write(const SafeByteArray&) { assert(false); }
-
- bool connects;
- int id;
- EventLoop* eventLoop;
- };
-
- struct MockConnectionFactory : public ConnectionFactory {
- MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) {
- }
-
- boost::shared_ptr<Connection> createConnection() {
- return boost::make_shared<MockConnection>(connects, id, eventLoop);
- }
-
- EventLoop* eventLoop;
- bool connects;
- int id;
- };
-
- private:
- HostAddressPort host;
- DummyEventLoop* eventLoop;
- StaticDomainNameResolver* resolver;
- MockConnectionFactory* connectionFactory1;
- MockConnectionFactory* connectionFactory2;
- DummyTimerFactory* timerFactory;
- std::vector< boost::shared_ptr<MockConnection> > connections;
- boost::shared_ptr<Error> error;
+ CPPUNIT_TEST_SUITE(ChainedConnectorTest);
+ CPPUNIT_TEST(testConnect_FirstConnectorSucceeds);
+ CPPUNIT_TEST(testConnect_SecondConnectorSucceeds);
+ CPPUNIT_TEST(testConnect_NoConnectorSucceeds);
+ CPPUNIT_TEST(testConnect_NoDNS);
+ CPPUNIT_TEST(testStop);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ error.reset();
+ host = HostAddressPort(HostAddress("1.1.1.1"), 1234);
+ eventLoop = new DummyEventLoop();
+ resolver = new StaticDomainNameResolver(eventLoop);
+ resolver->addXMPPClientService("foo.com", host);
+ connectionFactory1 = new MockConnectionFactory(eventLoop, 1);
+ connectionFactory2 = new MockConnectionFactory(eventLoop, 2);
+ timerFactory = new DummyTimerFactory();
+ }
+
+ void tearDown() {
+ delete timerFactory;
+ delete connectionFactory2;
+ delete connectionFactory1;
+ delete resolver;
+ delete eventLoop;
+ }
+
+ void testConnect_FirstConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = true;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT_EQUAL(1, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_SecondConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = false;
+ connectionFactory2->connects = true;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT_EQUAL(2, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = false;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoDNS() {
+ /* Reset resolver so there's no record */
+ delete resolver;
+ resolver = new StaticDomainNameResolver(eventLoop);
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = false;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ //testling->stop();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testStop() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = true;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ testling->stop();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ }
+
+ private:
+ boost::shared_ptr<ChainedConnector> createConnector() {
+ std::vector<ConnectionFactory*> factories;
+ factories.push_back(connectionFactory1);
+ factories.push_back(connectionFactory2);
+ boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", -1, boost::optional<std::string>("_xmpp-client._tcp."), resolver, factories, timerFactory);
+ connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1, _2));
+ return connector;
+ }
+
+ void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) {
+ error = resultError;
+ boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection));
+ if (connection) {
+ assert(c);
+ }
+ connections.push_back(c);
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) {
+ }
+
+ void listen() { assert(false); }
+ void connect(const HostAddressPort&) {
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects));
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+ void disconnect() { assert(false); }
+ void write(const SafeByteArray&) { assert(false); }
+
+ bool connects;
+ int id;
+ EventLoop* eventLoop;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ return boost::make_shared<MockConnection>(connects, id, eventLoop);
+ }
+
+ EventLoop* eventLoop;
+ bool connects;
+ int id;
+ };
+
+ private:
+ HostAddressPort host;
+ DummyEventLoop* eventLoop;
+ StaticDomainNameResolver* resolver;
+ MockConnectionFactory* connectionFactory1;
+ MockConnectionFactory* connectionFactory2;
+ DummyTimerFactory* timerFactory;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ boost::shared_ptr<Error> error;
};
CPPUNIT_TEST_SUITE_REGISTRATION(ChainedConnectorTest);
diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp
index a091074..ac2bc83 100644
--- a/Swiften/Network/UnitTest/ConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ConnectorTest.cpp
@@ -22,358 +22,358 @@
using namespace Swift;
class ConnectorTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(ConnectorTest);
- CPPUNIT_TEST(testConnect);
- CPPUNIT_TEST(testConnect_NoServiceLookups);
- CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort);
- CPPUNIT_TEST(testConnect_FirstAddressHostFails);
- CPPUNIT_TEST(testConnect_NoSRVHost);
- CPPUNIT_TEST(testConnect_NoHosts);
- CPPUNIT_TEST(testConnect_FirstSRVHostFails);
- CPPUNIT_TEST(testConnect_AllSRVHostsFailWithoutFallbackHost);
- CPPUNIT_TEST(testConnect_AllSRVHostsFailWithFallbackHost);
- CPPUNIT_TEST(testConnect_SRVAndFallbackHostsFail);
- //CPPUNIT_TEST(testConnect_TimeoutDuringResolve);
- CPPUNIT_TEST(testConnect_TimeoutDuringConnectToOnlyCandidate);
- CPPUNIT_TEST(testConnect_TimeoutDuringConnectToCandidateFallsBack);
- CPPUNIT_TEST(testConnect_NoTimeout);
- CPPUNIT_TEST(testStop_DuringSRVQuery);
- CPPUNIT_TEST(testStop_Timeout);
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- host1 = HostAddressPort(HostAddress("1.1.1.1"), 1234);
- host2 = HostAddressPort(HostAddress("2.2.2.2"), 2345);
- host3 = HostAddressPort(HostAddress("3.3.3.3"), 5222);
- eventLoop = new DummyEventLoop();
- resolver = new StaticDomainNameResolver(eventLoop);
- connectionFactory = new MockConnectionFactory(eventLoop);
- timerFactory = new DummyTimerFactory();
- }
-
- void tearDown() {
- delete timerFactory;
- delete connectionFactory;
- delete resolver;
- delete eventLoop;
- }
-
- void testConnect() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- resolver->addAddress("foo.com", host3.getAddress());
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(host1 == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoServiceLookups() {
- Connector::ref testling(createConnector(4321, boost::optional<std::string>()));
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- resolver->addAddress("foo.com", host3.getAddress());
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
- CPPUNIT_ASSERT(4321 == (*(connections[0]->hostAddressPort)).getPort());
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoServiceLookups_DefaultPort() {
- Connector::ref testling(createConnector(-1, boost::optional<std::string>()));
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- resolver->addAddress("foo.com", host3.getAddress());
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
- CPPUNIT_ASSERT_EQUAL(5222, (*(connections[0]->hostAddressPort)).getPort());
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoSRVHost() {
- Connector::ref testling(createConnector());
- resolver->addAddress("foo.com", host3.getAddress());
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_FirstAddressHostFails() {
- Connector::ref testling(createConnector());
-
- HostAddress address1("1.1.1.1");
- HostAddress address2("2.2.2.2");
- resolver->addXMPPClientService("foo.com", "host-foo.com", 1234);
- resolver->addAddress("host-foo.com", address1);
- resolver->addAddress("host-foo.com", address2);
- connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234));
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_NoHosts() {
- Connector::ref testling(createConnector());
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_FirstSRVHostFails() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- connectionFactory->failingPorts.push_back(host1);
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(host2 == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_AllSRVHostsFailWithoutFallbackHost() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- connectionFactory->failingPorts.push_back(host1);
- connectionFactory->failingPorts.push_back(host2);
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_AllSRVHostsFailWithFallbackHost() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addXMPPClientService("foo.com", host2);
- resolver->addAddress("foo.com", host3.getAddress());
- connectionFactory->failingPorts.push_back(host1);
- connectionFactory->failingPorts.push_back(host2);
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_SRVAndFallbackHostsFail() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
- resolver->addAddress("foo.com", host3.getAddress());
- connectionFactory->failingPorts.push_back(host1);
- connectionFactory->failingPorts.push_back(host3);
-
- testling->start();
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- /*void testConnect_TimeoutDuringResolve() {
- Connector::ref testling(createConnector());
- testling->setTimeoutMilliseconds(10);
- resolver->setIsResponsive(false);
-
- testling->start();
- eventLoop->processEvents();
- timerFactory->setTime(10);
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- CPPUNIT_ASSERT(!connections[0]);
- }*/
-
- void testConnect_TimeoutDuringConnectToOnlyCandidate() {
- Connector::ref testling(createConnector());
- testling->setTimeoutMilliseconds(10);
- resolver->addXMPPClientService("foo.com", host1);
- connectionFactory->isResponsive = false;
-
- testling->start();
- eventLoop->processEvents();
- timerFactory->setTime(10);
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testConnect_TimeoutDuringConnectToCandidateFallsBack() {
- Connector::ref testling(createConnector());
- testling->setTimeoutMilliseconds(10);
-
- resolver->addXMPPClientService("foo.com", "host-foo.com", 1234);
- HostAddress address1("1.1.1.1");
- resolver->addAddress("host-foo.com", address1);
- HostAddress address2("2.2.2.2");
- resolver->addAddress("host-foo.com", address2);
-
- connectionFactory->isResponsive = false;
- testling->start();
- eventLoop->processEvents();
- connectionFactory->isResponsive = true;
- timerFactory->setTime(10);
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort));
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
-
- void testConnect_NoTimeout() {
- Connector::ref testling(createConnector());
- testling->setTimeoutMilliseconds(10);
- resolver->addXMPPClientService("foo.com", host1);
-
- testling->start();
- eventLoop->processEvents();
- timerFactory->setTime(10);
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(connections[0]);
- CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testStop_DuringSRVQuery() {
- Connector::ref testling(createConnector());
- resolver->addXMPPClientService("foo.com", host1);
-
- testling->start();
- testling->stop();
-
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
- }
-
- void testStop_Timeout() {
- Connector::ref testling(createConnector());
- testling->setTimeoutMilliseconds(10);
- resolver->addXMPPClientService("foo.com", host1);
-
- testling->start();
- testling->stop();
-
- eventLoop->processEvents();
- timerFactory->setTime(10);
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
- CPPUNIT_ASSERT(!connections[0]);
- }
-
-
- private:
- Connector::ref createConnector(int port = -1, boost::optional<std::string> serviceLookupPrefix = boost::optional<std::string>("_xmpp-client._tcp.")) {
- Connector::ref connector = Connector::create("foo.com", port, serviceLookupPrefix, resolver, connectionFactory, timerFactory);
- connector->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2));
- return connector;
- }
-
- void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) {
- boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection));
- if (connection) {
- assert(c);
- }
- connections.push_back(c);
- error = resultError;
- }
-
- struct MockConnection : public Connection {
- public:
- MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {}
-
- void listen() { assert(false); }
- void connect(const HostAddressPort& address) {
- hostAddressPort = address;
- if (isResponsive) {
- bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
- eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
- }
- }
-
- HostAddressPort getLocalAddress() const { return HostAddressPort(); }
- HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
- void disconnect() { assert(false); }
- void write(const SafeByteArray&) { assert(false); }
-
- EventLoop* eventLoop;
- boost::optional<HostAddressPort> hostAddressPort;
- std::vector<HostAddressPort> failingPorts;
- bool isResponsive;
- };
-
- struct MockConnectionFactory : public ConnectionFactory {
- MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) {
- }
-
- boost::shared_ptr<Connection> createConnection() {
- return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop));
- }
-
- EventLoop* eventLoop;
- bool isResponsive;
- std::vector<HostAddressPort> failingPorts;
- };
-
- private:
- HostAddressPort host1;
- HostAddressPort host2;
- HostAddressPort host3;
- DummyEventLoop* eventLoop;
- StaticDomainNameResolver* resolver;
- MockConnectionFactory* connectionFactory;
- DummyTimerFactory* timerFactory;
- std::vector< boost::shared_ptr<MockConnection> > connections;
- boost::shared_ptr<Error> error;
+ CPPUNIT_TEST_SUITE(ConnectorTest);
+ CPPUNIT_TEST(testConnect);
+ CPPUNIT_TEST(testConnect_NoServiceLookups);
+ CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort);
+ CPPUNIT_TEST(testConnect_FirstAddressHostFails);
+ CPPUNIT_TEST(testConnect_NoSRVHost);
+ CPPUNIT_TEST(testConnect_NoHosts);
+ CPPUNIT_TEST(testConnect_FirstSRVHostFails);
+ CPPUNIT_TEST(testConnect_AllSRVHostsFailWithoutFallbackHost);
+ CPPUNIT_TEST(testConnect_AllSRVHostsFailWithFallbackHost);
+ CPPUNIT_TEST(testConnect_SRVAndFallbackHostsFail);
+ //CPPUNIT_TEST(testConnect_TimeoutDuringResolve);
+ CPPUNIT_TEST(testConnect_TimeoutDuringConnectToOnlyCandidate);
+ CPPUNIT_TEST(testConnect_TimeoutDuringConnectToCandidateFallsBack);
+ CPPUNIT_TEST(testConnect_NoTimeout);
+ CPPUNIT_TEST(testStop_DuringSRVQuery);
+ CPPUNIT_TEST(testStop_Timeout);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ host1 = HostAddressPort(HostAddress("1.1.1.1"), 1234);
+ host2 = HostAddressPort(HostAddress("2.2.2.2"), 2345);
+ host3 = HostAddressPort(HostAddress("3.3.3.3"), 5222);
+ eventLoop = new DummyEventLoop();
+ resolver = new StaticDomainNameResolver(eventLoop);
+ connectionFactory = new MockConnectionFactory(eventLoop);
+ timerFactory = new DummyTimerFactory();
+ }
+
+ void tearDown() {
+ delete timerFactory;
+ delete connectionFactory;
+ delete resolver;
+ delete eventLoop;
+ }
+
+ void testConnect() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ resolver->addAddress("foo.com", host3.getAddress());
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(host1 == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoServiceLookups() {
+ Connector::ref testling(createConnector(4321, boost::optional<std::string>()));
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ resolver->addAddress("foo.com", host3.getAddress());
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
+ CPPUNIT_ASSERT(4321 == (*(connections[0]->hostAddressPort)).getPort());
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoServiceLookups_DefaultPort() {
+ Connector::ref testling(createConnector(-1, boost::optional<std::string>()));
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ resolver->addAddress("foo.com", host3.getAddress());
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress());
+ CPPUNIT_ASSERT_EQUAL(5222, (*(connections[0]->hostAddressPort)).getPort());
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoSRVHost() {
+ Connector::ref testling(createConnector());
+ resolver->addAddress("foo.com", host3.getAddress());
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_FirstAddressHostFails() {
+ Connector::ref testling(createConnector());
+
+ HostAddress address1("1.1.1.1");
+ HostAddress address2("2.2.2.2");
+ resolver->addXMPPClientService("foo.com", "host-foo.com", 1234);
+ resolver->addAddress("host-foo.com", address1);
+ resolver->addAddress("host-foo.com", address2);
+ connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234));
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_NoHosts() {
+ Connector::ref testling(createConnector());
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_FirstSRVHostFails() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ connectionFactory->failingPorts.push_back(host1);
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(host2 == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_AllSRVHostsFailWithoutFallbackHost() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ connectionFactory->failingPorts.push_back(host1);
+ connectionFactory->failingPorts.push_back(host2);
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_AllSRVHostsFailWithFallbackHost() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addXMPPClientService("foo.com", host2);
+ resolver->addAddress("foo.com", host3.getAddress());
+ connectionFactory->failingPorts.push_back(host1);
+ connectionFactory->failingPorts.push_back(host2);
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_SRVAndFallbackHostsFail() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+ resolver->addAddress("foo.com", host3.getAddress());
+ connectionFactory->failingPorts.push_back(host1);
+ connectionFactory->failingPorts.push_back(host3);
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ /*void testConnect_TimeoutDuringResolve() {
+ Connector::ref testling(createConnector());
+ testling->setTimeoutMilliseconds(10);
+ resolver->setIsResponsive(false);
+
+ testling->start();
+ eventLoop->processEvents();
+ timerFactory->setTime(10);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ CPPUNIT_ASSERT(!connections[0]);
+ }*/
+
+ void testConnect_TimeoutDuringConnectToOnlyCandidate() {
+ Connector::ref testling(createConnector());
+ testling->setTimeoutMilliseconds(10);
+ resolver->addXMPPClientService("foo.com", host1);
+ connectionFactory->isResponsive = false;
+
+ testling->start();
+ eventLoop->processEvents();
+ timerFactory->setTime(10);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testConnect_TimeoutDuringConnectToCandidateFallsBack() {
+ Connector::ref testling(createConnector());
+ testling->setTimeoutMilliseconds(10);
+
+ resolver->addXMPPClientService("foo.com", "host-foo.com", 1234);
+ HostAddress address1("1.1.1.1");
+ resolver->addAddress("host-foo.com", address1);
+ HostAddress address2("2.2.2.2");
+ resolver->addAddress("host-foo.com", address2);
+
+ connectionFactory->isResponsive = false;
+ testling->start();
+ eventLoop->processEvents();
+ connectionFactory->isResponsive = true;
+ timerFactory->setTime(10);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort));
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+
+ void testConnect_NoTimeout() {
+ Connector::ref testling(createConnector());
+ testling->setTimeoutMilliseconds(10);
+ resolver->addXMPPClientService("foo.com", host1);
+
+ testling->start();
+ eventLoop->processEvents();
+ timerFactory->setTime(10);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testStop_DuringSRVQuery() {
+ Connector::ref testling(createConnector());
+ resolver->addXMPPClientService("foo.com", host1);
+
+ testling->start();
+ testling->stop();
+
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error));
+ }
+
+ void testStop_Timeout() {
+ Connector::ref testling(createConnector());
+ testling->setTimeoutMilliseconds(10);
+ resolver->addXMPPClientService("foo.com", host1);
+
+ testling->start();
+ testling->stop();
+
+ eventLoop->processEvents();
+ timerFactory->setTime(10);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ }
+
+
+ private:
+ Connector::ref createConnector(int port = -1, boost::optional<std::string> serviceLookupPrefix = boost::optional<std::string>("_xmpp-client._tcp.")) {
+ Connector::ref connector = Connector::create("foo.com", port, serviceLookupPrefix, resolver, connectionFactory, timerFactory);
+ connector->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2));
+ return connector;
+ }
+
+ void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) {
+ boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection));
+ if (connection) {
+ assert(c);
+ }
+ connections.push_back(c);
+ error = resultError;
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {}
+
+ void listen() { assert(false); }
+ void connect(const HostAddressPort& address) {
+ hostAddressPort = address;
+ if (isResponsive) {
+ bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
+ }
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+ void disconnect() { assert(false); }
+ void write(const SafeByteArray&) { assert(false); }
+
+ EventLoop* eventLoop;
+ boost::optional<HostAddressPort> hostAddressPort;
+ std::vector<HostAddressPort> failingPorts;
+ bool isResponsive;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop));
+ }
+
+ EventLoop* eventLoop;
+ bool isResponsive;
+ std::vector<HostAddressPort> failingPorts;
+ };
+
+ private:
+ HostAddressPort host1;
+ HostAddressPort host2;
+ HostAddressPort host3;
+ DummyEventLoop* eventLoop;
+ StaticDomainNameResolver* resolver;
+ MockConnectionFactory* connectionFactory;
+ DummyTimerFactory* timerFactory;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ boost::shared_ptr<Error> error;
};
diff --git a/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp b/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp
index d5cef84..7042b27 100644
--- a/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp
+++ b/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp
@@ -15,67 +15,67 @@
using namespace Swift;
namespace {
- struct RandomGenerator1 : public RandomGenerator {
- virtual int generateRandomInteger(int) {
- return 0;
- }
- };
+ struct RandomGenerator1 : public RandomGenerator {
+ virtual int generateRandomInteger(int) {
+ return 0;
+ }
+ };
- struct RandomGenerator2 : public RandomGenerator {
- virtual int generateRandomInteger(int i) {
- return i;
- }
- };
+ struct RandomGenerator2 : public RandomGenerator {
+ virtual int generateRandomInteger(int i) {
+ return i;
+ }
+ };
}
class DomainNameServiceQueryTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(DomainNameServiceQueryTest);
- CPPUNIT_TEST(testSortResults_Random1);
- CPPUNIT_TEST(testSortResults_Random2);
- CPPUNIT_TEST_SUITE_END();
+ CPPUNIT_TEST_SUITE(DomainNameServiceQueryTest);
+ CPPUNIT_TEST(testSortResults_Random1);
+ CPPUNIT_TEST(testSortResults_Random2);
+ CPPUNIT_TEST_SUITE_END();
- public:
- void testSortResults_Random1() {
- std::vector<DomainNameServiceQuery::Result> results;
- results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1));
- results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10));
- results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1));
- results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20));
- results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1));
- results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10));
+ public:
+ void testSortResults_Random1() {
+ std::vector<DomainNameServiceQuery::Result> results;
+ results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1));
+ results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10));
+ results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1));
+ results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20));
+ results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1));
+ results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10));
- RandomGenerator1 generator;
- DomainNameServiceQuery::sortResults(results, generator);
+ RandomGenerator1 generator;
+ DomainNameServiceQuery::sortResults(results, generator);
- CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[1].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[2].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[3].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[4].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[5].hostname);
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[1].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[2].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[3].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[4].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[5].hostname);
+ }
- void testSortResults_Random2() {
- std::vector<DomainNameServiceQuery::Result> results;
- results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1));
- results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10));
- results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1));
- results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20));
- results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1));
- results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10));
- results.push_back(DomainNameServiceQuery::Result("server7.com", 5222, 3, 40));
+ void testSortResults_Random2() {
+ std::vector<DomainNameServiceQuery::Result> results;
+ results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1));
+ results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10));
+ results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1));
+ results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20));
+ results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1));
+ results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10));
+ results.push_back(DomainNameServiceQuery::Result("server7.com", 5222, 3, 40));
- RandomGenerator2 generator;
- DomainNameServiceQuery::sortResults(results, generator);
+ RandomGenerator2 generator;
+ DomainNameServiceQuery::sortResults(results, generator);
- CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server7.com"), results[1].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[2].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[3].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[4].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[5].hostname);
- CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[6].hostname);
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server7.com"), results[1].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[2].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[3].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[4].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[5].hostname);
+ CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[6].hostname);
+ }
};
diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
index 1d01214..aa3d578 100644
--- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
@@ -31,409 +31,409 @@
using namespace Swift;
namespace {
- class ExampleHTTPTrafficFilter : public HTTPTrafficFilter {
- public:
- ExampleHTTPTrafficFilter() {}
- virtual ~ExampleHTTPTrafficFilter() {}
-
- virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& /* statusLine */, const std::vector<std::pair<std::string, std::string> >& response) {
- filterResponses.push_back(response);
- SWIFT_LOG(debug) << std::endl;
- return filterResponseReturn;
- }
-
- std::vector<std::vector<std::pair<std::string, std::string> > > filterResponses;
-
- std::vector<std::pair<std::string, std::string> > filterResponseReturn;
- };
-
- class ProxyAuthenticationHTTPTrafficFilter : public HTTPTrafficFilter {
- static std::string to_lower(const std::string& str) {
- std::string lower = str;
- boost::algorithm::to_lower(lower);
- return lower;
- }
-
- public:
- ProxyAuthenticationHTTPTrafficFilter() {}
- virtual ~ProxyAuthenticationHTTPTrafficFilter() {}
-
- virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& response) {
- std::vector<std::pair<std::string, std::string> > filterResponseReturn;
- std::vector<std::string> statusLineFields;
- boost::split(statusLineFields, statusLine, boost::is_any_of(" "), boost::token_compress_on);
-
- int statusCode = boost::lexical_cast<int>(statusLineFields[1]);
- if (statusCode == 407) {
- typedef std::pair<std::string, std::string> StrPair;
- foreach (const StrPair& field, response) {
- if (to_lower(field.first) == to_lower("Proxy-Authenticate")) {
- if (field.second.size() >= 6 && field.second.substr(0, 6) == " NTLM ") {
- filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig=="));
- return filterResponseReturn;
- }
- else if (field.second.size() >= 5 && field.second.substr(0, 5) == " NTLM") {
- filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA=="));
- return filterResponseReturn;
- }
- }
- }
-
- return filterResponseReturn;
- }
- else {
- return std::vector<std::pair<std::string, std::string> >();
- }
- }
- };
+ class ExampleHTTPTrafficFilter : public HTTPTrafficFilter {
+ public:
+ ExampleHTTPTrafficFilter() {}
+ virtual ~ExampleHTTPTrafficFilter() {}
+
+ virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& /* statusLine */, const std::vector<std::pair<std::string, std::string> >& response) {
+ filterResponses.push_back(response);
+ SWIFT_LOG(debug) << std::endl;
+ return filterResponseReturn;
+ }
+
+ std::vector<std::vector<std::pair<std::string, std::string> > > filterResponses;
+
+ std::vector<std::pair<std::string, std::string> > filterResponseReturn;
+ };
+
+ class ProxyAuthenticationHTTPTrafficFilter : public HTTPTrafficFilter {
+ static std::string to_lower(const std::string& str) {
+ std::string lower = str;
+ boost::algorithm::to_lower(lower);
+ return lower;
+ }
+
+ public:
+ ProxyAuthenticationHTTPTrafficFilter() {}
+ virtual ~ProxyAuthenticationHTTPTrafficFilter() {}
+
+ virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& response) {
+ std::vector<std::pair<std::string, std::string> > filterResponseReturn;
+ std::vector<std::string> statusLineFields;
+ boost::split(statusLineFields, statusLine, boost::is_any_of(" "), boost::token_compress_on);
+
+ int statusCode = boost::lexical_cast<int>(statusLineFields[1]);
+ if (statusCode == 407) {
+ typedef std::pair<std::string, std::string> StrPair;
+ foreach (const StrPair& field, response) {
+ if (to_lower(field.first) == to_lower("Proxy-Authenticate")) {
+ if (field.second.size() >= 6 && field.second.substr(0, 6) == " NTLM ") {
+ filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig=="));
+ return filterResponseReturn;
+ }
+ else if (field.second.size() >= 5 && field.second.substr(0, 5) == " NTLM") {
+ filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA=="));
+ return filterResponseReturn;
+ }
+ }
+ }
+
+ return filterResponseReturn;
+ }
+ else {
+ return std::vector<std::pair<std::string, std::string> >();
+ }
+ }
+ };
}
class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest);
- CPPUNIT_TEST(testConnect_CreatesConnectionToProxy);
- CPPUNIT_TEST(testConnect_SendsConnectRequest);
- CPPUNIT_TEST(testConnect_ReceiveConnectResponse);
- CPPUNIT_TEST(testConnect_ReceiveConnectChunkedResponse);
- CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse);
- CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse);
- CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect);
- CPPUNIT_TEST(testWrite_AfterConnect);
- CPPUNIT_TEST(testDisconnect_AfterConnectRequest);
- CPPUNIT_TEST(testDisconnect_AfterConnect);
- CPPUNIT_TEST(testTrafficFilter);
- CPPUNIT_TEST(testTrafficFilterNoConnectionReuse);
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- proxyHost = "doo.bah";
- proxyPort = 1234;
- proxyHostAddress = HostAddressPort(HostAddress("1.1.1.1"), proxyPort);
- host = HostAddressPort(HostAddress("2.2.2.2"), 2345);
- eventLoop = new DummyEventLoop();
- resolver = new StaticDomainNameResolver(eventLoop);
- resolver->addAddress(proxyHost, proxyHostAddress.getAddress());
- timerFactory = new DummyTimerFactory();
- connectionFactory = new MockConnectionFactory(eventLoop);
- connectFinished = false;
- connectFinishedWithError = false;
- disconnected = false;
- }
-
- void tearDown() {
- delete timerFactory;
- delete connectionFactory;
- delete resolver;
- delete eventLoop;
- }
-
- void connect(HTTPConnectProxiedConnection::ref connection, const HostAddressPort& to) {
- connection->connect(to);
- eventLoop->processEvents();
- eventLoop->processEvents();
- eventLoop->processEvents();
- }
-
- void testConnect_CreatesConnectionToProxy() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
-
- connect(testling, host);
-
- CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size()));
- CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort);
- CPPUNIT_ASSERT(proxyHostAddress == *connectionFactory->connections[0]->hostAddressPort);
- CPPUNIT_ASSERT(!connectFinished);
- }
-
- void testConnect_SendsConnectRequest() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
-
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten);
- }
-
- void testConnect_ReceiveConnectResponse() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT(connectFinished);
- CPPUNIT_ASSERT(!connectFinishedWithError);
- CPPUNIT_ASSERT(dataRead.empty());
- }
-
- void testConnect_ReceiveConnectChunkedResponse() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 "));
- eventLoop->processEvents();
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("200 Connection established\r\n\r\n"));
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT(connectFinished);
- CPPUNIT_ASSERT(!connectFinishedWithError);
- CPPUNIT_ASSERT(dataRead.empty());
- }
-
-
- void testConnect_ReceiveMalformedConnectResponse() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP"));
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT(connectFinished);
- CPPUNIT_ASSERT(connectFinishedWithError);
- CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
- }
-
- void testConnect_ReceiveErrorConnectResponse() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 401 Unauthorized\r\n\r\n"));
- eventLoop->processEvents();
-
- CPPUNIT_ASSERT(connectFinished);
- CPPUNIT_ASSERT(connectFinishedWithError);
- CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
- }
+ CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest);
+ CPPUNIT_TEST(testConnect_CreatesConnectionToProxy);
+ CPPUNIT_TEST(testConnect_SendsConnectRequest);
+ CPPUNIT_TEST(testConnect_ReceiveConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveConnectChunkedResponse);
+ CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect);
+ CPPUNIT_TEST(testWrite_AfterConnect);
+ CPPUNIT_TEST(testDisconnect_AfterConnectRequest);
+ CPPUNIT_TEST(testDisconnect_AfterConnect);
+ CPPUNIT_TEST(testTrafficFilter);
+ CPPUNIT_TEST(testTrafficFilterNoConnectionReuse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ proxyHost = "doo.bah";
+ proxyPort = 1234;
+ proxyHostAddress = HostAddressPort(HostAddress("1.1.1.1"), proxyPort);
+ host = HostAddressPort(HostAddress("2.2.2.2"), 2345);
+ eventLoop = new DummyEventLoop();
+ resolver = new StaticDomainNameResolver(eventLoop);
+ resolver->addAddress(proxyHost, proxyHostAddress.getAddress());
+ timerFactory = new DummyTimerFactory();
+ connectionFactory = new MockConnectionFactory(eventLoop);
+ connectFinished = false;
+ connectFinishedWithError = false;
+ disconnected = false;
+ }
+
+ void tearDown() {
+ delete timerFactory;
+ delete connectionFactory;
+ delete resolver;
+ delete eventLoop;
+ }
+
+ void connect(HTTPConnectProxiedConnection::ref connection, const HostAddressPort& to) {
+ connection->connect(to);
+ eventLoop->processEvents();
+ eventLoop->processEvents();
+ eventLoop->processEvents();
+ }
+
+ void testConnect_CreatesConnectionToProxy() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+
+ connect(testling, host);
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size()));
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort);
+ CPPUNIT_ASSERT(proxyHostAddress == *connectionFactory->connections[0]->hostAddressPort);
+ CPPUNIT_ASSERT(!connectFinished);
+ }
+
+ void testConnect_SendsConnectRequest() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten);
+ }
+
+ void testConnect_ReceiveConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(!connectFinishedWithError);
+ CPPUNIT_ASSERT(dataRead.empty());
+ }
+
+ void testConnect_ReceiveConnectChunkedResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 "));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(!connectFinishedWithError);
+ CPPUNIT_ASSERT(dataRead.empty());
+ }
+
+
+ void testConnect_ReceiveMalformedConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(connectFinishedWithError);
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ }
+
+ void testConnect_ReceiveErrorConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 401 Unauthorized\r\n\r\n"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(connectFinishedWithError);
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ }
- void testConnect_ReceiveDataAfterConnect() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
- eventLoop->processEvents();
-
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("abcdef"));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead);
- }
+ void testConnect_ReceiveDataAfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("abcdef"));
+
+ CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead);
+ }
- void testWrite_AfterConnect() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
- eventLoop->processEvents();
- connectionFactory->connections[0]->dataWritten.clear();
+ void testWrite_AfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->dataWritten.clear();
- testling->write(createSafeByteArray("abcdef"));
+ testling->write(createSafeByteArray("abcdef"));
- CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten);
- }
+ CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten);
+ }
- void testDisconnect_AfterConnectRequest() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ void testDisconnect_AfterConnectRequest() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
- testling->disconnect();
+ testling->disconnect();
- CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
- CPPUNIT_ASSERT(disconnected);
- CPPUNIT_ASSERT(!disconnectedError);
- }
-
- void testDisconnect_AfterConnect() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
- eventLoop->processEvents();
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ CPPUNIT_ASSERT(disconnected);
+ CPPUNIT_ASSERT(!disconnectedError);
+ }
+
+ void testDisconnect_AfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
- testling->disconnect();
-
- CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
- CPPUNIT_ASSERT(disconnected);
- CPPUNIT_ASSERT(!disconnectedError);
- }
-
- void testTrafficFilter() {
- HTTPConnectProxiedConnection::ref testling(createTestling());
-
- boost::shared_ptr<ExampleHTTPTrafficFilter> httpTrafficFilter = boost::make_shared<ExampleHTTPTrafficFilter>();
-
- testling->setHTTPTrafficFilter(httpTrafficFilter);
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- // set a default response so the server response is answered by the traffic filter
- httpTrafficFilter->filterResponseReturn.clear();
- httpTrafficFilter->filterResponseReturn.push_back(std::pair<std::string, std::string>("Authorization", "Negotiate a87421000492aa874209af8bc028"));
-
- connectionFactory->connections[0]->dataWritten.clear();
-
- // test chunked response
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
- "HTTP/1.0 401 Unauthorized\r\n"));
- eventLoop->processEvents();
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
- "WWW-Authenticate: Negotiate\r\n"
- "\r\n"));
- eventLoop->processEvents();
-
-
- // verify that the traffic filter got called and answered with its response
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), httpTrafficFilter->filterResponses.size());
- CPPUNIT_ASSERT_EQUAL(std::string("WWW-Authenticate"), httpTrafficFilter->filterResponses[0][0].first);
-
- // remove the default response from the traffic filter
- httpTrafficFilter->filterResponseReturn.clear();
- eventLoop->processEvents();
-
- // verify that the traffic filter answer is send over the wire
- CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\nAuthorization: Negotiate a87421000492aa874209af8bc028\r\n\r\n"), connectionFactory->connections[1]->dataWritten);
-
- // verify that after without the default response, the traffic filter is skipped, authentication proceeds and traffic goes right through
- connectionFactory->connections[1]->dataWritten.clear();
- testling->write(createSafeByteArray("abcdef"));
- CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[1]->dataWritten);
- }
-
- void testTrafficFilterNoConnectionReuse() {
- HTTPConnectProxiedConnection::ref testling = createTestling();
-
- boost::shared_ptr<ProxyAuthenticationHTTPTrafficFilter> httpTrafficFilter = boost::make_shared<ProxyAuthenticationHTTPTrafficFilter>();
- testling->setHTTPTrafficFilter(httpTrafficFilter);
-
- connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
-
- // First HTTP CONNECT request assumes the proxy will work.
- CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
- "\r\n"), connectionFactory->connections[0]->dataWritten);
-
- // First reply presents initiator with authentication options.
- connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
- "HTTP/1.0 407 ProxyAuthentication Required\r\n"
- "proxy-Authenticate: Negotiate\r\n"
- "Proxy-Authenticate: Kerberos\r\n"
- "proxy-Authenticate: NTLM\r\n"
- "\r\n"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(false, connectFinished);
- CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
-
- // The HTTP proxy responds with code 407, so the traffic filter should inject the authentication response on a new connection.
- CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
- "Proxy-Authorization: NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA==\r\n"
- "\r\n"), connectionFactory->connections[1]->dataWritten);
-
- // The proxy responds with another authentication step.
- connectionFactory->connections[1]->onDataRead(createSafeByteArrayRef(
- "HTTP/1.0 407 ProxyAuthentication Required\r\n"
- "Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAA1goriluCDYHcYI/sAAAAAAAAAAFQAVABIAAAABQLODgAAAA9TAFAASQBSAEkAVAAxAEIAAgAQAFMAUABJAFIASQBUADEAQgABABAAUwBQAEkAUgBJAFQAMQBCAAQAEABzAHAAaQByAGkAdAAxAGIAAwAQAHMAcABpAHIAaQB0ADEAYgAAAAAA\r\n"
- "\r\n"));
- eventLoop->processEvents();
- CPPUNIT_ASSERT_EQUAL(false, connectFinished);
- CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
-
- // Last HTTP request that should succeed. Further traffic will go over the connection of this request.
- CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
- "Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig==\r\n"
- "\r\n"), connectionFactory->connections[2]->dataWritten);
-
- connectionFactory->connections[2]->onDataRead(createSafeByteArrayRef(
- "HTTP/1.0 200 OK\r\n"
- "\r\n"));
- eventLoop->processEvents();
-
- // The HTTP CONNECT proxy initialization finished without error.
- CPPUNIT_ASSERT_EQUAL(true, connectFinished);
- CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
-
- // Further traffic is written directly, without interception of the filter.
- connectionFactory->connections[2]->dataWritten.clear();
- testling->write(createSafeByteArray("This is some basic data traffic."));
- CPPUNIT_ASSERT_EQUAL(createByteArray("This is some basic data traffic."), connectionFactory->connections[2]->dataWritten);
- }
-
- private:
- HTTPConnectProxiedConnection::ref createTestling() {
- boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, "", "");
- c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1));
- c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1));
- c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1));
- return c;
- }
-
- void handleConnectFinished(bool error) {
- connectFinished = true;
- connectFinishedWithError = error;
- }
-
- void handleDisconnected(const boost::optional<Connection::Error>& e) {
- disconnected = true;
- disconnectedError = e;
- }
-
- void handleDataRead(boost::shared_ptr<SafeByteArray> d) {
- append(dataRead, *d);
- }
-
- struct MockConnection : public Connection {
- public:
- MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) {
- }
-
- void listen() { assert(false); }
-
- void connect(const HostAddressPort& address) {
- hostAddressPort = address;
- bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
- eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
- }
-
- HostAddressPort getLocalAddress() const { return HostAddressPort(); }
- HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
-
- void disconnect() {
- disconnected = true;
- onDisconnected(boost::optional<Connection::Error>());
- }
-
- void write(const SafeByteArray& d) {
- append(dataWritten, d);
- }
-
- EventLoop* eventLoop;
- boost::optional<HostAddressPort> hostAddressPort;
- std::vector<HostAddressPort> failingPorts;
- ByteArray dataWritten;
- bool disconnected;
- };
-
- struct MockConnectionFactory : public ConnectionFactory {
- MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
- }
-
- boost::shared_ptr<Connection> createConnection() {
- boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop);
- connections.push_back(connection);
- SWIFT_LOG(debug) << "new connection created" << std::endl;
- return connection;
- }
-
- EventLoop* eventLoop;
- std::vector< boost::shared_ptr<MockConnection> > connections;
- std::vector<HostAddressPort> failingPorts;
- };
-
- private:
- std::string proxyHost;
- HostAddressPort proxyHostAddress;
- int proxyPort;
- HostAddressPort host;
- DummyEventLoop* eventLoop;
- StaticDomainNameResolver* resolver;
- MockConnectionFactory* connectionFactory;
- TimerFactory* timerFactory;
- bool connectFinished;
- bool connectFinishedWithError;
- bool disconnected;
- boost::optional<Connection::Error> disconnectedError;
- ByteArray dataRead;
+ testling->disconnect();
+
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ CPPUNIT_ASSERT(disconnected);
+ CPPUNIT_ASSERT(!disconnectedError);
+ }
+
+ void testTrafficFilter() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+
+ boost::shared_ptr<ExampleHTTPTrafficFilter> httpTrafficFilter = boost::make_shared<ExampleHTTPTrafficFilter>();
+
+ testling->setHTTPTrafficFilter(httpTrafficFilter);
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ // set a default response so the server response is answered by the traffic filter
+ httpTrafficFilter->filterResponseReturn.clear();
+ httpTrafficFilter->filterResponseReturn.push_back(std::pair<std::string, std::string>("Authorization", "Negotiate a87421000492aa874209af8bc028"));
+
+ connectionFactory->connections[0]->dataWritten.clear();
+
+ // test chunked response
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
+ "HTTP/1.0 401 Unauthorized\r\n"));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
+ "WWW-Authenticate: Negotiate\r\n"
+ "\r\n"));
+ eventLoop->processEvents();
+
+
+ // verify that the traffic filter got called and answered with its response
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), httpTrafficFilter->filterResponses.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("WWW-Authenticate"), httpTrafficFilter->filterResponses[0][0].first);
+
+ // remove the default response from the traffic filter
+ httpTrafficFilter->filterResponseReturn.clear();
+ eventLoop->processEvents();
+
+ // verify that the traffic filter answer is send over the wire
+ CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\nAuthorization: Negotiate a87421000492aa874209af8bc028\r\n\r\n"), connectionFactory->connections[1]->dataWritten);
+
+ // verify that after without the default response, the traffic filter is skipped, authentication proceeds and traffic goes right through
+ connectionFactory->connections[1]->dataWritten.clear();
+ testling->write(createSafeByteArray("abcdef"));
+ CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[1]->dataWritten);
+ }
+
+ void testTrafficFilterNoConnectionReuse() {
+ HTTPConnectProxiedConnection::ref testling = createTestling();
+
+ boost::shared_ptr<ProxyAuthenticationHTTPTrafficFilter> httpTrafficFilter = boost::make_shared<ProxyAuthenticationHTTPTrafficFilter>();
+ testling->setHTTPTrafficFilter(httpTrafficFilter);
+
+ connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345));
+
+ // First HTTP CONNECT request assumes the proxy will work.
+ CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
+ "\r\n"), connectionFactory->connections[0]->dataWritten);
+
+ // First reply presents initiator with authentication options.
+ connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef(
+ "HTTP/1.0 407 ProxyAuthentication Required\r\n"
+ "proxy-Authenticate: Negotiate\r\n"
+ "Proxy-Authenticate: Kerberos\r\n"
+ "proxy-Authenticate: NTLM\r\n"
+ "\r\n"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(false, connectFinished);
+ CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
+
+ // The HTTP proxy responds with code 407, so the traffic filter should inject the authentication response on a new connection.
+ CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
+ "Proxy-Authorization: NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA==\r\n"
+ "\r\n"), connectionFactory->connections[1]->dataWritten);
+
+ // The proxy responds with another authentication step.
+ connectionFactory->connections[1]->onDataRead(createSafeByteArrayRef(
+ "HTTP/1.0 407 ProxyAuthentication Required\r\n"
+ "Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAA1goriluCDYHcYI/sAAAAAAAAAAFQAVABIAAAABQLODgAAAA9TAFAASQBSAEkAVAAxAEIAAgAQAFMAUABJAFIASQBUADEAQgABABAAUwBQAEkAUgBJAFQAMQBCAAQAEABzAHAAaQByAGkAdAAxAGIAAwAQAHMAcABpAHIAaQB0ADEAYgAAAAAA\r\n"
+ "\r\n"));
+ eventLoop->processEvents();
+ CPPUNIT_ASSERT_EQUAL(false, connectFinished);
+ CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
+
+ // Last HTTP request that should succeed. Further traffic will go over the connection of this request.
+ CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n"
+ "Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig==\r\n"
+ "\r\n"), connectionFactory->connections[2]->dataWritten);
+
+ connectionFactory->connections[2]->onDataRead(createSafeByteArrayRef(
+ "HTTP/1.0 200 OK\r\n"
+ "\r\n"));
+ eventLoop->processEvents();
+
+ // The HTTP CONNECT proxy initialization finished without error.
+ CPPUNIT_ASSERT_EQUAL(true, connectFinished);
+ CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError);
+
+ // Further traffic is written directly, without interception of the filter.
+ connectionFactory->connections[2]->dataWritten.clear();
+ testling->write(createSafeByteArray("This is some basic data traffic."));
+ CPPUNIT_ASSERT_EQUAL(createByteArray("This is some basic data traffic."), connectionFactory->connections[2]->dataWritten);
+ }
+
+ private:
+ HTTPConnectProxiedConnection::ref createTestling() {
+ boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, "", "");
+ c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1));
+ c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1));
+ c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1));
+ return c;
+ }
+
+ void handleConnectFinished(bool error) {
+ connectFinished = true;
+ connectFinishedWithError = error;
+ }
+
+ void handleDisconnected(const boost::optional<Connection::Error>& e) {
+ disconnected = true;
+ disconnectedError = e;
+ }
+
+ void handleDataRead(boost::shared_ptr<SafeByteArray> d) {
+ append(dataRead, *d);
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) {
+ }
+
+ void listen() { assert(false); }
+
+ void connect(const HostAddressPort& address) {
+ hostAddressPort = address;
+ bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+
+ void disconnect() {
+ disconnected = true;
+ onDisconnected(boost::optional<Connection::Error>());
+ }
+
+ void write(const SafeByteArray& d) {
+ append(dataWritten, d);
+ }
+
+ EventLoop* eventLoop;
+ boost::optional<HostAddressPort> hostAddressPort;
+ std::vector<HostAddressPort> failingPorts;
+ ByteArray dataWritten;
+ bool disconnected;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop);
+ connections.push_back(connection);
+ SWIFT_LOG(debug) << "new connection created" << std::endl;
+ return connection;
+ }
+
+ EventLoop* eventLoop;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ std::vector<HostAddressPort> failingPorts;
+ };
+
+ private:
+ std::string proxyHost;
+ HostAddressPort proxyHostAddress;
+ int proxyPort;
+ HostAddressPort host;
+ DummyEventLoop* eventLoop;
+ StaticDomainNameResolver* resolver;
+ MockConnectionFactory* connectionFactory;
+ TimerFactory* timerFactory;
+ bool connectFinished;
+ bool connectFinishedWithError;
+ bool disconnected;
+ boost::optional<Connection::Error> disconnectedError;
+ ByteArray dataRead;
};
CPPUNIT_TEST_SUITE_REGISTRATION(HTTPConnectProxiedConnectionTest);
diff --git a/Swiften/Network/UnitTest/HostAddressTest.cpp b/Swiften/Network/UnitTest/HostAddressTest.cpp
index 42fb108..aceb9be 100644
--- a/Swiften/Network/UnitTest/HostAddressTest.cpp
+++ b/Swiften/Network/UnitTest/HostAddressTest.cpp
@@ -14,54 +14,54 @@
using namespace Swift;
class HostAddressTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(HostAddressTest);
- CPPUNIT_TEST(testConstructor);
- CPPUNIT_TEST(testConstructor_Invalid);
- CPPUNIT_TEST(testConstructor_InvalidString);
- CPPUNIT_TEST(testToString);
- CPPUNIT_TEST(testToString_IPv6);
- CPPUNIT_TEST(testToString_Invalid);
- CPPUNIT_TEST_SUITE_END();
+ CPPUNIT_TEST_SUITE(HostAddressTest);
+ CPPUNIT_TEST(testConstructor);
+ CPPUNIT_TEST(testConstructor_Invalid);
+ CPPUNIT_TEST(testConstructor_InvalidString);
+ CPPUNIT_TEST(testToString);
+ CPPUNIT_TEST(testToString_IPv6);
+ CPPUNIT_TEST(testToString_Invalid);
+ CPPUNIT_TEST_SUITE_END();
- public:
- void testConstructor() {
- HostAddress testling("192.168.1.254");
+ public:
+ void testConstructor() {
+ HostAddress testling("192.168.1.254");
- CPPUNIT_ASSERT_EQUAL(std::string("192.168.1.254"), testling.toString());
- CPPUNIT_ASSERT(testling.isValid());
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("192.168.1.254"), testling.toString());
+ CPPUNIT_ASSERT(testling.isValid());
+ }
- void testConstructor_Invalid() {
- HostAddress testling;
+ void testConstructor_Invalid() {
+ HostAddress testling;
- CPPUNIT_ASSERT(!testling.isValid());
- }
+ CPPUNIT_ASSERT(!testling.isValid());
+ }
- void testConstructor_InvalidString() {
- HostAddress testling("invalid");
+ void testConstructor_InvalidString() {
+ HostAddress testling("invalid");
- CPPUNIT_ASSERT(!testling.isValid());
- }
+ CPPUNIT_ASSERT(!testling.isValid());
+ }
- void testToString() {
- unsigned char address[4] = {10, 0, 1, 253};
- HostAddress testling(address, 4);
+ void testToString() {
+ unsigned char address[4] = {10, 0, 1, 253};
+ HostAddress testling(address, 4);
- CPPUNIT_ASSERT_EQUAL(std::string("10.0.1.253"), testling.toString());
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("10.0.1.253"), testling.toString());
+ }
- void testToString_IPv6() {
- unsigned char address[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17};
- HostAddress testling(address, 16);
+ void testToString_IPv6() {
+ unsigned char address[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17};
+ HostAddress testling(address, 16);
- CPPUNIT_ASSERT_EQUAL(std::string("102:304:506:708:90a:b0c:d0e:f11"), testling.toString());
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("102:304:506:708:90a:b0c:d0e:f11"), testling.toString());
+ }
- void testToString_Invalid() {
- HostAddress testling;
+ void testToString_Invalid() {
+ HostAddress testling;
- CPPUNIT_ASSERT_EQUAL(std::string("0.0.0.0"), testling.toString());
- }
+ CPPUNIT_ASSERT_EQUAL(std::string("0.0.0.0"), testling.toString());
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(HostAddressTest);