diff options
Diffstat (limited to 'Swiften/FileTransfer/UnitTest')
8 files changed, 1525 insertions, 1296 deletions
diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h index 26adb05..6119658 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h @@ -4,46 +4,52 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> -#include <boost/filesystem/path.hpp> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> -#include <Swiften/Base/Override.h> #include <Swiften/FileTransfer/FileTransferManager.h> namespace Swift { - class S5BProxyRequest; - class FileTransferOptions; - - class DummyFileTransferManager : public FileTransferManager { - public: - DummyFileTransferManager() : FileTransferManager() { - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const boost::filesystem::path&, - const std::string&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const std::string&, - const std::string&, - const boost::uintmax_t, - const boost::posix_time::ptime&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual void addS5BProxy(boost::shared_ptr<S5BProxyRequest>) { - } - - }; + class S5BProxyRequest; + class FileTransferOptions; + + class DummyFileTransferManager : public FileTransferManager { + public: + DummyFileTransferManager() : FileTransferManager() { + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const boost::filesystem::path&, + const std::string&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) override { + return OutgoingFileTransfer::ref(); + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const std::string&, + const std::string&, + const boost::uintmax_t, + const boost::posix_time::ptime&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) override { + return OutgoingFileTransfer::ref(); + } + + virtual void addS5BProxy(std::shared_ptr<S5BProxyRequest>) { + } + + }; } diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h new file mode 100644 index 0000000..5db3368 --- /dev/null +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/IBBReceiveTransportSession.h> +#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/IBBSendTransportSession.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/JID/JID.h> +#include <Swiften/StringCodecs/Hexify.h> + +namespace Swift { + +class DummyFileTransferTransporter : public FileTransferTransporter { +public: + enum Role { + Initiator, + Responder + }; + +public: + DummyFileTransferTransporter( + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* /* s5bServerManager */, + SOCKS5BytestreamProxiesManager* /* s5bProxy */, + IDGenerator* /* idGenerator */, + ConnectionFactory*, + TimerFactory*, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter, + const FileTransferOptions& ftOptions) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter), ftOptions_(ftOptions) { + + } + + void initialize() { + s5bSessionID_ = s5bRegistry_->generateSessionID(); + } + + virtual void startGeneratingLocalCandidates() { + std::vector<JingleS5BTransportPayload::Candidate> candidates; + if (ftOptions_.isDirectAllowed()) { + JingleS5BTransportPayload::Candidate candidate; + candidate.cid = "123"; + candidate.priority = 1235; + candidates.push_back(candidate); + } + onLocalCandidatesGenerated(s5bSessionID_, candidates, getSOCKS5DstAddr()); + } + + virtual void stopGeneratingLocalCandidates() { + } + + virtual void addRemoteCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) { + } + + virtual void startTryingRemoteCandidates() { + onRemoteCandidateSelectFinished(s5bSessionID_, boost::optional<JingleS5BTransportPayload::Candidate>()); + } + + virtual void stopTryingRemoteCandidates() { + } + + virtual void startActivatingProxy(const JID& /* proxy */) { + } + + virtual void stopActivatingProxy() { + } + + virtual std::shared_ptr<TransportSession> createIBBSendSession(const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream> stream) { + std::shared_ptr<IBBSendSession> ibbSession = std::make_shared<IBBSendSession>( + sessionID, initiator_, responder_, stream, iqRouter_); + ibbSession->setBlockSize(blockSize); + return std::make_shared<IBBSendTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createIBBReceiveSession(const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream> stream) { + std::shared_ptr<IBBReceiveSession> ibbSession = std::make_shared<IBBReceiveSession>( + sessionID, initiator_, responder_, size, stream, iqRouter_); + return std::make_shared<IBBReceiveTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + +private: + std::string getSOCKS5DstAddr() const { + std::string result; + if (role_ == Initiator) { + result = getInitiatorCandidateSOCKS5DstAddr(); + } + else { + result = getResponderCandidateSOCKS5DstAddr(); + } + return result; + } + + std::string getInitiatorCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + initiator_.toString() + responder_.toString()))); + } + + std::string getResponderCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + responder_.toString() + initiator_.toString()))); + } + + +private: + JID initiator_; + JID responder_; + Role role_; + SOCKS5BytestreamRegistry* s5bRegistry_; + CryptoProvider* crypto_; + std::string s5bSessionID_; + IQRouter* iqRouter_; + FileTransferOptions ftOptions_; +}; + +class DummyFileTransferTransporterFactory : public FileTransferTransporterFactory { +public: + DummyFileTransferTransporterFactory( + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter) : s5bRegistry_(s5bRegistry), s5bServerManager_(s5bServerManager), s5bProxy_(s5bProxy), idGenerator_(idGenerator), connectionFactory_(connectionFactory), timerFactory_(timerFactory), cryptoProvider_(cryptoProvider), iqRouter_(iqRouter) { + + } + + virtual ~DummyFileTransferTransporterFactory() { + } + + virtual FileTransferTransporter* createInitiatorTransporter(const JID& initiator, const JID& responder, const FileTransferOptions& options) { + DummyFileTransferTransporter* transporter = new DummyFileTransferTransporter( + initiator, + responder, + DummyFileTransferTransporter::Initiator, + s5bRegistry_, + s5bServerManager_, + s5bProxy_, + idGenerator_, + connectionFactory_, + timerFactory_, + cryptoProvider_, + iqRouter_, + options); + transporter->initialize(); + return transporter; + } + + virtual FileTransferTransporter* createResponderTransporter(const JID& /* initiator */, const JID& /* responder */, const std::string& /* s5bSessionID */, const FileTransferOptions& /* options */) { + return nullptr; + } + +private: + SOCKS5BytestreamRegistry* s5bRegistry_; + SOCKS5BytestreamServerManager* s5bServerManager_; + SOCKS5BytestreamProxiesManager* s5bProxy_; + IDGenerator* idGenerator_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + CryptoProvider* cryptoProvider_; + IQRouter* iqRouter_; +}; + +} diff --git a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp index 339e245..31f46de 100644 --- a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp @@ -1,185 +1,187 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <vector> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBReceiveSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); - CPPUNIT_TEST(testOpen); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveMultipleData); - CPPUNIT_TEST(testReceiveDataForOtherSession); - CPPUNIT_TEST(testReceiveDataOutOfOrder); - CPPUNIT_TEST(testReceiveLastData); - CPPUNIT_TEST(testReceiveClose); - CPPUNIT_TEST(testStopWhileActive); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - finished = false; - bytestream = boost::make_shared<ByteArrayWriteBytestream>(); - } + CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); + CPPUNIT_TEST(testOpen); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveMultipleData); + CPPUNIT_TEST(testReceiveDataForOtherSession); + CPPUNIT_TEST(testReceiveDataOutOfOrder); + CPPUNIT_TEST(testReceiveLastData); + CPPUNIT_TEST(testReceiveClose); + CPPUNIT_TEST(testStopWhileActive); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + finished = false; + bytestream = std::make_shared<ByteArrayWriteBytestream>(); + } - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testOpen() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testOpen() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } - void testReceiveData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveMultipleData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveDataForOtherSession() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); - - testling->stop(); - } - - void testReceiveDataOutOfOrder() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - - testling->stop(); - } - - void testReceiveLastData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - - testling->stop(); - } - - void testReceiveClose() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); + void testReceiveData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveMultipleData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveDataForOtherSession() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); + + testling->stop(); + } + + void testReceiveDataOutOfOrder() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + + testling->stop(); + } + + void testReceiveLastData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + + testling->stop(); + } + + void testReceiveClose() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); - testling->stop(); - } + testling->stop(); + } - void testStopWhileActive() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void testStopWhileActive() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - testling->stop(); + testling->stop(); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } - private: - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); - request->setFrom(from); - return request; - } + private: + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); + request->setFrom(from); + return request; + } - IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { - IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); - session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); - return session; - } + IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { + IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); + session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); + return session; + } - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayWriteBytestream> bytestream; + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayWriteBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp index 13b73bb..2399cbe 100644 --- a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp @@ -1,230 +1,232 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> + #include <boost/bind.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> +#include <Swiften/FileTransfer/IBBSendSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBSendSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBSendSessionTest); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStart_ResponseStartsSending); - CPPUNIT_TEST(testResponseContinuesSending); - CPPUNIT_TEST(testRespondToAllFinishes); - CPPUNIT_TEST(testErrorResponseFinishesWithError); - CPPUNIT_TEST(testStopDuringSessionCloses); - CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); - CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); - - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - bytestream = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testStart() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(1234); - - testling->start(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(1234, ibb->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testStart_ResponseStartsSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testResponseContinuesSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testRespondToAllFinishes() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testErrorResponseFinishesWithError() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - } - - void testStopDuringSessionCloses() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testStopAfterFinishedDoesNotClose() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(16); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - CPPUNIT_ASSERT(finished); - - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - - CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeBeforePauseDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterResumeDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - bytestream->addData(createByteArray("xuv")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - private: - IQ::ref createIBBResult() { - return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), boost::shared_ptr<IBB>()); - } - - private: - boost::shared_ptr<IBBSendSession> createSession(const std::string& to) { - boost::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); - session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayReadBytestream> bytestream; + CPPUNIT_TEST_SUITE(IBBSendSessionTest); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStart_ResponseStartsSending); + CPPUNIT_TEST(testResponseContinuesSending); + CPPUNIT_TEST(testRespondToAllFinishes); + CPPUNIT_TEST(testErrorResponseFinishesWithError); + CPPUNIT_TEST(testStopDuringSessionCloses); + CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); + CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); + + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + bytestream = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testStart() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(1234); + + testling->start(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(1234u, ibb->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testStart_ResponseStartsSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testResponseContinuesSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testRespondToAllFinishes() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testErrorResponseFinishesWithError() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + } + + void testStopDuringSessionCloses() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testStopAfterFinishedDoesNotClose() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(16); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + CPPUNIT_ASSERT(finished); + + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + + CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeBeforePauseDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterResumeDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + bytestream->addData(createByteArray("xuv")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + private: + IQ::ref createIBBResult() { + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), std::shared_ptr<IBB>()); + } + + private: + std::shared_ptr<IBBSendSession> createSession(const std::string& to) { + std::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); + session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayReadBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBSendSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp index 669ed80..9793b87 100644 --- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp @@ -5,214 +5,238 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ +#include <iostream> +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Override.h> #include <Swiften/Base/Log.h> #include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Elements/IBB.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> #include <Swiften/Jingle/FakeJingleSession.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/DummyConnectionFactory.h> +#include <Swiften/Network/DummyConnectionServerFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/Network/NATTraverser.h> #include <Swiften/Network/PlatformNATTraversalWorker.h> +#include <Swiften/Network/PlatformNetworkEnvironment.h> +#include <Swiften/Network/StaticDomainNameResolver.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> - -#include <iostream> using namespace Swift; -using namespace boost; class IncomingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); - //CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); - //CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); - //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); + CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); + CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); + //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); + CPPUNIT_TEST_SUITE_END(); public: - // shared_ptr<IncomingJingleFileTransfer> createTestling() { - // JID ourJID("our@jid.org/full"); - // return boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get())); - // } - - // IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - // IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - // request->setFrom(from); - // return request; - // } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - eventLoop = new DummyEventLoop(); - session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); - // jingleContentPayload = make_shared<JingleContentPayload>(); - // fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); - // fakeLJTCF = make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); - // stanzaChannel = new DummyStanzaChannel(); - // iqRouter = new IQRouter(stanzaChannel); - // bytestreamRegistry = new SOCKS5BytestreamRegistry(); - // timerFactory = new DummyTimerFactory(); - // connectionFactory = new DummyConnectionFactory(eventLoop); - // bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); - } - - void tearDown() { - // delete bytestreamProxy; - // delete connectionFactory; - // delete timerFactory; - // delete bytestreamRegistry; - // delete iqRouter; - // delete stanzaChannel; - delete eventLoop; - } - - // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. + std::shared_ptr<IncomingJingleFileTransfer> createTestling() { + JID ourJID("our@jid.org/full"); + return std::make_shared<IncomingJingleFileTransfer>(ourJID, std::shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get()); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + session = std::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + // fakeRJTCSF = std::make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); + // fakeLJTCF = std::make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); + stanzaChannel = new DummyStanzaChannel(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + iqRouter = new IQRouter(stanzaChannel); + bytestreamRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + idGenerator = new SimpleIDGenerator(); + timerFactory = new DummyTimerFactory(); + bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransporterFactory; + delete bytestreamProxy; + delete timerFactory; + delete idGenerator; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete bytestreamRegistry; + delete iqRouter; + delete serverConnectionFactory; + delete connectionFactory; + delete stanzaChannel; + delete resolver; + delete eventLoop; + Log::setLogLevel(Log::error); + } + + // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. + void test_AcceptOnyIBBSendsSessionAccept() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + } + + void test_OnlyIBBTransferReceiveWorks() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } + + void test_AcceptFailingS5BFallsBackToIBB() { + //1. create your test incoming file transfer + addFileTransferDescription(); + + // add SOCKS5BytestreamTransportPayload + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // candidates are gathered + + // check whether accept has been called + FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); + CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); + + // check for candidate error + FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); + JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); + CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); + + // indicate transport replace (Romeo) + session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload()); + + FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); + + // send a bit of data + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } #if 0 - void test_AcceptOnyIBBSendsSessionAccept() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - } - - void test_OnlyIBBTransferReceiveWorks() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } - - void test_AcceptFailingS5BFallsBackToIBB() { - //1. create your test incoming file transfer - addFileTransferDescription(); - - // add SOCKS5BytestreamTransportPayload - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); - CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); - - // check for candidate error - FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); - JingleS5BTransportPayload::ref s5bPayload = dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); - CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); - - // indicate transport replace (Romeo) - session->onTransportReplaceReceived(getContentID(), addJingleIBBPayload()); - - FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); - - // send a bit of data - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } - - void test_S5BTransferReceiveTest() { - addFileTransferDescription(); - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - } - -private: - void addFileTransferDescription() { - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - } - - shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < session->calledCommands.size()); - T* cmd = boost::get<T>(&session->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void test_S5BTransferReceiveTest() { + addFileTransferDescription(); + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + } #endif +private: + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < session->calledCommands.size()); + T* cmd = boost::get<T>(&session->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - EventLoop* eventLoop; - boost::shared_ptr<CryptoProvider> crypto; - boost::shared_ptr<FakeJingleSession> session; -#if 0 - shared_ptr<JingleContentPayload> jingleContentPayload; - shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; - shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - SOCKS5BytestreamRegistry* bytestreamRegistry; - DummyConnectionFactory* connectionFactory; - SOCKS5BytestreamProxiesManager* bytestreamProxy; - DummyTimerFactory* timerFactory; -#endif + EventLoop* eventLoop; + std::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<FakeJingleSession> session; + std::shared_ptr<JingleContentPayload> jingleContentPayload; +// shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; +// shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; + FileTransferTransporterFactory* ftTransporterFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + SOCKS5BytestreamRegistry* bytestreamRegistry; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + DummyTimerFactory* timerFactory; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + IDGenerator* idGenerator; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest); diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp index 16b1225..a0fe057 100644 --- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp @@ -5,290 +5,278 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <iostream> +#include <memory> #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> -#include <Swiften/Jingle/FakeJingleSession.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/FileTransfer/ByteArrayReadBytestream.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Elements/JingleFileTransferDescription.h> -#include <Swiften/Elements/IBB.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Override.h> #include <Swiften/Base/IDGenerator.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/IBB.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Network/PlatformNATTraversalWorker.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/Network/DummyConnection.h> +#include <Swiften/FileTransfer/ByteArrayReadBytestream.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h> +#include <Swiften/Jingle/FakeJingleSession.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyConnection.h> #include <Swiften/Network/DummyConnectionFactory.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> - -#include <Swiften/Base/Log.h> - -#include <iostream> +#include <Swiften/Network/DummyConnectionServer.h> +#include <Swiften/Network/DummyConnectionServerFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/Network/PlatformNATTraversalWorker.h> +#include <Swiften/Network/PlatformNetworkEnvironment.h> +#include <Swiften/Queries/IQRouter.h> -#if 0 using namespace Swift; -class OFakeRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector { - void addRemoteTransportCandidates(JingleTransportPayload::ref cand) { - candidate = cand; - } - - void selectCandidate() { - JingleS5BTransportPayload::ref payload = boost::make_shared<JingleS5BTransportPayload>(); - payload->setCandidateError(true); - payload->setSessionID(candidate->getSessionID()); - onRemoteTransportCandidateSelectFinished(payload); - } - - void setMinimumPriority(int) { - - } - - bool isActualCandidate(JingleTransportPayload::ref) { - return false; - } - - int getPriority(JingleTransportPayload::ref) { - return 0; - } - - JingleTransport::ref selectTransport(JingleTransportPayload::ref) { - return JingleTransport::ref(); - } - -private: - JingleTransportPayload::ref candidate; -}; - -class OFakeRemoteJingleTransportCandidateSelectorFactory : public RemoteJingleTransportCandidateSelectorFactory { -public: - virtual ~OFakeRemoteJingleTransportCandidateSelectorFactory() { - - } - - virtual RemoteJingleTransportCandidateSelector* createCandidateSelector() { - return new OFakeRemoteJingleTransportCandidateSelector(); - } -}; - -class OFakeLocalJingleTransportCandidateGenerator : public LocalJingleTransportCandidateGenerator { -public: - void emitonLocalTransportCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - onLocalTransportCandidatesGenerated(candidates); - } - - virtual bool isActualCandidate(JingleTransportPayload::ref) { - return false; - } - - virtual int getPriority(JingleTransportPayload::ref) { - return 0; - } - - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) { - return JingleTransport::ref(); - } - - virtual void start() SWIFTEN_OVERRIDE { - //JingleTransportPayload::ref payL = make_shared<JingleTransportPayload>(); - //payL->setSessionID(payload->getSessionID()); - // JingleS5BTransportPayload::ref payL = boost::make_shared<JingleS5BTransportPayload>(); - - onLocalTransportCandidatesGenerated(std::vector<JingleS5BTransportPayload::Candidate>()); - } - - virtual void stop() SWIFTEN_OVERRIDE {} -}; - -class OFakeLocalJingleTransportCandidateGeneratorFactory : public LocalJingleTransportCandidateGeneratorFactory { -public: - virtual LocalJingleTransportCandidateGenerator* createCandidateGenerator() { - return new OFakeLocalJingleTransportCandidateGenerator(); - } -}; - class OutgoingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); - CPPUNIT_TEST(test_SendSessionInitiateOnStart); - CPPUNIT_TEST(test_IBBStartsAfterSendingSessionAccept); - CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); - CPPUNIT_TEST_SUITE_END(); - - class FTStatusHelper { - public: - bool finishedCalled; - FileTransferError::Type error; - void handleFileTransferFinished(boost::optional<FileTransferError> error) { - finishedCalled = true; - if (error.is_initialized()) this->error = error.get().getType(); - } - }; + CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); + CPPUNIT_TEST(test_SendSessionInitiateOnStart); + CPPUNIT_TEST(test_FallbackToIBBAfterFailingS5B); + CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); + CPPUNIT_TEST(test_DeclineEmitsFinishedStateCanceled); + CPPUNIT_TEST_SUITE_END(); + + class FTStatusHelper { + public: + FTStatusHelper() : finishedCalled(false), error(FileTransferError::UnknownError) { + } + + void handleFileTransferFinished(boost::optional<FileTransferError> error) { + finishedCalled = true; + if (error.is_initialized()) this->error = error.get().getType(); + } + + void handleFileTransferStatusChanged(FileTransfer::State fileTransferSTate) { + state = fileTransferSTate; + } + + public: + bool finishedCalled; + FileTransferError::Type error; + boost::optional<FileTransfer::State> state; + }; + public: - boost::shared_ptr<OutgoingJingleFileTransfer> createTestling() { - JID to("test@foo.com/bla"); - StreamInitiationFileInfo fileInfo; - fileInfo.setDescription("some file"); - fileInfo.setName("test.bin"); - fileInfo.setHash("asdjasdas"); - fileInfo.setSize(1024 * 1024); - return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(boost::shared_ptr<JingleSession>(fakeJingleSession), fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, idGen, JID(), to, stream, fileInfo, s5bRegistry, s5bProxy, crypto.get())); - } - - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - request->setFrom(from); - return request; - } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); - jingleContentPayload = boost::make_shared<JingleContentPayload>(); - fakeRJTCSF = boost::make_shared<OFakeRemoteJingleTransportCandidateSelectorFactory>(); - fakeLJTCF = boost::make_shared<OFakeLocalJingleTransportCandidateGeneratorFactory>(); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connectionFactory = new DummyConnectionFactory(eventLoop); - s5bRegistry = new SOCKS5BytestreamRegistry(); - s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); - - data.clear(); - for (int n=0; n < 1024 * 1024; ++n) { - data.push_back(34); - } - - stream = boost::make_shared<ByteArrayReadBytestream>(data); - - idGen = new IDGenerator(); - } - - void tearDown() { - delete idGen; - delete s5bRegistry; - delete connectionFactory; - delete timerFactory; - delete eventLoop; - delete iqRouter; - delete stanzaChannel; - } - - - void test_SendSessionInitiateOnStart() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - JingleFileTransferDescription::ref description = boost::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); - CPPUNIT_ASSERT(description); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), description->getOffers().size()); - CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getOffers()[0].getSize()); - - JingleS5BTransportPayload::ref transport = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload); - CPPUNIT_ASSERT(transport); - } - - void test_IBBStartsAfterSendingSessionAccept() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - // FIXME: we initiate with SOCSK5 now and not IBB, needs to be fixed. - /* - fakeJingleSession->onSessionAcceptReceived(call.id, call.description, call.payload); - IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); - CPPUNIT_ASSERT(iqOpenStanza); - */ - } - - void test_ReceiveSessionTerminateAfterSessionInitiate() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - getCall<FakeJingleSession::InitiateCall>(0); - - FTStatusHelper helper; - helper.finishedCalled = false; - transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); - fakeJingleSession->onSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); - CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); - CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); - } - + std::shared_ptr<OutgoingJingleFileTransfer> createTestling(const FileTransferOptions& options = FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false)) { + JID to("test@foo.com/bla"); + JingleFileTransferFileInfo fileInfo; + fileInfo.setDescription("some file"); + fileInfo.setName("test.bin"); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.setSize(1024 * 1024); + return std::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( + to, + std::shared_ptr<JingleSession>(fakeJingleSession), + stream, + ftTransportFactory, + timerFactory, + idGen, + fileInfo, + options, + crypto.get())); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + eventLoop = new DummyEventLoop(); + timerFactory = new DummyTimerFactory(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + s5bRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(s5bRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + + data.clear(); + for (int n=0; n < 1024 * 1024; ++n) { + data.push_back(34); + } + + stream = std::make_shared<ByteArrayReadBytestream>(data); + + idGen = new IDGenerator(); + s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransportFactory = new DummyFileTransferTransporterFactory(s5bRegistry, bytestreamServerManager, s5bProxy, idGen, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransportFactory; + delete s5bProxy; + delete idGen; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete s5bRegistry; + delete serverConnectionFactory; + delete connectionFactory; + delete timerFactory; + delete eventLoop; + delete iqRouter; + delete stanzaChannel; + } + + + void test_SendSessionInitiateOnStart() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + JingleFileTransferDescription::ref description = std::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); + CPPUNIT_ASSERT(description); + CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getFileInfo().getSize()); + + JingleIBBTransportPayload::ref transport = std::dynamic_pointer_cast<JingleIBBTransportPayload>(call.payload); + CPPUNIT_ASSERT(transport); + } + + void test_FallbackToIBBAfterFailingS5B() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true)); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + + CPPUNIT_ASSERT(std::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload)); + fakeJingleSession->handleSessionAcceptReceived(call.id, call.description, call.payload); + + // send candidate failure + JingleS5BTransportPayload::ref candidateFailurePayload = std::make_shared<JingleS5BTransportPayload>(); + candidateFailurePayload->setCandidateError(true); + candidateFailurePayload->setSessionID(call.payload->getSessionID()); + fakeJingleSession->handleTransportInfoReceived(call.id, candidateFailurePayload); + + // no S5B candidates -> fallback to IBB + // call at position 1 is the candidate our candidate error + FakeJingleSession::ReplaceTransportCall replaceCall = getCall<FakeJingleSession::ReplaceTransportCall>(2); + + // accept transport replace + fakeJingleSession->handleTransportAcceptReceived(replaceCall.id, replaceCall.payload); + + IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); + CPPUNIT_ASSERT(iqOpenStanza); + IBB::ref ibbOpen = iqOpenStanza->getPayload<IBB>(); + CPPUNIT_ASSERT(ibbOpen); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibbOpen->getAction()); + } + + void test_ReceiveSessionTerminateAfterSessionInitiate() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); + } + + void test_DeclineEmitsFinishedStateCanceled() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + transfer->onStateChanged.connect(bind(&FTStatusHelper::handleFileTransferStatusChanged, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Decline)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::UnknownError == helper.error); + CPPUNIT_ASSERT_EQUAL(true, helper.state.is_initialized()); + CPPUNIT_ASSERT(FileTransfer::State::Canceled == helper.state.get().type); + } //TODO: some more testcases private: - void addFileTransferDescription() { - boost::shared_ptr<JingleFileTransferDescription> desc = boost::make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo()); - jingleContentPayload->addDescription(desc); - } - - boost::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = boost::make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - boost::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = boost::make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); - T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo()); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); + T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - std::vector<unsigned char> data; - boost::shared_ptr<ByteArrayReadBytestream> stream; - FakeJingleSession* fakeJingleSession; - boost::shared_ptr<JingleContentPayload> jingleContentPayload; - boost::shared_ptr<OFakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; - boost::shared_ptr<OFakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - IDGenerator* idGen; - EventLoop *eventLoop; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxiesManager* s5bProxy; - DummyTimerFactory* timerFactory; - DummyConnectionFactory* connectionFactory; - boost::shared_ptr<CryptoProvider> crypto; + std::vector<unsigned char> data; + std::shared_ptr<ByteArrayReadBytestream> stream; + FakeJingleSession* fakeJingleSession; + std::shared_ptr<JingleContentPayload> jingleContentPayload; + FileTransferTransporterFactory* ftTransportFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + IDGenerator* idGen; + EventLoop *eventLoop; + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamProxiesManager* s5bProxy; + DummyTimerFactory* timerFactory; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + std::shared_ptr<CryptoProvider> crypto; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(OutgoingJingleFileTransferTest); -#endif diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp index 78ea8ed..fad02da 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp @@ -4,23 +4,31 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <Swiften/Base/ByteArray.h> -#include <QA/Checker/IO.h> +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <boost/bind.hpp> #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <boost/smart_ptr/make_shared.hpp> + +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/StartStopper.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> @@ -30,280 +38,277 @@ #include <Swiften/Network/DummyConnection.h> #include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; static boost::mt19937 randomGen; class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); - CPPUNIT_TEST(testForSessionReady); - CPPUNIT_TEST(testErrorHandlingHello); - CPPUNIT_TEST(testErrorHandlingRequest); - CPPUNIT_TEST(testWriteBytestream); - CPPUNIT_TEST(testReadBytestream); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); + CPPUNIT_TEST(testForSessionReady); + CPPUNIT_TEST(testErrorHandlingHello); + CPPUNIT_TEST(testErrorHandlingRequest); + CPPUNIT_TEST(testWriteBytestream); + CPPUNIT_TEST(testReadBytestream); + CPPUNIT_TEST_SUITE_END(); public: - SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)) {} - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - destination = "092a44d859d19c9eed676b551ee80025903351c2"; - randomGen.seed(static_cast<unsigned int>(time(NULL))); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connection = boost::make_shared<MockeryConnection>(failingPorts, true, eventLoop); - //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - //stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); -// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); - } - - void tearDown() { - //connection.reset(); - delete timerFactory; - delete eventLoop; - } - - void testForSessionReady() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - } - - void testErrorHandlingHello() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloAuthFail(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testErrorHandlingRequest() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestFail(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testWriteBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - boost::shared_ptr<ByteArrayWriteBytestream> output = boost::make_shared<ByteArrayWriteBytestream>(); - clientSession->startReceiving(output); - - ByteArray transferData = generateRandomByteArray(1024); - connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); - CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); - } - - void testReadBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - helper.unprocessedInput.clear(); - ByteArray transferData = generateRandomByteArray(1024); - boost::shared_ptr<ByteArrayReadBytestream> input = boost::make_shared<ByteArrayReadBytestream>(transferData); - clientSession->startSending(input); - eventLoop->processEvents(); + SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 8888)) {} + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + destination = "092a44d859d19c9eed676b551ee80025903351c2"; + randomGen.seed(static_cast<unsigned int>(time(nullptr))); + eventLoop = std::make_unique<DummyEventLoop>(); + timerFactory = std::make_unique<DummyTimerFactory>(); + connection = std::make_shared<MockeryConnection>(failingPorts, true, eventLoop.get()); + //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + //stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); +// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); + } + + void tearDown() { + //connection.reset(); + } + + void testForSessionReady() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + } + + void testErrorHandlingHello() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloAuthFail(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testErrorHandlingRequest() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestFail(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testWriteBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + std::shared_ptr<ByteArrayWriteBytestream> output = std::make_shared<ByteArrayWriteBytestream>(); + clientSession->startReceiving(output); + + ByteArray transferData = generateRandomByteArray(1024); + connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); + CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); + } + + void testReadBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + helper.unprocessedInput.clear(); + ByteArray transferData = generateRandomByteArray(1024); + std::shared_ptr<ByteArrayReadBytestream> input = std::make_shared<ByteArrayReadBytestream>(transferData); + clientSession->startSending(input); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); + } - CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); - } +private: + static ByteArray generateRandomByteArray(size_t len) { + boost::uniform_int<> dist(0, 255); + boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); + ByteArray result(len); + for (size_t i=0; i < len; ++i ) { + result[i] = static_cast<unsigned char>(randomByte()); + } + return result; + } + + // Server responses + void serverRespondHelloOK() { + connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); + } + + void serverRespondHelloAuthFail() { + connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); + } + + void serverRespondRequestOK() { + std::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); + append(*dataToSend, createSafeByteArray(destination)); + append(*dataToSend, createSafeByteArray("\x00", 1)); + connection->onDataRead(dataToSend); + } + + void serverRespondRequestFail() { + std::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); + append(*correctData, createSafeByteArray(destination)); + append(*correctData, createSafeByteArray("\x00", 1)); + + std::shared_ptr<SafeByteArray> dataToSend; + //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); + //append(dataToSend, failingData); + //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData); + do { + ByteArray rndArray = generateRandomByteArray(correctData->size()); + dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); + } while (*dataToSend == *correctData); + connection->onDataRead(dataToSend); + } +private: + struct TestHelper { + TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} + ByteArray unprocessedInput; + bool sessionReadyCalled; + bool sessionReadyError; + void handleConnectionDataWritten(const SafeByteArray& data) { + append(unprocessedInput, data); + //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput); + } + + void handleSessionReady(bool error) { + sessionReadyCalled = true; + sessionReadyError = error; + } + }; -private: - static ByteArray generateRandomByteArray(size_t len) { - boost::uniform_int<> dist(0, 255); - boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); - ByteArray result(len); - for (size_t i=0; i < len; ++i ) { - result[i] = static_cast<unsigned char>(randomByte()); - } - return result; - } - - // Server responses - void serverRespondHelloOK() { - connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); - } - - void serverRespondHelloAuthFail() { - connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); - } - - void serverRespondRequestOK() { - boost::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); - append(*dataToSend, createSafeByteArray(destination)); - append(*dataToSend, createSafeByteArray("\x00", 1)); - connection->onDataRead(dataToSend); - } - - void serverRespondRequestFail() { - boost::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); - append(*correctData, createSafeByteArray(destination)); - append(*correctData, createSafeByteArray("\x00", 1)); - - boost::shared_ptr<SafeByteArray> dataToSend; - //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); - //append(dataToSend, failingData); - //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData) << std::endl; - do { - ByteArray rndArray = generateRandomByteArray(correctData->size()); - dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); - } while (*dataToSend == *correctData); - connection->onDataRead(dataToSend); - } private: - struct TestHelper { - TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} - ByteArray unprocessedInput; - bool sessionReadyCalled; - bool sessionReadyError; + struct MockeryConnection : public Connection, public EventOwner, public std::enable_shared_from_this<MockeryConnection> { + public: + MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - void handleConnectionDataWritten(const SafeByteArray& data) { - append(unprocessedInput, data); - //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput) << std::endl; - } + 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)); + } + } - void handleSessionReady(bool error) { - sessionReadyCalled = true; - sessionReadyError = error; - } - }; + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } -private: - struct MockeryConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<MockeryConnection> { - public: - MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - - 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(); } - void disconnect() { - disconnectCalled = true; - } - - void write(const SafeByteArray& data) { - eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); - onDataSent(data); - } - - boost::signal<void (const SafeByteArray&)> onDataSent; - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - bool disconnectCalled; - }; + void disconnect() { + disconnectCalled = true; + } + + void write(const SafeByteArray& data) { + eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); + onDataSent(data); + } + + boost::signals2::signal<void (const SafeByteArray&)> onDataSent; + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + bool disconnectCalled; + }; private: - HostAddressPort destinationAddressPort; - std::string destination; - DummyEventLoop* eventLoop; - DummyTimerFactory* timerFactory; - boost::shared_ptr<MockeryConnection> connection; - const std::vector<HostAddressPort> failingPorts; - boost::shared_ptr<CryptoProvider> crypto; + HostAddressPort destinationAddressPort; + std::string destination; + std::unique_ptr<DummyEventLoop> eventLoop; + std::unique_ptr<DummyTimerFactory> timerFactory; + std::shared_ptr<MockeryConnection> connection; + const std::vector<HostAddressPort> failingPorts; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamClientSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp index 7af546f..d419b8a 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp @@ -1,213 +1,213 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <boost/bind.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> +#include <Swiften/Base/StartStopper.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/Network/DummyConnection.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Base/StartStopper.h> using namespace Swift; class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); - CPPUNIT_TEST(testAuthenticate); - CPPUNIT_TEST(testAuthenticate_Chunked); - CPPUNIT_TEST(testRequest); - CPPUNIT_TEST(testRequest_UnknownBytestream); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveData_Chunked); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - receivedDataChunks = 0; - eventLoop = new DummyEventLoop(); - bytestreams = new SOCKS5BytestreamRegistry(); - connection = boost::make_shared<DummyConnection>(eventLoop); - connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - connection.reset(); - delete bytestreams; - delete eventLoop; - } - - void testAuthenticate() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01\x02")); - - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testAuthenticate_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01")); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); - receive(createSafeByteArray("\x01")); - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testRequest() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); - } - - void testRequest_UnknownBytestream() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); - } - - void testReceiveData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - skipHeader("abcdef"); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); - } - - void testReceiveData_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - - stream1->addData(createByteArray("xyz")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - private: - void receive(const SafeByteArray& data) { - connection->receive(data); - eventLoop->processEvents(); - } - - void authenticate() { - receive(createSafeByteArray("\x05\x02\x01\x02")); - receivedData.clear(); - receivedDataChunks = 0; - } - - void request(const std::string& hostname) { - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - } - - void skipHeader(const std::string& hostname) { - size_t headerSize = 7 + hostname.size(); - receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); - } - - - void handleDataWritten(const SafeByteArray& data) { - receivedData.insert(receivedData.end(), data.begin(), data.end()); - receivedDataChunks++; - } - - private: - SOCKS5BytestreamServerSession* createSession() { - SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyEventLoop* eventLoop; - SOCKS5BytestreamRegistry* bytestreams; - boost::shared_ptr<DummyConnection> connection; - std::vector<unsigned char> receivedData; - int receivedDataChunks; - boost::shared_ptr<ByteArrayReadBytestream> stream1; - bool finished; - boost::optional<FileTransferError> error; + CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); + CPPUNIT_TEST(testAuthenticate); + CPPUNIT_TEST(testAuthenticate_Chunked); + CPPUNIT_TEST(testRequest); + CPPUNIT_TEST(testRequest_UnknownBytestream); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveData_Chunked); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + receivedDataChunks = 0; + eventLoop = new DummyEventLoop(); + bytestreams = new SOCKS5BytestreamRegistry(); + connection = std::make_shared<DummyConnection>(eventLoop); + connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + connection.reset(); + delete bytestreams; + delete eventLoop; + } + + void testAuthenticate() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01\x02")); + + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testAuthenticate_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01")); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); + receive(createSafeByteArray("\x01")); + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testRequest() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); + } + + void testRequest_UnknownBytestream() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); + } + + void testReceiveData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + skipHeader("abcdef"); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); + } + + void testReceiveData_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + + stream1->addData(createByteArray("xyz")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + private: + void receive(const SafeByteArray& data) { + connection->receive(data); + eventLoop->processEvents(); + } + + void authenticate() { + receive(createSafeByteArray("\x05\x02\x01\x02")); + receivedData.clear(); + receivedDataChunks = 0; + } + + void request(const std::string& hostname) { + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + } + + void skipHeader(const std::string& hostname) { + size_t headerSize = 7 + hostname.size(); + receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); + } + + + void handleDataWritten(const SafeByteArray& data) { + receivedData.insert(receivedData.end(), data.begin(), data.end()); + receivedDataChunks++; + } + + private: + SOCKS5BytestreamServerSession* createSession() { + SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyEventLoop* eventLoop; + SOCKS5BytestreamRegistry* bytestreams; + std::shared_ptr<DummyConnection> connection; + std::vector<unsigned char> receivedData; + int receivedDataChunks; + std::shared_ptr<ByteArrayReadBytestream> stream1; + bool finished; + boost::optional<FileTransferError> error; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamServerSessionTest); |