/* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include #include #include #include using namespace Swift; class RequestTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RequestTest); CPPUNIT_TEST(testSendGet); CPPUNIT_TEST(testSendSet); CPPUNIT_TEST(testHandleIQ); CPPUNIT_TEST(testHandleIQ_InvalidID); CPPUNIT_TEST(testHandleIQ_Error); CPPUNIT_TEST(testHandleIQ_ErrorWithoutPayload); CPPUNIT_TEST(testHandleIQ_BeforeSend); CPPUNIT_TEST(testHandleIQ_DifferentPayload); CPPUNIT_TEST(testHandleIQ_RawXMLPayload); CPPUNIT_TEST(testHandleIQ_GetWithSameID); CPPUNIT_TEST(testHandleIQ_SetWithSameID); CPPUNIT_TEST(testHandleIQ_IncorrectSender); CPPUNIT_TEST(testHandleIQ_IncorrectSenderForServerQuery); CPPUNIT_TEST(testHandleIQ_IncorrectOtherResourceSenderForServerQuery); CPPUNIT_TEST(testHandleIQ_ServerRespondsWithDomain); CPPUNIT_TEST(testHandleIQ_ServerRespondsWithBareJID); CPPUNIT_TEST(testHandleIQ_ServerRespondsWithoutFrom); CPPUNIT_TEST(testHandleIQ_ServerRespondsWithFullJID); CPPUNIT_TEST_SUITE_END(); public: class MyPayload : public Payload { public: MyPayload(const std::string& s = "") : text_(s) {} std::string text_; }; struct MyOtherPayload : public Payload { }; class MyRequest : public Request { public: MyRequest( IQ::Type type, const JID& receiver, std::shared_ptr payload, IQRouter* router) : Request(type, receiver, payload, router) { } virtual void handleResponse(std::shared_ptr payload, ErrorPayload::ref error) { onResponse(payload, error); } public: boost::signal, ErrorPayload::ref)> onResponse; }; public: void setUp() { channel_ = new DummyIQChannel(); router_ = new IQRouter(channel_); payload_ = std::make_shared("foo"); responsePayload_ = std::make_shared("bar"); responsesReceived_ = 0; } void tearDown() { delete router_; delete channel_; } void testSendSet() { MyRequest testling(IQ::Set, JID("foo@bar.com/baz"), payload_, router_); testling.send(); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getTo()); CPPUNIT_ASSERT_EQUAL(IQ::Set, channel_->iqs_[0]->getType()); CPPUNIT_ASSERT_EQUAL(std::string("test-id"), channel_->iqs_[0]->getID()); } void testSendGet() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.send(); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); CPPUNIT_ASSERT_EQUAL(IQ::Get, channel_->iqs_[0]->getType()); } void testHandleIQ() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } // FIXME: Doesn't test that it didn't handle the payload void testHandleIQ_InvalidID() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"different-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_Error() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); std::shared_ptr error = createError(JID("foo@bar.com/baz"),"test-id"); std::shared_ptr errorPayload = std::make_shared(ErrorPayload::InternalServerError); error->addPayload(errorPayload); channel_->onIQReceived(error); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(1, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); CPPUNIT_ASSERT_EQUAL(ErrorPayload::InternalServerError, receivedErrors[0].getCondition()); } void testHandleIQ_ErrorWithoutPayload() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createError(JID("foo@bar.com/baz"),"test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(1, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); CPPUNIT_ASSERT_EQUAL(ErrorPayload::UndefinedCondition, receivedErrors[0].getCondition()); } void testHandleIQ_BeforeSend() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(0, static_cast(channel_->iqs_.size())); } void testHandleIQ_DifferentPayload() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleDifferentResponse, this, _1, _2)); testling.send(); responsePayload_ = std::make_shared(); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_RawXMLPayload() { payload_ = std::make_shared(""); MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleRawXMLResponse, this, _1, _2)); testling.send(); responsePayload_ = std::make_shared(); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_GetWithSameID() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); std::shared_ptr response = createResponse(JID("foo@bar.com/baz"),"test-id"); response->setType(IQ::Get); channel_->onIQReceived(response); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(2, static_cast(channel_->iqs_.size())); } void testHandleIQ_SetWithSameID() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); std::shared_ptr response = createResponse(JID("foo@bar.com/baz"), "test-id"); response->setType(IQ::Set); channel_->onIQReceived(response); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(2, static_cast(channel_->iqs_.size())); } void testHandleIQ_IncorrectSender() { MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("anotherfoo@bar.com/baz"), "test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_IncorrectSenderForServerQuery() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"), "test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_IncorrectOtherResourceSenderForServerQuery() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/RabbitHole"), "test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_ServerRespondsWithDomain() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("wonderland.lit"),"test-id")); CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_ServerRespondsWithBareJID() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("alice@wonderland.lit"),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } // This tests a bug in ejabberd servers (2.0.5) void testHandleIQ_ServerRespondsWithFullJID() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/TeaParty"),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } void testHandleIQ_ServerRespondsWithoutFrom() { MyRequest testling(IQ::Get, JID(), payload_, router_); router_->setJID("alice@wonderland.lit/TeaParty"); testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); testling.send(); channel_->onIQReceived(createResponse(JID(),"test-id")); CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); CPPUNIT_ASSERT_EQUAL(0, static_cast(receivedErrors.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); } private: void handleResponse(std::shared_ptr p, ErrorPayload::ref e) { if (e) { receivedErrors.push_back(*e); } else { std::shared_ptr payload(std::dynamic_pointer_cast(p)); CPPUNIT_ASSERT(payload); CPPUNIT_ASSERT_EQUAL(std::string("bar"), payload->text_); ++responsesReceived_; } } void handleDifferentResponse(std::shared_ptr p, ErrorPayload::ref e) { CPPUNIT_ASSERT(!e); CPPUNIT_ASSERT(!p); ++responsesReceived_; } void handleRawXMLResponse(std::shared_ptr p, ErrorPayload::ref e) { CPPUNIT_ASSERT(!e); CPPUNIT_ASSERT(p); CPPUNIT_ASSERT(std::dynamic_pointer_cast(p)); ++responsesReceived_; } std::shared_ptr createResponse(const JID& from, const std::string& id) { std::shared_ptr iq(new IQ(IQ::Result)); iq->setFrom(from); iq->addPayload(responsePayload_); iq->setID(id); return iq; } std::shared_ptr createError(const JID& from, const std::string& id) { std::shared_ptr iq(new IQ(IQ::Error)); iq->setFrom(from); iq->setID(id); return iq; } private: IQRouter* router_; DummyIQChannel* channel_; std::shared_ptr payload_; std::shared_ptr responsePayload_; int responsesReceived_; std::vector receivedErrors; }; CPPUNIT_TEST_SUITE_REGISTRATION(RequestTest);