/* * 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 #include #include using namespace Swift; class EntityCapsManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(EntityCapsManagerTest); CPPUNIT_TEST(testReceiveKnownHash); CPPUNIT_TEST(testReceiveKnownHashTwiceDoesNotTriggerChange); CPPUNIT_TEST(testReceiveUnknownHashDoesNotTriggerChange); CPPUNIT_TEST(testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps); CPPUNIT_TEST(testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps); CPPUNIT_TEST(testReconnectTriggersChangeAndClearsCaps); CPPUNIT_TEST(testHashAvailable); CPPUNIT_TEST_SUITE_END(); public: void setUp() { crypto = std::shared_ptr(PlatformCryptoProvider::create()); stanzaChannel = new DummyStanzaChannel(); capsProvider = new DummyCapsProvider(); user1 = JID("user1@bar.com/bla"); discoInfo1 = std::make_shared(); discoInfo1->addFeature("http://swift.im/feature1"); capsInfo1 = std::make_shared(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); capsInfo1alt = std::make_shared(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); user2 = JID("user2@foo.com/baz"); discoInfo2 = std::make_shared(); discoInfo2->addFeature("http://swift.im/feature2"); capsInfo2 = std::make_shared(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); user3 = JID("user3@foo.com/baz"); legacyCapsInfo = std::make_shared("http://swift.im", "ver1", ""); } void tearDown() { delete capsProvider; delete stanzaChannel; } void testReceiveKnownHash() { std::shared_ptr testling = createManager(); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; sendPresenceWithCaps(user1, capsInfo1); CPPUNIT_ASSERT_EQUAL(1, static_cast(changes.size())); CPPUNIT_ASSERT_EQUAL(user1, changes[0]); CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); } void testReceiveKnownHashTwiceDoesNotTriggerChange() { std::shared_ptr testling = createManager(); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; sendPresenceWithCaps(user1, capsInfo1); changes.clear(); sendPresenceWithCaps(user1, capsInfo1); CPPUNIT_ASSERT_EQUAL(0, static_cast(changes.size())); } void testReceiveUnknownHashDoesNotTriggerChange() { std::shared_ptr testling = createManager(); sendPresenceWithCaps(user1, capsInfo1); CPPUNIT_ASSERT_EQUAL(0, static_cast(changes.size())); } void testHashAvailable() { std::shared_ptr testling = createManager(); sendPresenceWithCaps(user1, capsInfo1); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; capsProvider->onCapsAvailable(capsInfo1->getVersion()); CPPUNIT_ASSERT_EQUAL(1, static_cast(changes.size())); CPPUNIT_ASSERT_EQUAL(user1, changes[0]); CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); } void testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps() { std::shared_ptr testling = createManager(); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; sendPresenceWithCaps(user1, capsInfo1); changes.clear(); sendPresenceWithCaps(user1, capsInfo2); CPPUNIT_ASSERT_EQUAL(1, static_cast(changes.size())); CPPUNIT_ASSERT_EQUAL(user1, changes[0]); CPPUNIT_ASSERT(!testling->getCaps(user1)); } void testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps() { std::shared_ptr testling = createManager(); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; sendPresenceWithCaps(user1, capsInfo1); changes.clear(); sendUnavailablePresence(user1); CPPUNIT_ASSERT_EQUAL(1, static_cast(changes.size())); CPPUNIT_ASSERT_EQUAL(user1, changes[0]); CPPUNIT_ASSERT(!testling->getCaps(user1)); } void testReconnectTriggersChangeAndClearsCaps() { std::shared_ptr testling = createManager(); capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; capsProvider->caps[capsInfo2->getVersion()] = discoInfo2; sendPresenceWithCaps(user1, capsInfo1); sendPresenceWithCaps(user2, capsInfo2); changes.clear(); stanzaChannel->setAvailable(false); stanzaChannel->setAvailable(true); CPPUNIT_ASSERT_EQUAL(2, static_cast(changes.size())); CPPUNIT_ASSERT_EQUAL(user1, changes[0]); CPPUNIT_ASSERT(!testling->getCaps(user1)); CPPUNIT_ASSERT_EQUAL(user2, changes[1]); CPPUNIT_ASSERT(!testling->getCaps(user2)); } private: std::shared_ptr createManager() { std::shared_ptr manager(new EntityCapsManager(capsProvider, stanzaChannel)); manager->onCapsChanged.connect(boost::bind(&EntityCapsManagerTest::handleCapsChanged, this, _1)); return manager; } void handleCapsChanged(const JID& jid) { changes.push_back(jid); } void sendPresenceWithCaps(const JID& jid, std::shared_ptr caps) { std::shared_ptr presence(new Presence()); presence->setFrom(jid); presence->addPayload(caps); stanzaChannel->onPresenceReceived(presence); } void sendUnavailablePresence(const JID& jid) { std::shared_ptr presence(new Presence()); presence->setFrom(jid); presence->setType(Presence::Unavailable); stanzaChannel->onPresenceReceived(presence); } private: struct DummyCapsProvider : public CapsProvider { virtual DiscoInfo::ref getCaps(const std::string& hash) const { std::map::const_iterator i = caps.find(hash); if (i != caps.end()) { return i->second; } return DiscoInfo::ref(); } std::map caps; }; private: DummyStanzaChannel* stanzaChannel; DummyCapsProvider* capsProvider; JID user1; std::shared_ptr discoInfo1; std::shared_ptr capsInfo1; std::shared_ptr capsInfo1alt; JID user2; std::shared_ptr discoInfo2; std::shared_ptr capsInfo2; std::shared_ptr legacyCapsInfo; JID user3; std::vector changes; std::shared_ptr crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(EntityCapsManagerTest);