diff options
Diffstat (limited to 'Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp')
| -rw-r--r-- | Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp | 246 | 
1 files changed, 246 insertions, 0 deletions
| diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp new file mode 100644 index 0000000..48189ab --- /dev/null +++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <boost/optional.hpp> +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HTTPConnectProxiedConnection.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/DummyEventLoop.h> + +using namespace Swift; + +class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest); +		CPPUNIT_TEST(testConnect_CreatesConnectionToProxy); +		CPPUNIT_TEST(testConnect_SendsConnectRequest); +		CPPUNIT_TEST(testConnect_ReceiveConnectResponse); +		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_SUITE_END(); + +	public: +		void setUp() { +			proxyHost = HostAddressPort(HostAddress("1.1.1.1"), 1234); +			host = HostAddressPort(HostAddress("2.2.2.2"), 2345); +			eventLoop = new DummyEventLoop(); +			connectionFactory = new MockConnectionFactory(eventLoop); +			connectFinished = false; +			disconnected = false; +		} + +		void tearDown() { +			delete connectionFactory; +			delete eventLoop; +		} + +		void testConnect_CreatesConnectionToProxy() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); + +			testling->connect(host); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size())); +			CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort); +			CPPUNIT_ASSERT(proxyHost == *connectionFactory->connections[0]->hostAddressPort); +			CPPUNIT_ASSERT(!connectFinished); +		} + +		void testConnect_SendsConnectRequest() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); + +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			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()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 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()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("FLOOP")); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(connectFinished); +			CPPUNIT_ASSERT(connectFinishedWithError); +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +		} + +		void testConnect_ReceiveErrorConnectResponse() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("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()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); + +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("abcdef")); + +			CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead); +		} + +		void testWrite_AfterConnect() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("HTTP/1.0 200 Connection established\r\n\r\n")); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->dataWritten.clear(); + +			testling->write(createSafeByteArray("abcdef")); + +			CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten); +		} + +		void testDisconnect_AfterConnectRequest() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); + +			testling->disconnect(); + +			CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); +			CPPUNIT_ASSERT(disconnected); +			CPPUNIT_ASSERT(!disconnectedError); +		} + +		void testDisconnect_AfterConnect() { +			HTTPConnectProxiedConnection::ref testling(createTestling()); +			testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345)); +			eventLoop->processEvents(); +			connectionFactory->connections[0]->onDataRead(createSafeByteArray("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); +		} + +	private: +		HTTPConnectProxiedConnection::ref createTestling() { +			boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(connectionFactory, proxyHost); +			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(const 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(); } + +				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; +		}; + +	private: +		HostAddressPort proxyHost; +		HostAddressPort host; +		DummyEventLoop* eventLoop; +		MockConnectionFactory* connectionFactory; +		std::vector< boost::shared_ptr<MockConnection> > connections; +		bool connectFinished; +		bool connectFinishedWithError; +		bool disconnected; +		boost::optional<Connection::Error> disconnectedError; +		ByteArray dataRead; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(HTTPConnectProxiedConnectionTest); | 
 Swift
 Swift