/*
* 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 <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <Swiften/Queries/GenericRequest.h>
#include <Swiften/Queries/IQRouter.h>
#include <Swiften/Queries/DummyIQChannel.h>
#include <Swiften/Elements/Payload.h>
#include <Swiften/Elements/RawXMLPayload.h>
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_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,
boost::shared_ptr<Payload> payload,
IQRouter* router) :
Request(type, receiver, payload, router) {
}
virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) {
onResponse(payload, error);
}
public:
boost::signal<void (boost::shared_ptr<Payload>, ErrorPayload::ref)> onResponse;
};
public:
void setUp() {
channel_ = new DummyIQChannel();
router_ = new IQRouter(channel_);
payload_ = boost::shared_ptr<Payload>(new MyPayload("foo"));
responsePayload_ = boost::shared_ptr<Payload>(new MyPayload("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<int>(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<int>(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("test-id"));
CPPUNIT_ASSERT_EQUAL(1, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(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("different-id"));
CPPUNIT_ASSERT_EQUAL(0, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(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();
boost::shared_ptr<IQ> error = createError("test-id");
boost::shared_ptr<Payload> errorPayload = boost::shared_ptr<ErrorPayload>(new ErrorPayload(ErrorPayload::FeatureNotImplemented));
error->addPayload(errorPayload);
channel_->onIQReceived(error);
CPPUNIT_ASSERT_EQUAL(0, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size()));
CPPUNIT_ASSERT_EQUAL(ErrorPayload::FeatureNotImplemented, 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("test-id"));
CPPUNIT_ASSERT_EQUAL(0, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(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("test-id"));
CPPUNIT_ASSERT_EQUAL(0, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(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_ = boost::make_shared<MyOtherPayload>();
channel_->onIQReceived(createResponse("test-id"));
CPPUNIT_ASSERT_EQUAL(1, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size()));
}
void testHandleIQ_RawXMLPayload() {
payload_ = boost::make_shared<RawXMLPayload>("<bla/>");
MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_);
testling.onResponse.connect(boost::bind(&RequestTest::handleRawXMLResponse, this, _1, _2));
testling.send();
responsePayload_ = boost::make_shared<MyOtherPayload>();
channel_->onIQReceived(createResponse("test-id"));
CPPUNIT_ASSERT_EQUAL(1, responsesReceived_);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size()));
}
private:
void handleResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) {
if (e) {
receivedErrors.push_back(*e);
}
else {
boost::shared_ptr<MyPayload> payload(boost::dynamic_pointer_cast<MyPayload>(p));
CPPUNIT_ASSERT(payload);
CPPUNIT_ASSERT_EQUAL(std::string("bar"), payload->text_);
++responsesReceived_;
}
}
void handleDifferentResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) {
CPPUNIT_ASSERT(!e);
CPPUNIT_ASSERT(!p);
++responsesReceived_;
}
void handleRawXMLResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) {
CPPUNIT_ASSERT(!e);
CPPUNIT_ASSERT(p);
CPPUNIT_ASSERT(boost::dynamic_pointer_cast<MyOtherPayload>(p));
++responsesReceived_;
}
boost::shared_ptr<IQ> createResponse(const std::string& id) {
boost::shared_ptr<IQ> iq(new IQ(IQ::Result));
iq->addPayload(responsePayload_);
iq->setID(id);
return iq;
}
boost::shared_ptr<IQ> createError(const std::string& id) {
boost::shared_ptr<IQ> iq(new IQ(IQ::Error));
iq->setID(id);
return iq;
}
private:
IQRouter* router_;
DummyIQChannel* channel_;
boost::shared_ptr<Payload> payload_;
boost::shared_ptr<Payload> responsePayload_;
int responsesReceived_;
std::vector<ErrorPayload> receivedErrors;
};
CPPUNIT_TEST_SUITE_REGISTRATION(RequestTest);