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);  | 
 Swift