/* * 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 "Swift/Controllers/PresenceNotifier.h" #include "Swiften/Client/NickResolver.h" #include "SwifTools/Notifier/LoggingNotifier.h" #include "Swiften/Client/DummyStanzaChannel.h" #include "Swiften/MUC/MUCRegistry.h" #include "Swiften/Roster/XMPPRosterImpl.h" #include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Avatars/DummyAvatarManager.h" #include "Swiften/Network/DummyTimerFactory.h" using namespace Swift; class PresenceNotifierTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PresenceNotifierTest); CPPUNIT_TEST(testReceiveFirstPresenceCreatesAvailableNotification); CPPUNIT_TEST(testReceiveSecondPresenceCreatesStatusChangeNotification); CPPUNIT_TEST(testReceiveUnavailablePresenceAfterAvailablePresenceCreatesUnavailableNotification); CPPUNIT_TEST(testReceiveUnavailablePresenceWithoutAvailableDoesNotCreateNotification); CPPUNIT_TEST(testReceiveAvailablePresenceAfterUnavailableCreatesAvailableNotification); CPPUNIT_TEST(testReceiveAvailablePresenceAfterReconnectCreatesAvailableNotification); CPPUNIT_TEST(testReceiveAvailablePresenceFromMUCDoesNotCreateNotification); CPPUNIT_TEST(testNotificationSubjectContainsNameForJIDInRoster); CPPUNIT_TEST(testNotificationSubjectContainsJIDForJIDNotInRoster); CPPUNIT_TEST(testNotificationSubjectContainsStatus); CPPUNIT_TEST(testNotificationMessageContainsStatusMessage); CPPUNIT_TEST(testNotificationPicture); CPPUNIT_TEST(testNotificationActivationEmitsSignal); CPPUNIT_TEST(testReceiveFirstPresenceWithQuietPeriodDoesNotNotify); CPPUNIT_TEST(testReceiveFirstPresenceWithQuietPeriodDoesNotCountAsQuietPeriod); CPPUNIT_TEST(testReceivePresenceDuringQuietPeriodDoesNotNotify); CPPUNIT_TEST(testReceivePresenceDuringQuietPeriodResetsTimer); CPPUNIT_TEST(testReceivePresenceAfterQuietPeriodNotifies); CPPUNIT_TEST(testReceiveFirstPresenceAfterReconnectWithQuietPeriodDoesNotNotify); CPPUNIT_TEST_SUITE_END(); public: void setUp() { stanzaChannel = new DummyStanzaChannel(); notifier = new LoggingNotifier(); mucRegistry = new MUCRegistry(); user1 = JID("user1@bar.com/bla"); user2 = JID("user2@foo.com/baz"); avatarManager = new DummyAvatarManager(); roster = new XMPPRosterImpl(); nickResolver = new NickResolver(JID("foo@bar.com"), roster, NULL, mucRegistry); presenceOracle = new PresenceOracle(stanzaChannel); timerFactory = new DummyTimerFactory(); } void tearDown() { delete timerFactory; delete presenceOracle; delete nickResolver; delete roster; delete avatarManager; delete mucRegistry; delete notifier; delete stanzaChannel; } void testReceiveFirstPresenceCreatesAvailableNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(Notifier::ContactAvailable, notifier->notifications[0].type); } void testReceiveSecondPresenceCreatesStatusChangeNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); notifier->notifications.clear(); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(Notifier::ContactStatusChange, notifier->notifications[0].type); } void testReceiveUnavailablePresenceAfterAvailablePresenceCreatesUnavailableNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); notifier->notifications.clear(); sendUnavailablePresence(user1); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(Notifier::ContactUnavailable, notifier->notifications[0].type); } void testReceiveUnavailablePresenceWithoutAvailableDoesNotCreateNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendUnavailablePresence(user1); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testReceiveAvailablePresenceAfterUnavailableCreatesAvailableNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); sendUnavailablePresence(user1); notifier->notifications.clear(); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(Notifier::ContactAvailable, notifier->notifications[0].type); } void testReceiveAvailablePresenceAfterReconnectCreatesAvailableNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); stanzaChannel->setAvailable(false); stanzaChannel->setAvailable(true); notifier->notifications.clear(); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(Notifier::ContactAvailable, notifier->notifications[0].type); } void testReceiveAvailablePresenceFromMUCDoesNotCreateNotification() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); mucRegistry->addMUC(JID("teaparty@wonderland.lit")); sendPresence(JID("teaparty@wonderland.lit/Alice"), StatusShow::Away); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testNotificationPicture() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); avatarManager->avatars[user1] = createByteArray("abcdef"); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT_EQUAL(boost::filesystem::path("/avatars/user1@bar.com/bla"), notifier->notifications[0].picture); } void testNotificationActivationEmitsSignal() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT(notifier->notifications[0].callback); notifier->notifications[0].callback(); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(activatedNotifications.size())); CPPUNIT_ASSERT_EQUAL(user1, activatedNotifications[0]); } void testNotificationSubjectContainsNameForJIDInRoster() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); roster->addContact(user1.toBare(), "User 1", std::vector<std::string>(), RosterItemPayload::Both); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); std::string subject = notifier->notifications[0].subject; CPPUNIT_ASSERT(subject.find("User 1") != std::string::npos); } void testNotificationSubjectContainsJIDForJIDNotInRoster() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); std::string subject = notifier->notifications[0].subject; CPPUNIT_ASSERT(subject.find(user1.toBare().toString()) != std::string::npos); } void testNotificationSubjectContainsStatus() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); std::string subject = notifier->notifications[0].subject; CPPUNIT_ASSERT(subject.find("Away") != std::string::npos); } void testNotificationMessageContainsStatusMessage() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); CPPUNIT_ASSERT(notifier->notifications[0].description.find("Status Message") != std::string::npos); } void testReceiveFirstPresenceWithQuietPeriodDoesNotNotify() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); sendPresence(user1, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testReceivePresenceDuringQuietPeriodDoesNotNotify() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); sendPresence(user1, StatusShow::Online); timerFactory->setTime(1); sendPresence(user2, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testReceivePresenceDuringQuietPeriodResetsTimer() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); sendPresence(user1, StatusShow::Online); timerFactory->setTime(9); sendPresence(user2, StatusShow::Away); timerFactory->setTime(18); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testReceivePresenceAfterQuietPeriodNotifies() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); sendPresence(user1, StatusShow::Online); timerFactory->setTime(11); sendPresence(user2, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(notifier->notifications.size())); } void testReceiveFirstPresenceWithQuietPeriodDoesNotCountAsQuietPeriod() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); timerFactory->setTime(11); sendPresence(user1, StatusShow::Away); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } void testReceiveFirstPresenceAfterReconnectWithQuietPeriodDoesNotNotify() { boost::shared_ptr<PresenceNotifier> testling = createNotifier(); testling->setInitialQuietPeriodMS(10); sendPresence(user1, StatusShow::Online); timerFactory->setTime(15); notifier->notifications.clear(); stanzaChannel->setAvailable(false); stanzaChannel->setAvailable(true); sendPresence(user1, StatusShow::Online); timerFactory->setTime(21); sendPresence(user2, StatusShow::Online); CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(notifier->notifications.size())); } private: boost::shared_ptr<PresenceNotifier> createNotifier() { boost::shared_ptr<PresenceNotifier> result(new PresenceNotifier(stanzaChannel, notifier, mucRegistry, avatarManager, nickResolver, presenceOracle, timerFactory)); result->onNotificationActivated.connect(boost::bind(&PresenceNotifierTest::handleNotificationActivated, this, _1)); result->setInitialQuietPeriodMS(0); return result; } void sendPresence(const JID& jid, StatusShow::Type type) { boost::shared_ptr<Presence> presence(new Presence()); presence->setFrom(jid); presence->setShow(type); presence->setStatus("Status Message"); stanzaChannel->onPresenceReceived(presence); } void sendUnavailablePresence(const JID& jid) { boost::shared_ptr<Presence> presence(new Presence()); presence->setType(Presence::Unavailable); presence->setFrom(jid); stanzaChannel->onPresenceReceived(presence); } void handleNotificationActivated(const JID& j) { activatedNotifications.push_back(j); } private: DummyStanzaChannel* stanzaChannel; LoggingNotifier* notifier; MUCRegistry* mucRegistry; DummyAvatarManager* avatarManager; XMPPRosterImpl* roster; NickResolver* nickResolver; PresenceOracle* presenceOracle; DummyTimerFactory* timerFactory; JID user1; JID user2; std::vector<JID> activatedNotifications; }; CPPUNIT_TEST_SUITE_REGISTRATION(PresenceNotifierTest);