diff options
author | Tobias Markmann <tm@ayena.de> | 2016-04-21 09:02:07 (GMT) |
---|---|---|
committer | Kevin Smith <kevin.smith@isode.com> | 2016-11-10 11:09:16 (GMT) |
commit | d2ba1ab8a36333523bf794c23226bd044e1717c2 (patch) | |
tree | 737ac14bc1dfcec4b80192ea23e7b0e860a2f8d3 /Swift/Controllers/Roster/UnitTest | |
parent | 41c771ec02682c2b344263d29f68eb6452c42dbe (diff) | |
download | swift-d2ba1ab8a36333523bf794c23226bd044e1717c2.zip swift-d2ba1ab8a36333523bf794c23226bd044e1717c2.tar.bz2 |
Use FeatureOracle to detect file-transfer support in roster
The FeatureOracle provides tri-state feature lookup
functionality for bare JIDs. It returns Yes if a feature is
supported by all resources of the bare JID, Maybe if some
support it, and No if none of the resources support it.
If passed a full JID, it returns the specific features supported
by that end-point.
Sending a file to a bare JID, will send a file to the resource
of the bare JID with the highest availability by presence, show
status and priority and which supports the features required
for a Jingle file-transfer.
Test-Information:
Added unit test verifying new behavior.
All tests pass on OS X 10.11.6. Added new unit tests for
FeatureOracle.
Manually verified that the roster and chat window both use
the same mechanism to detect support for file-transfers.
Manually verified that file-transfers via the contact list
goes to already bound full JIDs if there is an existing
ChatController.
Change-Id: I0175ac42ecb73f1d54f9c96ffbba773eb5e24296
Diffstat (limited to 'Swift/Controllers/Roster/UnitTest')
-rw-r--r-- | Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp | 135 |
1 files changed, 101 insertions, 34 deletions
diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp index 0cd4080..ddbd7d3 100644 --- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp +++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp @@ -12,13 +12,16 @@ #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/DummyNickManager.h> #include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Client/MemoryStorages.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Disco/CapsManager.h> #include <Swiften/Disco/CapsProvider.h> +#include <Swiften/Disco/ClientDiscoManager.h> #include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/MUC/MUCRegistry.h> #include <Swiften/Presence/PresenceOracle.h> @@ -29,7 +32,6 @@ #include <Swiften/VCards/VCardManager.h> #include <Swiften/VCards/VCardMemoryStorage.h> -#include <Swift/Controllers/FileTransfer/FileTransferOverview.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/Roster.h> @@ -42,8 +44,6 @@ using namespace Swift; -#define CHILDREN mainWindow_->roster->getRoot()->getChildren() - class DummyCapsProvider : public CapsProvider { DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());} }; @@ -61,6 +61,7 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_TEST(testUnavailablePresence); CPPUNIT_TEST(testRemoveResultsInUnavailablePresence); CPPUNIT_TEST(testOwnContactInRosterPresence); + CPPUNIT_TEST(testMultiResourceFileTransferFeature); CPPUNIT_TEST_SUITE_END(); public: @@ -70,6 +71,8 @@ class RosterControllerTest : public CppUnit::TestFixture { avatarManager_ = new NullAvatarManager(); mainWindowFactory_ = new MockMainWindowFactory(); mucRegistry_ = new MUCRegistry(); + crypto_ = PlatformCryptoProvider::create(); + storages_ = std::unique_ptr<MemoryStorages>(new MemoryStorages(crypto_)); nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, nullptr, mucRegistry_); channel_ = new DummyIQChannel(); router_ = new IQRouter(channel_); @@ -80,18 +83,16 @@ class RosterControllerTest : public CppUnit::TestFixture { uiEventStream_ = new UIEventStream(); settings_ = new DummySettingsProvider(); nickManager_ = new DummyNickManager(); - capsProvider_ = new DummyCapsProvider(); - entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_); + capsManager_ = std::unique_ptr<CapsManager>(new CapsManager(storages_->getCapsStorage(), stanzaChannel_, router_, crypto_)); + entityCapsManager_ = new EntityCapsManager(capsManager_.get(), stanzaChannel_); jingleSessionManager_ = new JingleSessionManager(router_); - ftManager_ = new DummyFileTransferManager(); - ftOverview_ = new FileTransferOverview(ftManager_); clientBlockListManager_ = new ClientBlockListManager(router_); - crypto_ = PlatformCryptoProvider::create(); vcardStorage_ = new VCardMemoryStorage(crypto_); vcardManager_ = new VCardManager(jid_, router_, vcardStorage_); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, ftOverview_, clientBlockListManager_, vcardManager_); + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, clientBlockListManager_, vcardManager_); mainWindow_ = mainWindowFactory_->last; + capsInfoGenerator_ = std::unique_ptr<CapsInfoGenerator>(new CapsInfoGenerator("", crypto_)); } void tearDown() { @@ -100,11 +101,8 @@ class RosterControllerTest : public CppUnit::TestFixture { delete vcardStorage_; delete crypto_; delete clientBlockListManager_; - delete ftOverview_; - delete ftManager_; delete jingleSessionManager_; delete entityCapsManager_; - delete capsProvider_; delete nickManager_; delete nickResolver_; delete mucRegistry_; @@ -122,7 +120,7 @@ class RosterControllerTest : public CppUnit::TestFixture { } GroupRosterItem* groupChild(size_t i) { - return dynamic_cast<GroupRosterItem*>(CHILDREN[i]); + return dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[i]); } JID withResource(const JID& jid, const std::string& resource) { @@ -140,10 +138,10 @@ class RosterControllerTest : public CppUnit::TestFixture { presence->setPriority(2); presence->setStatus("So totally here"); stanzaChannel_->onPresenceReceived(presence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item->getStatusText()); - ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[1])->getChildren()[0]); + ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[1])->getChildren()[0]); CPPUNIT_ASSERT(item2); CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); } @@ -163,7 +161,7 @@ class RosterControllerTest : public CppUnit::TestFixture { highPresence->setStatus("So totally here"); stanzaChannel_->onPresenceReceived(lowPresence); stanzaChannel_->onPresenceReceived(highPresence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); } @@ -183,7 +181,7 @@ class RosterControllerTest : public CppUnit::TestFixture { highPresence->setStatus("So totally here"); stanzaChannel_->onPresenceReceived(highPresence); stanzaChannel_->onPresenceReceived(lowPresence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(highPresence->getStatus(), item->getStatusText()); } @@ -223,7 +221,7 @@ class RosterControllerTest : public CppUnit::TestFixture { stanzaChannel_->onPresenceReceived(highPresenceOffline); // After this, the roster should show the low presence. - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); Presence::ref low = presenceOracle_->getAccountPresence(from); @@ -233,7 +231,7 @@ class RosterControllerTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(lowPresence->getShow(), item->getStatusShow()); CPPUNIT_ASSERT_EQUAL(lowPresence->getStatus(), item->getStatusText()); stanzaChannel_->onPresenceReceived(lowPresenceOffline); - item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); /* A verification that if the test fails, it's the RosterController, not the PresenceOracle. */ low = presenceOracle_->getHighestPriorityPresence(from); @@ -249,7 +247,7 @@ class RosterControllerTest : public CppUnit::TestFixture { groups.push_back("testGroup2"); xmppRoster_->addContact(JID("test@testdomain.com/bob"), "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(getUIRosterChildren().size())); //CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(JID("foo@bar.com"))); } @@ -258,14 +256,14 @@ class RosterControllerTest : public CppUnit::TestFixture { JID jid("test@testdomain.com"); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::None); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::To); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); } @@ -275,11 +273,11 @@ class RosterControllerTest : public CppUnit::TestFixture { JID jid("test@testdomain.com"); xmppRoster_->addContact(jid, "name", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(std::string("name"), groupChild(0)->getChildren()[0]->getDisplayName()); xmppRoster_->addContact(jid, "NewName", groups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(std::string("NewName"), groupChild(0)->getChildren()[0]->getDisplayName()); } @@ -293,18 +291,18 @@ class RosterControllerTest : public CppUnit::TestFixture { JID jid("test@testdomain.com"); xmppRoster_->addContact(jid, "", oldGroups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(jid.toString(), groupChild(0)->getChildren()[0]->getDisplayName()); xmppRoster_->addContact(jid, "new name", newGroups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); CPPUNIT_ASSERT_EQUAL(std::string("A Group"), groupChild(0)->getDisplayName()); xmppRoster_->addContact(jid, "new name", newestGroups, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(CHILDREN.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(getUIRosterChildren().size())); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(groupChild(0)->getChildren().size())); CPPUNIT_ASSERT_EQUAL(std::string("new name"), groupChild(0)->getChildren()[0]->getDisplayName()); CPPUNIT_ASSERT_EQUAL(std::string("Best Group"), groupChild(0)->getDisplayName()); @@ -364,14 +362,79 @@ class RosterControllerTest : public CppUnit::TestFixture { presence->setPriority(2); presence->setStatus("So totally here"); stanzaChannel_->onPresenceReceived(presence); - ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[0])->getChildren()[0]); + ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); CPPUNIT_ASSERT(item); CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item->getStatusText()); - ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(CHILDREN[1])->getChildren()[0]); + ContactRosterItem* item2 = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[1])->getChildren()[0]); CPPUNIT_ASSERT(item2); CPPUNIT_ASSERT_EQUAL(presence->getStatus(), item2->getStatusText()); } + // This tests a scenario of a contact having a resource supporting Jingle File Transfer and + // one resource not supporting it, and the contact features being set correctly. + void testMultiResourceFileTransferFeature() { + JID contact("test@testdomain.com"); + xmppRoster_->addContact(contact, "Name", {}, RosterItemPayload::Both); + + auto sendPresenceAndAnswerCaps = [=](const JID& from, const DiscoInfo& discoInfo) { + auto capsInfo = capsInfoGenerator_->generateCapsInfo(discoInfo); + + auto ftClientPresence = std::make_shared<Presence>(); + ftClientPresence->setFrom(from); + ftClientPresence->setPriority(0); + ftClientPresence->setShow(StatusShow::Online); + ftClientPresence->addPayload(std::make_shared<CapsInfo>(capsInfo)); + stanzaChannel_->onPresenceReceived(ftClientPresence); + + // disco reply + auto discoRequest = channel_->iqs_.back(); + CPPUNIT_ASSERT(discoRequest); + auto discoReply = IQ::createResult(discoRequest->getFrom(), ftClientPresence->getFrom(), discoRequest->getID(), std::make_shared<DiscoInfo>(discoInfo)); + channel_->onIQReceived(discoReply); + }; + + auto ftDiscoInfo = DiscoInfo(); + ftDiscoInfo.addFeature(DiscoInfo::JingleFeature); + ftDiscoInfo.addFeature(DiscoInfo::JingleFTFeature); + ftDiscoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + + sendPresenceAndAnswerCaps(contact.withResource("ft-supported"), ftDiscoInfo); + + auto* item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + sendPresenceAndAnswerCaps(contact.withResource("ft-unsupported"), DiscoInfo()); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + auto unavailablePresence = std::make_shared<Presence>(); + unavailablePresence->setFrom(contact.withResource("ft-unsupported")); + unavailablePresence->setPriority(0); + unavailablePresence->setType(Presence::Unavailable); + stanzaChannel_->onPresenceReceived(unavailablePresence); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(true, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + + unavailablePresence = std::make_shared<Presence>(); + unavailablePresence->setFrom(contact.withResource("ft-supported")); + unavailablePresence->setPriority(0); + unavailablePresence->setType(Presence::Unavailable); + stanzaChannel_->onPresenceReceived(unavailablePresence); + + item = dynamic_cast<ContactRosterItem*>(dynamic_cast<GroupRosterItem*>(getUIRosterChildren()[0])->getChildren()[0]); + CPPUNIT_ASSERT(item); + CPPUNIT_ASSERT_EQUAL(contact, item->getJID()); + CPPUNIT_ASSERT_EQUAL(false, item->supportsFeature(ContactRosterItem::FileTransferFeature)); + } + void assertVectorsEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2, int line) { for (const auto& entry : v1) { if (std::find(v2.begin(), v2.end(), entry) == v2.end()) { @@ -382,8 +445,13 @@ class RosterControllerTest : public CppUnit::TestFixture { } } + const std::vector<RosterItem*>& getUIRosterChildren() const { + return mainWindow_->roster->getRoot()->getChildren(); + } + private: JID jid_; + std::unique_ptr<MemoryStorages> storages_; XMPPRosterImpl* xmppRoster_; MUCRegistry* mucRegistry_; AvatarManager* avatarManager_; @@ -400,15 +468,14 @@ class RosterControllerTest : public CppUnit::TestFixture { UIEventStream* uiEventStream_; MockMainWindow* mainWindow_; DummySettingsProvider* settings_; - DummyCapsProvider* capsProvider_; + std::unique_ptr<CapsManager> capsManager_; EntityCapsManager* entityCapsManager_; JingleSessionManager* jingleSessionManager_; - FileTransferManager* ftManager_; - FileTransferOverview* ftOverview_; ClientBlockListManager* clientBlockListManager_; CryptoProvider* crypto_; VCardStorage* vcardStorage_; VCardManager* vcardManager_; + std::unique_ptr<CapsInfoGenerator> capsInfoGenerator_; }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest); |