From 907fdbdab74b72cc4fde2425dc9b2d4d461daf66 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Fri, 16 Oct 2015 12:10:09 +0200 Subject: Add additional unit tests for Chat <-> JID binding The recent commit 582ca91 changed the behavior the binding between chat sessions and the full JID of a chat contact. This commit adds additional unit tests verifying the behavior of implemented in 582ca91. This means a chat session binds to the full JID of an incoming message only if the message has a non-empty body text or is a 'typing' chat state notification. It also tests the rebind to another resource if a 'typing'-CSN or a body message is received from that resource. Test-Information: All unit tests pass on OS X 10.10.5. Change-Id: Id3f25d8a3ff78c407ed4b2a97bd421dc4aa58688 diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index cf3253a..487f0f9 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010-2012 Isode Limited. + * Copyright (c) 2010-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ +#include + #include #include - #include -#include - #include #include #include @@ -20,8 +19,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -33,12 +31,11 @@ #include #include #include -#include #include #include -#include #include +#include #include #include #include @@ -58,13 +55,8 @@ #include #include - using namespace Swift; -class DummyCapsProvider : public CapsProvider { - DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());} -}; - class ChatsManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ChatsManagerTest); CPPUNIT_TEST(testFirstOpenWindowIncoming); @@ -79,6 +71,8 @@ class ChatsManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnAddToRoster); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom); + CPPUNIT_TEST(testChatControllerFullJIDBindingOnMessageAndNotReceipt); + CPPUNIT_TEST(testChatControllerFullJIDBindingOnTypingAndNotActive); CPPUNIT_TEST_SUITE_END(); public: @@ -88,7 +82,7 @@ public: stanzaChannel_ = new DummyStanzaChannel(); iqChannel_ = new DummyIQChannel(); iqRouter_ = new IQRouter(iqChannel_); - capsProvider_ = new DummyCapsProvider(); +// capsProvider_ = new DummyCapsProvider(); eventController_ = new EventController(); chatWindowFactory_ = mocks_->InterfaceMock(); joinMUCWindowFactory_ = mocks_->InterfaceMock(); @@ -101,7 +95,8 @@ public: directedPresenceSender_ = new DirectedPresenceSender(presenceSender_); mucManager_ = new MUCManager(stanzaChannel_, iqRouter_, directedPresenceSender_, mucRegistry_); uiEventStream_ = new UIEventStream(); - entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_); +// entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_); + entityCapsProvider_ = new DummyEntityCapsProvider(); chatListWindowFactory_ = mocks_->InterfaceMock(); mucSearchWindowFactory_ = mocks_->InterfaceMock(); settings_ = new DummySettingsProvider(); @@ -110,7 +105,7 @@ public: ftManager_ = new DummyFileTransferManager(); ftOverview_ = new FileTransferOverview(ftManager_); avatarManager_ = new NullAvatarManager(); - wbSessionManager_ = new WhiteboardSessionManager(iqRouter_, stanzaChannel_, presenceOracle_, entityCapsManager_); + wbSessionManager_ = new WhiteboardSessionManager(iqRouter_, stanzaChannel_, presenceOracle_, entityCapsProvider_); wbManager_ = new WhiteboardManager(whiteboardWindowFactory_, uiEventStream_, nickResolver_, wbSessionManager_); highlightManager_ = new HighlightManager(settings_); @@ -119,7 +114,7 @@ public: vcardManager_ = new VCardManager(jid_, iqRouter_, vcardStorage_); mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(chatListWindow_); clientBlockListManager_ = new ClientBlockListManager(iqRouter_); - manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, NULL, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, NULL, vcardManager_); + manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsProvider_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, NULL, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, NULL, vcardManager_); manager_->setAvatarManager(avatarManager_); } @@ -150,8 +145,7 @@ public: delete uiEventStream_; delete mucManager_; delete xmppRoster_; - delete entityCapsManager_; - delete capsProvider_; + delete entityCapsProvider_; delete chatListWindow_; delete mocks_; delete settings_; @@ -429,6 +423,225 @@ public: testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::To, RosterItemPayload::From); } + void testChatControllerFullJIDBindingOnMessageAndNotReceipt() { + JID ownJID("test@test.com/resource"); + JID sender("foo@test.com"); + std::vector senderResource; + senderResource.push_back(sender.withResource("resourceA")); + senderResource.push_back(sender.withResource("resourceB")); + + // We support delivery receipts. + settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true); + + // Open chat window to a sender. + MockChatWindow* window = new MockChatWindow(); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(sender, uiEventStream_).Return(window); + + uiEventStream_->send(boost::make_shared(sender)); + + foreach(const JID& senderJID, senderResource) { + // The sender supports delivery receipts. + DiscoInfo::ref disco = boost::make_shared(); + disco->addFeature(DiscoInfo::MessageDeliveryReceiptsFeature); + entityCapsProvider_->caps[senderJID] = disco; + + // The sender is online. + Presence::ref senderPresence = boost::make_shared(); + senderPresence->setFrom(senderJID); + senderPresence->setTo(ownJID); + stanzaChannel_->onPresenceReceived(senderPresence); + + entityCapsProvider_->onCapsChanged(senderJID); + } + + // Send first message. + window->onSendMessageRequest("hello there", false); + + // A bare message is send because no resources is bound. + CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex(0)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(0)->getPayload()); + + // Two resources respond with message receipts. + foreach(const JID& senderJID, senderResource) { + Message::ref receiptReply = boost::make_shared(); + receiptReply->setFrom(senderJID); + receiptReply->setTo(ownJID); + + boost::shared_ptr receipt = boost::make_shared(); + receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex(0)->getID()); + receiptReply->addPayload(receipt); + manager_->handleIncomingMessage(receiptReply); + } + + // Send second message. + window->onSendMessageRequest("how are you?", false); + + // A bare message is send because no resources is bound. + CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex(1)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(1)->getPayload()); + + // Two resources respond with message receipts. + foreach(const JID& senderJID, senderResource) { + Message::ref receiptReply = boost::make_shared(); + receiptReply->setFrom(senderJID); + receiptReply->setTo(ownJID); + + boost::shared_ptr receipt = boost::make_shared(); + receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex(1)->getID()); + receiptReply->addPayload(receipt); + manager_->handleIncomingMessage(receiptReply); + } + + // Reply with a message including a body text. + Message::ref reply = boost::make_shared(); + reply->setFrom(senderResource[0]); + reply->setTo(ownJID); + reply->setBody("fine."); + manager_->handleIncomingMessage(reply); + + // Send third message. + window->onSendMessageRequest("great to hear.", false); + + // The chat session is bound to the full JID of the first resource. + CPPUNIT_ASSERT_EQUAL(senderResource[0], stanzaChannel_->getStanzaAtIndex(2)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(2)->getPayload()); + + // Receive random receipt from second sender resource. + reply = boost::make_shared(); + reply->setFrom(senderResource[1]); + reply->setTo(ownJID); + + boost::shared_ptr receipt = boost::make_shared(); + receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex(2)->getID()); + reply->addPayload(receipt); + manager_->handleIncomingMessage(reply); + + // Send forth message. + window->onSendMessageRequest("what else is new?", false); + + // The chat session is bound to the full JID of the first resource. + CPPUNIT_ASSERT_EQUAL(senderResource[0], stanzaChannel_->getStanzaAtIndex(3)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(3)->getPayload()); + + // Reply with a message including a body text from second resource. + reply = boost::make_shared(); + reply->setFrom(senderResource[1]); + reply->setTo(ownJID); + reply->setBody("nothing."); + manager_->handleIncomingMessage(reply); + + // Send fifth message. + window->onSendMessageRequest("okay", false); + + // The chat session is now bound to the full JID of the second resource. + CPPUNIT_ASSERT_EQUAL(senderResource[1], stanzaChannel_->getStanzaAtIndex(4)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(4)->getPayload()); + } + + void testChatControllerFullJIDBindingOnTypingAndNotActive() { + JID ownJID("test@test.com/resource"); + JID sender("foo@test.com"); + std::vector senderResource; + senderResource.push_back(sender.withResource("resourceA")); + senderResource.push_back(sender.withResource("resourceB")); + + // We support delivery receipts. + settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true); + + // Open chat window to a sender. + MockChatWindow* window = new MockChatWindow(); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(sender, uiEventStream_).Return(window); + + uiEventStream_->send(boost::make_shared(sender)); + + foreach(const JID& senderJID, senderResource) { + // The sender supports delivery receipts. + DiscoInfo::ref disco = boost::make_shared(); + disco->addFeature(DiscoInfo::MessageDeliveryReceiptsFeature); + entityCapsProvider_->caps[senderJID] = disco; + + // The sender is online. + Presence::ref senderPresence = boost::make_shared(); + senderPresence->setFrom(senderJID); + senderPresence->setTo(ownJID); + stanzaChannel_->onPresenceReceived(senderPresence); + + entityCapsProvider_->onCapsChanged(senderJID); + } + + // Send first message. + window->onSendMessageRequest("hello there", false); + + // A bare message is send because no resources is bound. + CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex(0)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(0)->getPayload()); + + // Two resources respond with message receipts. + foreach(const JID& senderJID, senderResource) { + Message::ref reply = boost::make_shared(); + reply->setFrom(senderJID); + reply->setTo(ownJID); + + boost::shared_ptr csn = boost::make_shared(); + csn->setChatState(ChatState::Active); + reply->addPayload(csn); + manager_->handleIncomingMessage(reply); + } + + // Send second message. + window->onSendMessageRequest("how are you?", false); + + // A bare message is send because no resources is bound. + CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex(1)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(1)->getPayload()); + + // Two resources respond with message receipts. + foreach(const JID& senderJID, senderResource) { + Message::ref receiptReply = boost::make_shared(); + receiptReply->setFrom(senderJID); + receiptReply->setTo(ownJID); + + boost::shared_ptr receipt = boost::make_shared(); + receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex(1)->getID()); + receiptReply->addPayload(receipt); + manager_->handleIncomingMessage(receiptReply); + } + + // Reply with a message including a CSN. + Message::ref reply = boost::make_shared(); + reply->setFrom(senderResource[0]); + reply->setTo(ownJID); + + boost::shared_ptr csn = boost::make_shared(); + csn->setChatState(ChatState::Composing); + reply->addPayload(csn); + manager_->handleIncomingMessage(reply); + + // Send third message. + window->onSendMessageRequest("great to hear.", false); + + // The chat session is now bound to the full JID of the first resource due to its recent composing message. + CPPUNIT_ASSERT_EQUAL(senderResource[0], stanzaChannel_->getStanzaAtIndex(2)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(2)->getPayload()); + + // Reply with a message including a CSN from the other resource. + reply = boost::make_shared(); + reply->setFrom(senderResource[1]); + reply->setTo(ownJID); + + csn = boost::make_shared(); + csn->setChatState(ChatState::Composing); + reply->addPayload(csn); + manager_->handleIncomingMessage(reply); + + // Send third message. + window->onSendMessageRequest("ping.", false); + + // The chat session is now bound to the full JID of the second resource due to its recent composing message. + CPPUNIT_ASSERT_EQUAL(senderResource[1], stanzaChannel_->getStanzaAtIndex(3)->getTo()); + CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex(3)->getPayload()); + } + void testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::Subscription from, RosterItemPayload::Subscription to) { JID messageJID("testling@test.com/resource1"); xmppRoster_->addContact(messageJID, "foo", std::vector(), from); @@ -487,8 +700,7 @@ private: MUCSearchWindowFactory* mucSearchWindowFactory_; MUCRegistry* mucRegistry_; DirectedPresenceSender* directedPresenceSender_; - EntityCapsManager* entityCapsManager_; - CapsProvider* capsProvider_; + DummyEntityCapsProvider* entityCapsProvider_; MUCManager* mucManager_; DummySettingsProvider* settings_; ProfileSettingsProvider* profileSettings_; -- cgit v0.10.2-6-g49f6