/* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <memory> #include <boost/bind.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Presence/SubscriptionManager.h> #include <Swiften/Roster/XMPPRoster.h> #include <Swiften/Roster/XMPPRosterImpl.h> using namespace Swift; class PresenceOracleTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PresenceOracleTest); CPPUNIT_TEST(testReceivePresence); CPPUNIT_TEST(testReceivePresenceFromDifferentResources); CPPUNIT_TEST(testSubscriptionRequest); CPPUNIT_TEST(testReconnectResetsPresences); CPPUNIT_TEST(testHighestPresenceSingle); CPPUNIT_TEST(testHighestPresenceMultiple); CPPUNIT_TEST(testHighestPresenceGlobal); CPPUNIT_TEST(testHighestPresenceChangePriority); CPPUNIT_TEST(testGetActivePresence); CPPUNIT_TEST_SUITE_END(); public: void setUp() { stanzaChannel_ = new DummyStanzaChannel(); xmppRoster_ = new XMPPRosterImpl(); oracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_); oracle_->onPresenceChange.connect(boost::bind(&PresenceOracleTest::handlePresenceChange, this, _1)); subscriptionManager_ = new SubscriptionManager(stanzaChannel_); subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&PresenceOracleTest::handlePresenceSubscriptionRequest, this, _1, _2)); user1 = JID("user1@foo.com/Foo"); user1alt = JID("user1@foo.com/Bar"); user2 = JID("user2@bar.com/Bar"); } void tearDown() { delete subscriptionManager_; delete oracle_; delete xmppRoster_; delete stanzaChannel_; } void testHighestPresenceSingle() { JID bareJID("alice@wonderland.lit"); Presence::ref fiveOn = makeOnline("blah", 5); Presence::ref fiveOff = makeOffline("/blah"); CPPUNIT_ASSERT_EQUAL(Presence::ref(), oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOn); CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOff); CPPUNIT_ASSERT_EQUAL(fiveOff, oracle_->getHighestPriorityPresence(bareJID)); } void testHighestPresenceMultiple() { JID bareJID("alice@wonderland.lit"); Presence::ref fiveOn = makeOnline("blah", 5); Presence::ref fiveOff = makeOffline("/blah"); Presence::ref tenOn = makeOnline("bert", 10); Presence::ref tenOff = makeOffline("/bert"); stanzaChannel_->onPresenceReceived(fiveOn); stanzaChannel_->onPresenceReceived(tenOn); CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOff); CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOn); stanzaChannel_->onPresenceReceived(tenOff); CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); } void testHighestPresenceGlobal() { JID bareJID("alice@wonderland.lit"); Presence::ref fiveOn = makeOnline("blah", 5); Presence::ref fiveOff = makeOffline("/blah"); Presence::ref tenOn = makeOnline("bert", 10); Presence::ref allOff = makeOffline(""); stanzaChannel_->onPresenceReceived(fiveOn); stanzaChannel_->onPresenceReceived(tenOn); stanzaChannel_->onPresenceReceived(allOff); CPPUNIT_ASSERT_EQUAL(allOff, oracle_->getHighestPriorityPresence(bareJID)); } void testHighestPresenceChangePriority() { JID bareJID("alice@wonderland.lit"); Presence::ref fiveOn = makeOnline("blah", 5); Presence::ref fiveOff = makeOffline("/blah"); Presence::ref tenOn = makeOnline("bert", 10); Presence::ref tenOnThree = makeOnline("bert", 3); Presence::ref tenOff = makeOffline("/bert"); stanzaChannel_->onPresenceReceived(fiveOn); stanzaChannel_->onPresenceReceived(tenOn); stanzaChannel_->onPresenceReceived(tenOnThree); CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOff); CPPUNIT_ASSERT_EQUAL(tenOnThree, oracle_->getHighestPriorityPresence(bareJID)); stanzaChannel_->onPresenceReceived(fiveOn); CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); } void testReceivePresence() { std::shared_ptr<Presence> sentPresence(createPresence(user1)); stanzaChannel_->onPresenceReceived(sentPresence); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(subscriptionRequests.size())); CPPUNIT_ASSERT_EQUAL(sentPresence, changes[0]); CPPUNIT_ASSERT_EQUAL(sentPresence, oracle_->getLastPresence(user1)); } void testReceivePresenceFromDifferentResources() { std::shared_ptr<Presence> sentPresence1(createPresence(user1)); std::shared_ptr<Presence> sentPresence2(createPresence(user1alt)); stanzaChannel_->onPresenceReceived(sentPresence1); stanzaChannel_->onPresenceReceived(sentPresence2); CPPUNIT_ASSERT_EQUAL(sentPresence1, oracle_->getLastPresence(user1)); CPPUNIT_ASSERT_EQUAL(sentPresence2, oracle_->getLastPresence(user1alt)); } void testSubscriptionRequest() { std::string reasonText = "Because I want to"; JID sentJID = JID("me@example.com"); std::shared_ptr<Presence> sentPresence(new Presence()); sentPresence->setType(Presence::Subscribe); sentPresence->setFrom(sentJID); sentPresence->setStatus(reasonText); stanzaChannel_->onPresenceReceived(sentPresence); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(subscriptionRequests.size())); CPPUNIT_ASSERT_EQUAL(sentJID, subscriptionRequests[0].jid); CPPUNIT_ASSERT_EQUAL(reasonText, subscriptionRequests[0].reason); } void testReconnectResetsPresences() { std::shared_ptr<Presence> sentPresence(createPresence(user1)); stanzaChannel_->onPresenceReceived(sentPresence); stanzaChannel_->setAvailable(false); stanzaChannel_->setAvailable(true); CPPUNIT_ASSERT(!oracle_->getLastPresence(user1)); } void testGetActivePresence() { { std::vector<Presence::ref> presenceList; presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 10, Presence::Available, StatusShow::Away)); presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 5, Presence::Available, StatusShow::Online)); CPPUNIT_ASSERT_EQUAL(StatusShow::Online, PresenceOracle::getActivePresence(presenceList)->getShow()); } { std::vector<Presence::ref> presenceList; presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 10, Presence::Available, StatusShow::Away)); presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 5, Presence::Available, StatusShow::DND)); CPPUNIT_ASSERT_EQUAL(StatusShow::DND, PresenceOracle::getActivePresence(presenceList)->getShow()); } { std::vector<Presence::ref> presenceList; presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 0, Presence::Available, StatusShow::Online)); presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 0, Presence::Available, StatusShow::DND)); CPPUNIT_ASSERT_EQUAL(StatusShow::Online, PresenceOracle::getActivePresence(presenceList)->getShow()); } { std::vector<Presence::ref> presenceList; presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 1, Presence::Available, StatusShow::Online)); presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 0, Presence::Available, StatusShow::Online)); CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/resourceA"), PresenceOracle::getActivePresence(presenceList)->getFrom()); } } private: Presence::ref createPresence(const JID &jid, int priority, Presence::Type type, const StatusShow::Type& statusShow) { Presence::ref presence = std::make_shared<Presence>(); presence->setFrom(jid); presence->setPriority(priority); presence->setType(type); presence->setShow(statusShow); return presence; } Presence::ref makeOnline(const std::string& resource, int priority) { Presence::ref presence(new Presence()); presence->setPriority(priority); presence->setFrom(JID("alice@wonderland.lit/" + resource)); return presence; } Presence::ref makeOffline(const std::string& resource) { Presence::ref presence(new Presence()); presence->setFrom(JID("alice@wonderland.lit" + resource)); presence->setType(Presence::Unavailable); return presence; } void handlePresenceChange(std::shared_ptr<Presence> newPresence) { changes.push_back(newPresence); } void handlePresenceSubscriptionRequest(const JID& jid, const std::string& reason) { SubscriptionRequestInfo subscriptionRequest; subscriptionRequest.jid = jid; subscriptionRequest.reason = reason; subscriptionRequests.push_back(subscriptionRequest); } std::shared_ptr<Presence> createPresence(const JID& jid) { std::shared_ptr<Presence> sentPresence(new Presence("blarb")); sentPresence->setFrom(jid); return sentPresence; } private: struct SubscriptionRequestInfo { JID jid; std::string reason; }; PresenceOracle* oracle_; SubscriptionManager* subscriptionManager_; DummyStanzaChannel* stanzaChannel_; XMPPRoster* xmppRoster_; std::vector<Presence::ref> changes; std::vector<SubscriptionRequestInfo> subscriptionRequests; JID user1; JID user1alt; JID user2; }; CPPUNIT_TEST_SUITE_REGISTRATION(PresenceOracleTest);