diff options
Diffstat (limited to 'Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp')
| -rw-r--r-- | Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp | 165 | 
1 files changed, 158 insertions, 7 deletions
| diff --git a/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp b/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp index 50b0adb..715b7fc 100644 --- a/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp +++ b/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp @@ -5,35 +5,48 @@   */  #include <cppunit/extensions/HelperMacros.h>  #include <cppunit/extensions/TestFactoryRegistry.h>  #include <boost/bind.hpp>  #include <Swiften/JID/JID.h>  #include <string>  #include <Swiften/Avatars/CombinedAvatarProvider.h> +#include <Swiften/Avatars/VCardAvatarManager.h> +#include <Swiften/Avatars/OfflineAvatarManager.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Avatars/AvatarMemoryStorage.h> +#include <Swiften/VCards/VCardMemoryStorage.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/Avatars/VCardUpdateAvatarManager.h> +#include <Swiften/StringCodecs/Hexify.h>  using namespace Swift;  class CombinedAvatarProviderTest : public CppUnit::TestFixture {  		CPPUNIT_TEST_SUITE(CombinedAvatarProviderTest);  		CPPUNIT_TEST(testGetAvatarWithNoAvatarProviderReturnsEmpty);  		CPPUNIT_TEST(testGetAvatarWithSingleAvatarProvider);  		CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar);  		CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar);  		CPPUNIT_TEST(testProviderUpdateTriggersChange);  		CPPUNIT_TEST(testProviderUpdateWithoutChangeDoesNotTriggerChange);  		CPPUNIT_TEST(testProviderSecondUpdateTriggersChange);  		CPPUNIT_TEST(testProviderUpdateWithAvatarDisappearingTriggersChange);  		CPPUNIT_TEST(testProviderUpdateAfterAvatarDisappearedTriggersChange);  		CPPUNIT_TEST(testProviderUpdateAfterGetDoesNotTriggerChange);  		CPPUNIT_TEST(testProviderUpdateBareJIDAfterGetFullJID);  		CPPUNIT_TEST(testRemoveProviderDisconnectsUpdates); +		CPPUNIT_TEST(testAddRemoveFallthrough);  		CPPUNIT_TEST_SUITE_END();  	public:  		void setUp() {  			avatarProvider1 = new DummyAvatarProvider();  			avatarProvider2 = new DummyAvatarProvider();  			user1 = JID("user1@bar.com/bla");  			user2 = JID("user2@foo.com/baz");  			avatarHash1 = "ABCDEFG"; @@ -43,46 +56,53 @@ class CombinedAvatarProviderTest : public CppUnit::TestFixture {  		void tearDown() {  			delete avatarProvider1;  			delete avatarProvider2;  		}  		void testGetAvatarWithNoAvatarProviderReturnsEmpty() {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); -			CPPUNIT_ASSERT(testling->getAvatarHash(user1).empty()); +			boost::optional<std::string> hash = testling->getAvatarHash(user1); +			CPPUNIT_ASSERT(!hash);  		}  		void testGetAvatarWithSingleAvatarProvider() {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());  			avatarProvider1->avatars[user1] = avatarHash1;  			testling->addProvider(avatarProvider1); -			CPPUNIT_ASSERT_EQUAL(avatarHash1, testling->getAvatarHash(user1)); +			boost::optional<std::string> hash = testling->getAvatarHash(user1); +			CPPUNIT_ASSERT(hash); +			CPPUNIT_ASSERT_EQUAL(avatarHash1, *hash);  		}  		void testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar() {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());  			avatarProvider1->avatars[user1] = avatarHash1;  			avatarProvider2->avatars[user1] = avatarHash2;  			testling->addProvider(avatarProvider1);  			testling->addProvider(avatarProvider2); -			CPPUNIT_ASSERT_EQUAL(avatarHash1, testling->getAvatarHash(user1)); +			boost::optional<std::string> hash = testling->getAvatarHash(user1); +			CPPUNIT_ASSERT(hash); +			CPPUNIT_ASSERT_EQUAL(avatarHash1, *hash);  		}  		void testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar() {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());  			avatarProvider2->avatars[user1] = avatarHash2;  			testling->addProvider(avatarProvider1);  			testling->addProvider(avatarProvider2); -			CPPUNIT_ASSERT_EQUAL(avatarHash2, testling->getAvatarHash(user1)); +			boost::optional<std::string> hash = testling->getAvatarHash(user1); +			CPPUNIT_ASSERT(hash); +			CPPUNIT_ASSERT_EQUAL(avatarHash2, *hash);  		}  		void testProviderUpdateTriggersChange() {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());  			testling->addProvider(avatarProvider1);  			avatarProvider1->avatars[user1] = avatarHash1;  			avatarProvider1->onAvatarChanged(user1);  			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); @@ -173,52 +193,183 @@ class CombinedAvatarProviderTest : public CppUnit::TestFixture {  			boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());  			avatarProvider1->useBare = true;  			testling->addProvider(avatarProvider1);  			avatarProvider1->avatars[user1.toBare()] = avatarHash1;  			testling->getAvatarHash(user1);  			avatarProvider1->avatars[user1.toBare()] = avatarHash2;  			avatarProvider1->onAvatarChanged(user1.toBare()); -			CPPUNIT_ASSERT_EQUAL(avatarHash2, testling->getAvatarHash(user1)); +			boost::optional<std::string> hash = testling->getAvatarHash(user1); +			CPPUNIT_ASSERT(hash); +			CPPUNIT_ASSERT_EQUAL(avatarHash2, *hash); +		} + +		void testAddRemoveFallthrough() { +				JID ownJID = JID("user0@own.com/res"); +				JID user1 = JID("user1@bar.com/bla"); + +				boost::shared_ptr<CryptoProvider> crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); +				DummyStanzaChannel* stanzaChannel = new DummyStanzaChannel(); +				stanzaChannel->setAvailable(true); +				IQRouter* iqRouter = new IQRouter(stanzaChannel); +				DummyMUCRegistry* mucRegistry = new DummyMUCRegistry(); +				AvatarMemoryStorage* avatarStorage = new AvatarMemoryStorage(); +				VCardMemoryStorage* vcardStorage = new VCardMemoryStorage(crypto.get()); +				VCardManager* vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); + +				boost::shared_ptr<VCardUpdateAvatarManager> updateManager(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry)); +				updateManager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + +				boost::shared_ptr<VCardAvatarManager> manager(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry)); +				manager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + +				boost::shared_ptr<OfflineAvatarManager> offlineManager(new OfflineAvatarManager(avatarStorage)); +				offlineManager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + +				boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); +				avatarProvider1->useBare = true; +				testling->addProvider(updateManager.get()); +				testling->addProvider(manager.get()); +				testling->addProvider(offlineManager.get()); + +				/* place an avatar in the cache, check that it reads back OK */ + +				CPPUNIT_ASSERT_EQUAL(size_t(0), changes.size()); + +				ByteArray avatar1 = createByteArray("abcdefg"); +				std::string avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); +				VCard::ref vcard1(new VCard()); +				vcard1->setPhoto(avatar1); + +				vcardStorage->setVCard(user1.toBare(), vcard1); +				boost::optional<std::string> testHash = testling->getAvatarHash(user1.toBare()); +				CPPUNIT_ASSERT(testHash); +				CPPUNIT_ASSERT_EQUAL(avatar1Hash, *testHash); + +				VCard::ref storedVCard = vcardStorage->getVCard(user1.toBare()); +				CPPUNIT_ASSERT(!!storedVCard); +				testHash = Hexify::hexify(crypto->getSHA1Hash(storedVCard->getPhoto())); +				CPPUNIT_ASSERT_EQUAL(avatar1Hash, *testHash); + +				/* change the avatar by sending an VCard IQ */ + +				vcardManager->requestVCard(user1.toBare()); +				CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); +				IQ::ref request = boost::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas.back()); +				VCard::ref payload = request->getPayload<VCard>(); +				CPPUNIT_ASSERT(!!payload); +				stanzaChannel->sentStanzas.pop_back(); + +				ByteArray avatar2 = createByteArray("1234567"); +				std::string avatar2Hash = Hexify::hexify(crypto->getSHA1Hash(avatar2)); +				VCard::ref vcard2(new VCard()); +				vcard2->setPhoto(avatar2); + +				IQ::ref reply = boost::make_shared<IQ>(); +				reply->setTo(request->getFrom()); +				reply->setFrom(request->getTo()); +				reply->setID(request->getID()); +				reply->addPayload(vcard2); +				reply->setType(IQ::Result); + +				stanzaChannel->onIQReceived(reply); + +				/* check that we changed the avatar successfully and that we were notified about the changes */ + +				testHash = testling->getAvatarHash(user1.toBare()); +				CPPUNIT_ASSERT(testHash); +				CPPUNIT_ASSERT_EQUAL(avatar2Hash, *testHash); +				CPPUNIT_ASSERT_EQUAL(size_t(3), changes.size()); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[2]); +				changes.clear(); +				storedVCard = vcardStorage->getVCard(user1.toBare()); +				CPPUNIT_ASSERT(!!storedVCard); +				testHash = Hexify::hexify(crypto->getSHA1Hash(storedVCard->getPhoto())); +				CPPUNIT_ASSERT_EQUAL(avatar2Hash, *testHash); + +				/* change the avatar to the empty avatar */ + +				vcardManager->requestVCard(user1.toBare()); +				CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); +				request = boost::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas.back()); +				payload = request->getPayload<VCard>(); +				CPPUNIT_ASSERT(!!payload); +				stanzaChannel->sentStanzas.pop_back(); + +				VCard::ref vcard3(new VCard()); +				reply = boost::make_shared<IQ>(); +				reply->setTo(request->getFrom()); +				reply->setFrom(request->getTo()); +				reply->setID(request->getID()); +				reply->addPayload(vcard3); +				reply->setType(IQ::Result); +				stanzaChannel->onIQReceived(reply); + +				/* check that we changed the avatar successfully */ + +				testHash = testling->getAvatarHash(user1.toBare()); +				CPPUNIT_ASSERT(testHash); +				CPPUNIT_ASSERT_EQUAL(std::string(""), *testHash); +				CPPUNIT_ASSERT_EQUAL(size_t(3), changes.size()); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); +				CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[2]); +				changes.clear(); +				storedVCard = vcardStorage->getVCard(user1.toBare()); +				CPPUNIT_ASSERT(!!storedVCard); +				CPPUNIT_ASSERT(!storedVCard->getPhoto().size()); + +				delete vcardManager; +				delete vcardStorage; +				delete mucRegistry; +				delete iqRouter; +				delete stanzaChannel;  		}  	private:  		boost::shared_ptr<CombinedAvatarProvider> createProvider() {  			boost::shared_ptr<CombinedAvatarProvider> result(new CombinedAvatarProvider());  			result->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1));  			return result;  		}  		void handleAvatarChanged(const JID& jid) {  			changes.push_back(jid);  		}  	private:  		struct DummyAvatarProvider : public AvatarProvider {  			DummyAvatarProvider() : useBare(false) {  			} -			std::string getAvatarHash(const JID& jid) const { +			boost::optional<std::string> getAvatarHash(const JID& jid) const {  				JID actualJID = useBare ? jid.toBare() : jid;  				std::map<JID, std::string>::const_iterator i = avatars.find(actualJID);  				if (i != avatars.end()) {  					return i->second;  				}  				else { -					return std::string(); +					return boost::optional<std::string>();  				}  			}  			bool useBare;  			std::map<JID, std::string> avatars;  		}; +		struct DummyMUCRegistry : public MUCRegistry { +			bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } +			std::vector<JID> mucs_; +		}; +  		DummyAvatarProvider* avatarProvider1;  		DummyAvatarProvider* avatarProvider2;  		JID user1;  		JID user2;  		std::string avatarHash1;  		std::string avatarHash2;  		std::string avatarHash3;  		std::vector<JID> changes;  }; | 
 Swift
 Swift