/* * Copyright (c) 2010 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/ByteArray.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; } 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")); 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") == receivedData); 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") == receivedData); 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") == receivedData); 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")); CPPUNIT_ASSERT(finished); CPPUNIT_ASSERT(error); 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")); 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); } 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, iqRouter); session->onDataReceived.connect(boost::bind(&IBBReceiveSessionTest::handleDataReceived, this, _1)); session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); return session; } void handleFinished(boost::optional<FileTransferError> error) { finished = true; this->error = error; } void handleDataReceived(const std::vector<unsigned char>& data) { receivedData.insert(receivedData.end(), data.begin(), data.end()); } private: DummyStanzaChannel* stanzaChannel; IQRouter* iqRouter; bool finished; boost::optional<FileTransferError> error; std::vector<unsigned char> receivedData; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest);