summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Maudsley <richard.maudsley@isode.com>2014-06-23 10:52:31 (GMT)
committerRichard Maudsley <richard.maudsley@isode.com>2014-06-24 14:32:55 (GMT)
commitc779e07f6d1d23cc157ab3823a00edd95f70ab3b (patch)
tree5de546a38677ce19be1b34932144460f11197f96
parentbd7f30aec53fc776be678577dbe4f9afec5898a6 (diff)
downloadswift-contrib-c779e07f6d1d23cc157ab3823a00edd95f70ab3b.zip
swift-contrib-c779e07f6d1d23cc157ab3823a00edd95f70ab3b.tar.bz2
Fix old avatar being displayed in QtRosterHeader when cleared.
Test-Information: Added unit tests for AvatarManagerImpl and CombinedAvatarProvider. Updated test cases to distinguish between error case and empty avatar. Tested changing between blank and non-blank avatars while watching MUC and 1-to-1 chats. Change-Id: I0bea89c7a22ae9c44a0b126e672a7af94b6f5049
-rw-r--r--Swiften/Avatars/AvatarManagerImpl.cpp16
-rw-r--r--Swiften/Avatars/AvatarProvider.h2
-rw-r--r--Swiften/Avatars/CombinedAvatarProvider.cpp16
-rw-r--r--Swiften/Avatars/CombinedAvatarProvider.h4
-rw-r--r--Swiften/Avatars/OfflineAvatarManager.cpp2
-rw-r--r--Swiften/Avatars/OfflineAvatarManager.h2
-rw-r--r--Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp142
-rw-r--r--Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp165
-rw-r--r--Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp27
-rw-r--r--Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp20
-rw-r--r--Swiften/Avatars/VCardAvatarManager.cpp2
-rw-r--r--Swiften/Avatars/VCardAvatarManager.h2
-rw-r--r--Swiften/Avatars/VCardUpdateAvatarManager.cpp4
-rw-r--r--Swiften/Avatars/VCardUpdateAvatarManager.h2
-rw-r--r--Swiften/SConscript1
15 files changed, 361 insertions, 46 deletions
diff --git a/Swiften/Avatars/AvatarManagerImpl.cpp b/Swiften/Avatars/AvatarManagerImpl.cpp
index 7c3baa7..3aaae33 100644
--- a/Swiften/Avatars/AvatarManagerImpl.cpp
+++ b/Swiften/Avatars/AvatarManagerImpl.cpp
@@ -1,64 +1,66 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Avatars/AvatarManagerImpl.h>
#include <boost/bind.hpp>
#include <Swiften/Avatars/VCardUpdateAvatarManager.h>
#include <Swiften/Avatars/VCardAvatarManager.h>
#include <Swiften/Avatars/AvatarStorage.h>
#include <Swiften/Avatars/OfflineAvatarManager.h>
#include <Swiften/Base/ByteArray.h>
namespace Swift {
AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : avatarStorage(avatarStorage) {
vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto, mucRegistry);
combinedAvatarProvider.addProvider(vcardUpdateAvatarManager);
vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, crypto, mucRegistry);
combinedAvatarProvider.addProvider(vcardAvatarManager);
offlineAvatarManager = new OfflineAvatarManager(avatarStorage);
combinedAvatarProvider.addProvider(offlineAvatarManager);
combinedAvatarProvider.onAvatarChanged.connect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1));
}
AvatarManagerImpl::~AvatarManagerImpl() {
combinedAvatarProvider.onAvatarChanged.disconnect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1));
combinedAvatarProvider.removeProvider(offlineAvatarManager);
delete offlineAvatarManager;
combinedAvatarProvider.removeProvider(vcardAvatarManager);
delete vcardAvatarManager;
combinedAvatarProvider.removeProvider(vcardUpdateAvatarManager);
delete vcardUpdateAvatarManager;
}
boost::filesystem::path AvatarManagerImpl::getAvatarPath(const JID& jid) const {
- std::string hash = combinedAvatarProvider.getAvatarHash(jid);
- if (!hash.empty()) {
- return avatarStorage->getAvatarPath(hash);
+ boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid);
+ if (hash && !hash->empty()) {
+ return avatarStorage->getAvatarPath(*hash);
}
return boost::filesystem::path();
}
ByteArray AvatarManagerImpl::getAvatar(const JID& jid) const {
- std::string hash = combinedAvatarProvider.getAvatarHash(jid);
- if (!hash.empty()) {
- return avatarStorage->getAvatar(hash);
+ boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid);
+ if (hash && !hash->empty()) {
+ return avatarStorage->getAvatar(*hash);
}
return ByteArray();
}
void AvatarManagerImpl::handleCombinedAvatarChanged(const JID& jid) {
- offlineAvatarManager->setAvatar(jid, combinedAvatarProvider.getAvatarHash(jid));
+ boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid);
+ assert(hash);
+ offlineAvatarManager->setAvatar(jid, *hash);
onAvatarChanged(jid);
}
}
diff --git a/Swiften/Avatars/AvatarProvider.h b/Swiften/Avatars/AvatarProvider.h
index 5c9460d..3606376 100644
--- a/Swiften/Avatars/AvatarProvider.h
+++ b/Swiften/Avatars/AvatarProvider.h
@@ -1,25 +1,25 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <string>
#include <Swiften/Base/API.h>
#include <Swiften/Base/boost_bsignals.h>
namespace Swift {
class JID;
class SWIFTEN_API AvatarProvider {
public:
virtual ~AvatarProvider();
- virtual std::string getAvatarHash(const JID&) const = 0;
+ virtual boost::optional<std::string> getAvatarHash(const JID&) const = 0;
boost::signal<void (const JID&)> onAvatarChanged;
};
}
diff --git a/Swiften/Avatars/CombinedAvatarProvider.cpp b/Swiften/Avatars/CombinedAvatarProvider.cpp
index d283664..1bd74dd 100644
--- a/Swiften/Avatars/CombinedAvatarProvider.cpp
+++ b/Swiften/Avatars/CombinedAvatarProvider.cpp
@@ -1,57 +1,61 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Avatars/CombinedAvatarProvider.h>
#include <algorithm>
#include <boost/bind.hpp>
#include <Swiften/Base/Log.h>
namespace Swift {
-std::string CombinedAvatarProvider::getAvatarHash(const JID& jid) const {
+boost::optional<std::string> CombinedAvatarProvider::getAvatarHash(const JID& jid) const {
return getCombinedAvatarAndCache(jid);
}
void CombinedAvatarProvider::addProvider(AvatarProvider* provider) {
provider->onAvatarChanged.connect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1));
providers.push_back(provider);
}
void CombinedAvatarProvider::removeProvider(AvatarProvider* provider) {
std::vector<AvatarProvider*>::iterator i = std::remove(providers.begin(), providers.end(), provider);
for(std::vector<AvatarProvider*>::iterator j = i; j < providers.end(); ++j) {
provider->onAvatarChanged.disconnect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1));
}
providers.erase(i, providers.end());
}
void CombinedAvatarProvider::handleAvatarChanged(const JID& jid) {
std::string oldHash;
std::map<JID, std::string>::const_iterator i = avatars.find(jid);
if (i != avatars.end()) {
oldHash = i->second;
}
- std::string newHash = getCombinedAvatarAndCache(jid);
+ boost::optional<std::string> newHash = getCombinedAvatarAndCache(jid);
if (newHash != oldHash) {
SWIFT_LOG(debug) << "Avatar changed: " << jid << ": " << oldHash << " -> " << newHash << std::endl;
onAvatarChanged(jid);
}
}
-std::string CombinedAvatarProvider::getCombinedAvatarAndCache(const JID& jid) const {
+boost::optional<std::string> CombinedAvatarProvider::getCombinedAvatarAndCache(const JID& jid) const {
SWIFT_LOG(debug) << "JID: " << jid << std::endl;
- std::string hash;
- for (size_t i = 0; i < providers.size() && hash.empty(); ++i) {
+ boost::optional<std::string> hash;
+ for (size_t i = 0; i < providers.size() && !hash; ++i) {
hash = providers[i]->getAvatarHash(jid);
SWIFT_LOG(debug) << "Provider " << providers[i] << ": " << hash << std::endl;
}
- avatars[jid] = hash;
+ if (hash) {
+ avatars[jid] = *hash;
+ } else {
+ avatars[jid] = "";
+ }
return hash;
}
}
diff --git a/Swiften/Avatars/CombinedAvatarProvider.h b/Swiften/Avatars/CombinedAvatarProvider.h
index 96989b2..ec06e72 100644
--- a/Swiften/Avatars/CombinedAvatarProvider.h
+++ b/Swiften/Avatars/CombinedAvatarProvider.h
@@ -1,32 +1,32 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <vector>
#include <map>
#include <Swiften/Base/API.h>
#include <Swiften/Avatars/AvatarProvider.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class SWIFTEN_API CombinedAvatarProvider : public AvatarProvider {
public:
- virtual std::string getAvatarHash(const JID&) const;
+ virtual boost::optional<std::string> getAvatarHash(const JID&) const;
void addProvider(AvatarProvider*);
void removeProvider(AvatarProvider*);
private:
void handleAvatarChanged(const JID&);
- std::string getCombinedAvatarAndCache(const JID&) const;
+ boost::optional<std::string> getCombinedAvatarAndCache(const JID&) const;
private:
std::vector<AvatarProvider*> providers;
mutable std::map<JID, std::string> avatars;
};
}
diff --git a/Swiften/Avatars/OfflineAvatarManager.cpp b/Swiften/Avatars/OfflineAvatarManager.cpp
index 02c6a35..8492e86 100644
--- a/Swiften/Avatars/OfflineAvatarManager.cpp
+++ b/Swiften/Avatars/OfflineAvatarManager.cpp
@@ -1,32 +1,32 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Avatars/OfflineAvatarManager.h>
#include <boost/bind.hpp>
#include <Swiften/Avatars/AvatarStorage.h>
namespace Swift {
OfflineAvatarManager::OfflineAvatarManager(AvatarStorage* avatarStorage) : avatarStorage(avatarStorage) {
}
OfflineAvatarManager::~OfflineAvatarManager() {
}
-std::string OfflineAvatarManager::getAvatarHash(const JID& jid) const {
+boost::optional<std::string> OfflineAvatarManager::getAvatarHash(const JID& jid) const {
return avatarStorage->getAvatarForJID(jid);
}
void OfflineAvatarManager::setAvatar(const JID& jid, const std::string& hash) {
if (getAvatarHash(jid) != hash) {
avatarStorage->setAvatarForJID(jid, hash);
onAvatarChanged(jid);
}
}
}
diff --git a/Swiften/Avatars/OfflineAvatarManager.h b/Swiften/Avatars/OfflineAvatarManager.h
index 2098990..baceae8 100644
--- a/Swiften/Avatars/OfflineAvatarManager.h
+++ b/Swiften/Avatars/OfflineAvatarManager.h
@@ -1,25 +1,25 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swiften/Avatars/AvatarProvider.h>
namespace Swift {
class AvatarStorage;
class OfflineAvatarManager : public AvatarProvider {
public:
OfflineAvatarManager(AvatarStorage*);
~OfflineAvatarManager();
- virtual std::string getAvatarHash(const JID&) const;
+ virtual boost::optional<std::string> getAvatarHash(const JID&) const;
void setAvatar(const JID&, const std::string& hash);
private:
AvatarStorage* avatarStorage;
};
}
diff --git a/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp
new file mode 100644
index 0000000..9b7515d
--- /dev/null
+++ b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014 Kevin Smith and 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 <boost/bind.hpp>
+
+#include <Swiften/JID/JID.h>
+#include <string>
+#include <Swiften/Avatars/AvatarManagerImpl.h>
+#include <Swiften/Avatars/CombinedAvatarProvider.h>
+#include <Swiften/Avatars/VCardAvatarManager.h>
+#include <Swiften/Avatars/OfflineAvatarManager.h>
+#include <Swiften/Elements/VCardUpdate.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 AvatarManagerImplTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(AvatarManagerImplTest);
+ CPPUNIT_TEST(testGetSetAvatar);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ ownerJID = JID("owner@domain.com/theowner");
+ stanzaChannel = boost::make_shared<DummyStanzaChannel>();
+ iqRouter = boost::make_shared<IQRouter>(stanzaChannel.get());
+ crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+ vcardStorage = boost::make_shared<VCardMemoryStorage>(crypto.get());
+ vcardManager = boost::make_shared<VCardManager>(ownerJID, iqRouter.get(), vcardStorage.get());
+ avatarStorage = boost::make_shared<AvatarMemoryStorage>();
+ mucRegistry = boost::make_shared<DummyMUCRegistry>();
+ avatarManager = boost::make_shared<AvatarManagerImpl>(vcardManager.get(), stanzaChannel.get(), avatarStorage.get(), crypto.get(), mucRegistry.get());
+ }
+
+ void testGetSetAvatar() {
+ /* initially we have no knowledge of the user or their avatar */
+ JID personJID("person@domain.com/theperson");
+ ByteArray avatar = avatarManager->getAvatar(personJID.toBare());
+ CPPUNIT_ASSERT(!avatar.size());
+
+ /* notify the 'owner' JID that our avatar has changed */
+
+ ByteArray fullAvatar = createByteArray("abcdefg");
+ boost::shared_ptr<VCardUpdate> vcardUpdate = boost::make_shared<VCardUpdate>();
+ vcardUpdate->setPhotoHash(Hexify::hexify(crypto->getSHA1Hash(fullAvatar)));
+ boost::shared_ptr<Presence> presence = boost::make_shared<Presence>();
+ presence->setTo(ownerJID);
+ presence->setFrom(personJID);
+ presence->setType(Presence::Available);
+ presence->addPayload(vcardUpdate);
+ stanzaChannel->onPresenceReceived(presence);
+
+ /* reply to the avatar request with our new avatar */
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size());
+ boost::shared_ptr<IQ> request = boost::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas[0]);
+ stanzaChannel->sentStanzas.pop_back();
+ CPPUNIT_ASSERT(!!request);
+ boost::shared_ptr<VCard> vcard = request->getPayload<VCard>();
+ CPPUNIT_ASSERT(!!vcard);
+
+ boost::shared_ptr<IQ> reply = boost::make_shared<IQ>(IQ::Result);
+ reply->setTo(request->getFrom());
+ reply->setFrom(request->getTo());
+ reply->setID(request->getID());
+ vcard->setPhoto(fullAvatar);
+ reply->addPayload(vcard);
+ stanzaChannel->onIQReceived(reply);
+
+ /* check hash through avatarManager that it received the correct photo */
+
+ ByteArray reportedAvatar = avatarManager->getAvatar(personJID.toBare());
+ CPPUNIT_ASSERT_EQUAL(byteArrayToString(fullAvatar), byteArrayToString(reportedAvatar));
+
+ /* send new presence to notify of blank avatar */
+
+ vcardUpdate = boost::make_shared<VCardUpdate>();
+ presence = boost::make_shared<Presence>();
+ presence->setTo(ownerJID);
+ presence->setFrom(personJID);
+ presence->setType(Presence::Available);
+ presence->addPayload(vcardUpdate);
+ stanzaChannel->onPresenceReceived(presence);
+
+ /* reply to the avatar request with our EMPTY avatar */
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size());
+ request = boost::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas[0]);
+ stanzaChannel->sentStanzas.pop_back();
+ CPPUNIT_ASSERT(!!request);
+ vcard = request->getPayload<VCard>();
+ CPPUNIT_ASSERT(!!vcard);
+
+ ByteArray blankAvatar = createByteArray("");
+ reply = boost::make_shared<IQ>(IQ::Result);
+ reply->setTo(request->getFrom());
+ reply->setFrom(request->getTo());
+ reply->setID(request->getID());
+ vcard->setPhoto(blankAvatar);
+ reply->addPayload(vcard);
+ stanzaChannel->onIQReceived(reply);
+
+ /* check hash through avatarManager that it received the correct photo */
+
+ reportedAvatar = avatarManager->getAvatar(personJID.toBare());
+ CPPUNIT_ASSERT_EQUAL(byteArrayToString(blankAvatar), byteArrayToString(reportedAvatar));
+ }
+
+ struct DummyMUCRegistry : public MUCRegistry {
+ bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); }
+ std::vector<JID> mucs_;
+ };
+
+ private:
+
+ JID ownerJID;
+ boost::shared_ptr<DummyStanzaChannel> stanzaChannel;
+ boost::shared_ptr<IQRouter> iqRouter;
+ boost::shared_ptr<CryptoProvider> crypto;
+ boost::shared_ptr<VCardMemoryStorage> vcardStorage;
+ boost::shared_ptr<VCardManager> vcardManager;
+ boost::shared_ptr<AvatarMemoryStorage> avatarStorage;
+ boost::shared_ptr<DummyMUCRegistry> mucRegistry;
+ boost::shared_ptr<AvatarManagerImpl> avatarManager;
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AvatarManagerImplTest);
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
@@ -1,226 +1,377 @@
/*
* 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 <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";
avatarHash2 = "XYZU";
avatarHash3 = "IDGH";
}
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()));
CPPUNIT_ASSERT_EQUAL(user1, changes[0]);
}
void testProviderUpdateWithoutChangeDoesNotTriggerChange() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
testling->addProvider(avatarProvider2);
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider1->onAvatarChanged(user1);
changes.clear();
avatarProvider2->avatars[user1] = avatarHash2;
avatarProvider2->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
}
void testProviderSecondUpdateTriggersChange() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider1->onAvatarChanged(user1);
changes.clear();
avatarProvider1->avatars[user1] = avatarHash2;
avatarProvider1->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1, changes[0]);
}
void testProviderUpdateWithAvatarDisappearingTriggersChange() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider1->onAvatarChanged(user1);
changes.clear();
avatarProvider1->avatars.clear();
avatarProvider1->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1, changes[0]);
}
void testProviderUpdateAfterAvatarDisappearedTriggersChange() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider1->onAvatarChanged(user1);
avatarProvider1->avatars.clear();
avatarProvider1->onAvatarChanged(user1);
changes.clear();
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider1->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1, changes[0]);
}
void testProviderUpdateAfterGetDoesNotTriggerChange() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
avatarProvider1->avatars[user1] = avatarHash1;
testling->getAvatarHash(user1);
avatarProvider1->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
}
void testRemoveProviderDisconnectsUpdates() {
boost::shared_ptr<CombinedAvatarProvider> testling(createProvider());
testling->addProvider(avatarProvider1);
testling->addProvider(avatarProvider2);
testling->removeProvider(avatarProvider1);
avatarProvider1->avatars[user1] = avatarHash1;
avatarProvider2->avatars[user1] = avatarHash2;
avatarProvider1->onAvatarChanged(user1);
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
}
void testProviderUpdateBareJIDAfterGetFullJID() {
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;
};
CPPUNIT_TEST_SUITE_REGISTRATION(CombinedAvatarProviderTest);
diff --git a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
index 97edc73..778b001 100644
--- a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
+++ b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
@@ -1,170 +1,175 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Base/ByteArray.h>
#include <QA/Checker/IO.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <boost/bind.hpp>
#include <Swiften/Elements/VCard.h>
#include <Swiften/Avatars/VCardAvatarManager.h>
#include <Swiften/VCards/VCardMemoryStorage.h>
#include <Swiften/Avatars/AvatarMemoryStorage.h>
#include <Swiften/VCards/VCardManager.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/Queries/IQRouter.h>
#include <Swiften/Client/DummyStanzaChannel.h>
#include <Swiften/Crypto/CryptoProvider.h>
#include <Swiften/Crypto/PlatformCryptoProvider.h>
#include <Swiften/StringCodecs/Hexify.h>
using namespace Swift;
class VCardAvatarManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(VCardAvatarManagerTest);
CPPUNIT_TEST(testGetAvatarHashKnownAvatar);
CPPUNIT_TEST(testGetAvatarHashEmptyAvatar);
CPPUNIT_TEST(testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar);
CPPUNIT_TEST(testGetAvatarHashUnknownAvatarUnknownVCard);
CPPUNIT_TEST(testVCardUpdateTriggersUpdate);
CPPUNIT_TEST(testGetAvatarHashKnownAvatarUnknownVCard);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
ownJID = JID("foo@fum.com/bum");
stanzaChannel = new DummyStanzaChannel();
stanzaChannel->setAvailable(true);
iqRouter = new IQRouter(stanzaChannel);
mucRegistry = new DummyMUCRegistry();
avatarStorage = new AvatarMemoryStorage();
vcardStorage = new VCardMemoryStorage(crypto.get());
vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage);
avatar1 = createByteArray("abcdefg");
avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1));
user1 = JID("user1@bar.com/bla");
user2 = JID("user2@foo.com/baz");
}
void tearDown() {
delete vcardManager;
delete vcardStorage;
delete avatarStorage;
delete mucRegistry;
delete iqRouter;
delete stanzaChannel;
}
void testGetAvatarHashKnownAvatar() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
storeVCardWithPhoto(user1.toBare(), avatar1);
avatarStorage->addAvatar(avatar1Hash, avatar1);
- std::string result = testling->getAvatarHash(user1);
+ boost::optional<std::string> result = testling->getAvatarHash(user1);
- CPPUNIT_ASSERT_EQUAL(avatar1Hash, result);
+ CPPUNIT_ASSERT(result);
+ CPPUNIT_ASSERT_EQUAL(avatar1Hash, *result);
}
void testGetAvatarHashEmptyAvatar() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
storeEmptyVCard(user1.toBare());
- std::string result = testling->getAvatarHash(user1);
+ boost::optional<std::string> result = testling->getAvatarHash(user1);
- CPPUNIT_ASSERT_EQUAL(std::string(), result);
+ CPPUNIT_ASSERT(result);
+ CPPUNIT_ASSERT_EQUAL(std::string(), *result);
}
void testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
storeVCardWithPhoto(user1.toBare(), avatar1);
- std::string result = testling->getAvatarHash(user1);
+ boost::optional<std::string> result = testling->getAvatarHash(user1);
- CPPUNIT_ASSERT_EQUAL(avatar1Hash, result);
+ CPPUNIT_ASSERT(result);
+ CPPUNIT_ASSERT_EQUAL(avatar1Hash, *result);
CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash));
CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash));
}
void testGetAvatarHashUnknownAvatarUnknownVCard() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
- std::string result = testling->getAvatarHash(user1);
+ boost::optional<std::string> result = testling->getAvatarHash(user1);
- CPPUNIT_ASSERT_EQUAL(std::string(), result);
+ CPPUNIT_ASSERT(result);
+ CPPUNIT_ASSERT_EQUAL(std::string(), *result);
}
void testGetAvatarHashKnownAvatarUnknownVCard() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
avatarStorage->setAvatarForJID(user1, avatar1Hash);
- std::string result = testling->getAvatarHash(user1);
-
- CPPUNIT_ASSERT_EQUAL(std::string(), result);
+ boost::optional<std::string> result = testling->getAvatarHash(user1);
+
+ CPPUNIT_ASSERT(result);
+ CPPUNIT_ASSERT_EQUAL(std::string(), *result);
}
void testVCardUpdateTriggersUpdate() {
boost::shared_ptr<VCardAvatarManager> testling = createManager();
vcardManager->requestVCard(user1);
sendVCardResult();
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
}
private:
boost::shared_ptr<VCardAvatarManager> createManager() {
boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry));
result->onAvatarChanged.connect(boost::bind(&VCardAvatarManagerTest::handleAvatarChanged, this, _1));
return result;
}
void storeVCardWithPhoto(const JID& jid, const ByteArray& avatar) {
VCard::ref vcard(new VCard());
vcard->setPhoto(avatar);
vcardStorage->setVCard(jid, vcard);
}
void storeEmptyVCard(const JID& jid) {
VCard::ref vcard(new VCard());
vcardStorage->setVCard(jid, vcard);
}
void handleAvatarChanged(const JID& jid) {
changes.push_back(jid);
}
void sendVCardResult() {
VCard::ref vcard(new VCard());
vcard->setFullName("Foo Bar");
stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard));
}
private:
struct DummyMUCRegistry : public MUCRegistry {
bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); }
std::vector<JID> mucs_;
};
JID ownJID;
DummyStanzaChannel* stanzaChannel;
IQRouter* iqRouter;
DummyMUCRegistry* mucRegistry;
AvatarMemoryStorage* avatarStorage;
VCardManager* vcardManager;
VCardMemoryStorage* vcardStorage;
ByteArray avatar1;
std::string avatar1Hash;
std::vector<JID> changes;
JID user1;
JID user2;
boost::shared_ptr<CryptoProvider> crypto;
};
CPPUNIT_TEST_SUITE_REGISTRATION(VCardAvatarManagerTest);
diff --git a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
index 01b10a2..c29a763 100644
--- a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
+++ b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
@@ -1,201 +1,211 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Base/ByteArray.h>
#include <QA/Checker/IO.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <boost/bind.hpp>
#include <Swiften/Elements/VCardUpdate.h>
#include <Swiften/Avatars/VCardUpdateAvatarManager.h>
#include <Swiften/Avatars/AvatarMemoryStorage.h>
#include <Swiften/VCards/VCardMemoryStorage.h>
#include <Swiften/VCards/VCardManager.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/Queries/IQRouter.h>
#include <Swiften/Client/DummyStanzaChannel.h>
#include <Swiften/StringCodecs/Hexify.h>
#include <Swiften/Crypto/CryptoProvider.h>
#include <Swiften/Crypto/PlatformCryptoProvider.h>
using namespace Swift;
class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(VCardUpdateAvatarManagerTest);
CPPUNIT_TEST(testUpdate_NewHashNewVCardRequestsVCard);
CPPUNIT_TEST(testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive);
CPPUNIT_TEST(testUpdate_KnownHash);
CPPUNIT_TEST(testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification);
CPPUNIT_TEST(testVCardWithEmptyPhoto);
CPPUNIT_TEST(testStanzaChannelReset_ClearsHash);
CPPUNIT_TEST(testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
ownJID = JID("foo@fum.com/bum");
stanzaChannel = new DummyStanzaChannel();
stanzaChannel->setAvailable(true);
iqRouter = new IQRouter(stanzaChannel);
mucRegistry = new DummyMUCRegistry();
avatarStorage = new AvatarMemoryStorage();
vcardStorage = new VCardMemoryStorage(crypto.get());
vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage);
avatar1 = createByteArray("abcdefg");
avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1));
user1 = JID("user1@bar.com/bla");
user2 = JID("user2@foo.com/baz");
}
void tearDown() {
delete vcardManager;
delete vcardStorage;
delete avatarStorage;
delete mucRegistry;
delete iqRouter;
delete stanzaChannel;
}
void testUpdate_NewHashNewVCardRequestsVCard() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, user1.toBare(), IQ::Get));
}
void testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
stanzaChannel->onIQReceived(createVCardResult(avatar1));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]);
- CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user1.toBare()));
+ boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare());
+ CPPUNIT_ASSERT(hash);
+ CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash);
CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash));
CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash));
}
void testUpdate_KnownHash() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
stanzaChannel->onIQReceived(createVCardResult(avatar1));
changes.clear();
stanzaChannel->sentStanzas.clear();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size()));
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
}
void testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
stanzaChannel->onIQReceived(createVCardResult(avatar1));
changes.clear();
stanzaChannel->sentStanzas.clear();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user2, avatar1Hash));
CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size()));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user2.toBare(), changes[0]);
- CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user2.toBare()));
+ boost::optional<std::string> hash = testling->getAvatarHash(user2.toBare());
+ CPPUNIT_ASSERT(hash);
+ CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash);
}
void testVCardWithEmptyPhoto() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
vcardManager->requestVCard(JID("foo@bar.com"));
stanzaChannel->onIQReceived(createVCardResult(ByteArray()));
CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(crypto->getSHA1Hash(ByteArray()))));
- CPPUNIT_ASSERT_EQUAL(std::string(), testling->getAvatarHash(JID("foo@bar.com")));
+ boost::optional<std::string> hash = testling->getAvatarHash(JID("foo@bar.com"));
+ CPPUNIT_ASSERT(hash);
+ CPPUNIT_ASSERT_EQUAL(std::string(), *hash);
}
void testStanzaChannelReset_ClearsHash() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
stanzaChannel->onIQReceived(createVCardResult(avatar1));
changes.clear();
stanzaChannel->sentStanzas.clear();
stanzaChannel->setAvailable(false);
stanzaChannel->setAvailable(true);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]);
- CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getAvatarHash(user1.toBare()));
+ boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare());
+ CPPUNIT_ASSERT(!hash);
+ //CPPUNIT_ASSERT_EQUAL(std::string(""), *hash);
}
void testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash() {
boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager();
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
stanzaChannel->onIQReceived(createVCardResult(avatar1));
changes.clear();
stanzaChannel->sentStanzas.clear();
stanzaChannel->setAvailable(false);
stanzaChannel->setAvailable(true);
stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash));
CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size()));
CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]);
- CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user1.toBare()));
+ boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare());
+ CPPUNIT_ASSERT(hash);
+ CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash);
}
private:
boost::shared_ptr<VCardUpdateAvatarManager> createManager() {
boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry));
result->onAvatarChanged.connect(boost::bind(&VCardUpdateAvatarManagerTest::handleAvatarChanged, this, _1));
return result;
}
boost::shared_ptr<Presence> createPresenceWithPhotoHash(const JID& jid, const std::string& hash) {
boost::shared_ptr<Presence> presence(new Presence());
presence->setFrom(jid);
presence->addPayload(boost::make_shared<VCardUpdate>(hash));
return presence;
}
IQ::ref createVCardResult(const ByteArray& avatar) {
VCard::ref vcard(new VCard());
if (!avatar.empty()) {
vcard->setPhoto(avatar);
}
return IQ::createResult(JID("baz@fum.com"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard);
}
void handleAvatarChanged(const JID& jid) {
changes.push_back(jid);
}
private:
struct DummyMUCRegistry : public MUCRegistry {
bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); }
std::vector<JID> mucs_;
};
JID ownJID;
DummyStanzaChannel* stanzaChannel;
IQRouter* iqRouter;
DummyMUCRegistry* mucRegistry;
AvatarMemoryStorage* avatarStorage;
VCardManager* vcardManager;
VCardMemoryStorage* vcardStorage;
ByteArray avatar1;
std::string avatar1Hash;
std::vector<JID> changes;
JID user1;
JID user2;
boost::shared_ptr<CryptoProvider> crypto;
};
CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateAvatarManagerTest);
diff --git a/Swiften/Avatars/VCardAvatarManager.cpp b/Swiften/Avatars/VCardAvatarManager.cpp
index 8212a6e..539b7a0 100644
--- a/Swiften/Avatars/VCardAvatarManager.cpp
+++ b/Swiften/Avatars/VCardAvatarManager.cpp
@@ -1,62 +1,62 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Avatars/VCardAvatarManager.h>
#include <boost/bind.hpp>
#include <Swiften/Elements/VCard.h>
#include <Swiften/Crypto/CryptoProvider.h>
#include <Swiften/StringCodecs/Hexify.h>
#include <Swiften/Avatars/AvatarStorage.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/VCards/VCardManager.h>
#include <Swiften/Base/Log.h>
namespace Swift {
VCardAvatarManager::VCardAvatarManager(VCardManager* vcardManager, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) {
vcardManager_->onVCardChanged.connect(boost::bind(&VCardAvatarManager::handleVCardChanged, this, _1));
}
void VCardAvatarManager::handleVCardChanged(const JID& from) {
// We don't check whether the avatar actually changed. Direct use of this
// manager could cause unnecessary updates, but in practice, this will be
// caught by the wrapping CombinedAvatarManager anyway.
onAvatarChanged(from);
}
-std::string VCardAvatarManager::getAvatarHash(const JID& jid) const {
+boost::optional<std::string> VCardAvatarManager::getAvatarHash(const JID& jid) const {
JID avatarJID = getAvatarJID(jid);
std::string hash = vcardManager_->getPhotoHash(avatarJID);
if (!hash.empty()) {
if (!avatarStorage_->hasAvatar(hash)) {
VCard::ref vCard = vcardManager_->getVCard(avatarJID);
if (vCard) {
std::string newHash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto()));
if (newHash != hash) {
// Shouldn't happen, but sometimes seem to. Might be fixed if we
// move to a safer backend.
SWIFT_LOG(warning) << "Inconsistent vCard photo hash cache";
hash = newHash;
}
avatarStorage_->addAvatar(hash, vCard->getPhoto());
}
else {
// Can happen if the cache is inconsistent.
hash = "";
}
}
}
return hash;
}
JID VCardAvatarManager::getAvatarJID(const JID& jid) const {
JID bareFrom = jid.toBare();
return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom;
}
}
diff --git a/Swiften/Avatars/VCardAvatarManager.h b/Swiften/Avatars/VCardAvatarManager.h
index 9c6943e..a907fa5 100644
--- a/Swiften/Avatars/VCardAvatarManager.h
+++ b/Swiften/Avatars/VCardAvatarManager.h
@@ -1,35 +1,35 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swiften/Base/API.h>
#include <Swiften/Avatars/AvatarProvider.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class MUCRegistry;
class AvatarStorage;
class VCardManager;
class CryptoProvider;
class SWIFTEN_API VCardAvatarManager : public AvatarProvider {
public:
VCardAvatarManager(VCardManager*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL);
- std::string getAvatarHash(const JID&) const;
+ boost::optional<std::string> getAvatarHash(const JID&) const;
private:
void handleVCardChanged(const JID& from);
JID getAvatarJID(const JID& o) const;
private:
VCardManager* vcardManager_;
AvatarStorage* avatarStorage_;
CryptoProvider* crypto_;
MUCRegistry* mucRegistry_;
};
}
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
index 3a32889..55537ff 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
@@ -1,105 +1,105 @@
/*
* Copyright (c) 2010-2014 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Avatars/VCardUpdateAvatarManager.h>
#include <boost/bind.hpp>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Elements/VCardUpdate.h>
#include <Swiften/VCards/GetVCardRequest.h>
#include <Swiften/Crypto/CryptoProvider.h>
#include <Swiften/StringCodecs/Hexify.h>
#include <Swiften/Avatars/AvatarStorage.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/VCards/VCardManager.h>
#include <Swiften/Base/Log.h>
namespace Swift {
VCardUpdateAvatarManager::VCardUpdateAvatarManager(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) {
stanzaChannel->onPresenceReceived.connect(boost::bind(&VCardUpdateAvatarManager::handlePresenceReceived, this, _1));
stanzaChannel->onAvailableChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged, this, _1));
vcardManager_->onVCardChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleVCardChanged, this, _1, _2));
}
void VCardUpdateAvatarManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) {
boost::shared_ptr<VCardUpdate> update = presence->getPayload<VCardUpdate>();
if (!update || presence->getPayload<ErrorPayload>()) {
return;
}
JID from = getAvatarJID(presence->getFrom());
if (getAvatarHash(from) == update->getPhotoHash()) {
return;
}
SWIFT_LOG(debug) << "Updated hash: " << from << " -> " << update->getPhotoHash() << std::endl;
if (avatarStorage_->hasAvatar(update->getPhotoHash())) {
setAvatarHash(from, update->getPhotoHash());
}
else {
vcardManager_->requestVCard(from);
}
}
void VCardUpdateAvatarManager::handleVCardChanged(const JID& from, VCard::ref vCard) {
if (!vCard) {
SWIFT_LOG(debug) << "Missing element: " << from << ": null vcard payload" << std::endl;
return;
}
if (vCard->getPhoto().empty()) {
setAvatarHash(from, "");
}
else {
std::string hash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto()));
if (!avatarStorage_->hasAvatar(hash)) {
avatarStorage_->addAvatar(hash, vCard->getPhoto());
}
setAvatarHash(from, hash);
}
}
void VCardUpdateAvatarManager::setAvatarHash(const JID& from, const std::string& hash) {
SWIFT_LOG(debug) << "Updating hash: " << from << " -> " << hash << std::endl;
avatarHashes_[from] = hash;
onAvatarChanged(from);
}
/*
void VCardUpdateAvatarManager::setAvatar(const JID& jid, const ByteArray& avatar) {
std::string hash = Hexify::hexify(SHA1::getHash(avatar));
avatarStorage_->addAvatar(hash, avatar);
setAvatarHash(getAvatarJID(jid), hash);
}
*/
-std::string VCardUpdateAvatarManager::getAvatarHash(const JID& jid) const {
+boost::optional<std::string> VCardUpdateAvatarManager::getAvatarHash(const JID& jid) const {
std::map<JID, std::string>::const_iterator i = avatarHashes_.find(getAvatarJID(jid));
if (i != avatarHashes_.end()) {
return i->second;
}
else {
- return "";
+ return boost::optional<std::string>();
}
}
JID VCardUpdateAvatarManager::getAvatarJID(const JID& jid) const {
JID bareFrom = jid.toBare();
return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom;
}
void VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged(bool available) {
if (available) {
std::map<JID, std::string> oldAvatarHashes;
avatarHashes_.swap(oldAvatarHashes);
for(std::map<JID, std::string>::const_iterator i = oldAvatarHashes.begin(); i != oldAvatarHashes.end(); ++i) {
onAvatarChanged(i->first);
}
}
}
}
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.h b/Swiften/Avatars/VCardUpdateAvatarManager.h
index 3409f99..333516b 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.h
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.h
@@ -1,46 +1,46 @@
/*
* Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/shared_ptr.hpp>
#include <map>
#include <Swiften/Base/API.h>
#include <Swiften/Avatars/AvatarProvider.h>
#include <Swiften/JID/JID.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/Elements/VCard.h>
#include <Swiften/Elements/ErrorPayload.h>
namespace Swift {
class MUCRegistry;
class AvatarStorage;
class StanzaChannel;
class VCardManager;
class CryptoProvider;
class SWIFTEN_API VCardUpdateAvatarManager : public AvatarProvider, public boost::bsignals::trackable {
public:
VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL);
- std::string getAvatarHash(const JID&) const;
+ boost::optional<std::string> getAvatarHash(const JID&) const;
private:
void handlePresenceReceived(boost::shared_ptr<Presence>);
void handleStanzaChannelAvailableChanged(bool);
void handleVCardChanged(const JID& from, VCard::ref);
void setAvatarHash(const JID& from, const std::string& hash);
JID getAvatarJID(const JID& o) const;
private:
VCardManager* vcardManager_;
AvatarStorage* avatarStorage_;
CryptoProvider* crypto_;
MUCRegistry* mucRegistry_;
std::map<JID, std::string> avatarHashes_;
};
}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 7dbb19d..0314118 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -1,555 +1,556 @@
import os, re, Version, os.path, time
Import("env")
################################################################################
# Flags
################################################################################
swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "LDNS", "UNBOUND", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP", "SQLITE"]
external_swiften_dep_modules = ["BOOST"]
if env["SCONS_STAGE"] == "flags" :
env["SWIFTEN_DLL"] = env["swiften_dll"]
env["SWIFTEN_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift")
version_match = re.match("(\d+)\.(\d+).*", env["SWIFTEN_VERSION"])
if version_match :
env["SWIFTEN_VERSION_MAJOR"] = int(version_match.group(1))
env["SWIFTEN_VERSION_MINOR"] = int(version_match.group(2))
else :
env["SWIFTEN_VERSION_MAJOR"] = 0
env["SWIFTEN_VERSION_MINOR"] = 0
env["SWIFTEN_VERSION_PATCH"] = 0
env["SWIFTEN_LIBRARY"] = "Swiften"
env["SWIFTEN_LIBRARY_FILE"] = "Swiften"
env["SWIFTEN_LIBRARY_ALIASES"] = []
if env["SWIFTEN_DLL"] :
if env["PLATFORM"] == "win32" :
env["SWIFTEN_LIBRARY"] = env.subst("Swiften${SWIFTEN_VERSION_MAJOR}")
env["SWIFTEN_LIBRARY_FILE"] = env.subst("${SWIFTEN_LIBRARY}.dll")
elif env["PLATFORM"] == "darwin" :
env["SWIFTEN_LIBRARY_FILE"] = env.subst("Swiften.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}")
env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.dylib", env.subst("libSwiften.${SWIFTEN_VERSION_MAJOR}.dylib")]
else :
env["SWIFTEN_LIBRARY_FILE"] = env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}")
env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.so", env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}")]
if env["SWIFTEN_DLL"] :
env.AddMethod(lambda e,s : e.SharedObject(s), "SwiftenObject")
else :
env.AddMethod(lambda e,s : e.StaticObject(s), "SwiftenObject")
swiften_env = env.Clone()
swiften_env["LIBPATH"] = [Dir(".")]
swiften_env["LIBRUNPATH"] = [Dir(".")]
swiften_env["LIBS"] = [swiften_env["SWIFTEN_LIBRARY"]]
if not env["SWIFTEN_DLL"] :
swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"])
dep_env = env.Clone()
for module in swiften_dep_modules :
module_flags = env.get(module + "_FLAGS", {})
if env.get(module + "_BUNDLED", False) :
if module in external_swiften_dep_modules :
swiften_env.UseFlags(module_flags)
else :
if module in external_swiften_dep_modules :
dep_env.UseFlags(module_flags)
else :
# Expose only libraries
dep_env.Append(LIBPATH = module_flags.get("LIBPATH", []))
dep_env.Append(LIBS = module_flags.get("LIBS", []))
dep_env.Append(FRAMEWORKS = module_flags.get("FRAMEWORKS", []))
dep_env.UseFlags(dep_env["PLATFORM_FLAGS"])
if env.get("HAVE_SCHANNEL", 0) :
dep_env.Append(LIBS = ["Winscard"])
for var, e in [("SWIFTEN_FLAGS", swiften_env), ("SWIFTEN_DEP_FLAGS", dep_env)] :
env[var] = {
"CPPDEFINES": e.get("CPPDEFINES", []),
"CPPPATH": e.get("CPPPATH", []),
"CPPFLAGS": e.get("CPPFLAGS", []),
"LIBPATH": e.get("LIBPATH", []),
"LIBRUNPATH": e.get("LIBRUNPATH", []),
"LIBS": e.get("LIBS", []),
"FRAMEWORKS": e.get("FRAMEWORKS", []),
}
################################################################################
# Build
################################################################################
if env["SCONS_STAGE"] == "build" :
swiften_env = env.Clone()
swiften_env.Append(CPPDEFINES = ["SWIFTEN_BUILDING"])
for module in swiften_dep_modules :
swiften_env.UseFlags(swiften_env.get(module + "_FLAGS", {}))
if env.get(module + "_BUNDLED", False) :
swiften_env.Append(SWIFTEN_OBJECTS = env.get(module + "_OBJECTS", []))
swiften_env.UseFlags(swiften_env["PLATFORM_FLAGS"])
if swiften_env["SWIFTEN_DLL"] :
swiften_env.AddMethod(lambda e,l,o : e.SharedLibrary(l,o), "SwiftenLibrary")
else :
swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"])
swiften_env.AddMethod(lambda e,l,o : e.StaticLibrary(l,o), "SwiftenLibrary")
Export("swiften_env")
# TODO: Move all this to a submodule SConscript
sources = [
"Chat/ChatStateTracker.cpp",
"Chat/ChatStateNotifier.cpp",
"Client/ClientSessionStanzaChannel.cpp",
"Client/CoreClient.cpp",
"Client/Client.cpp",
"Client/ClientXMLTracer.cpp",
"Client/ClientSession.cpp",
"Client/BlockList.cpp",
"Client/BlockListImpl.cpp",
"Client/ClientBlockListManager.cpp",
"Client/MemoryStorages.cpp",
"Client/NickResolver.cpp",
"Client/NickManager.cpp",
"Client/NickManagerImpl.cpp",
"Client/Storages.cpp",
"Client/XMLBeautifier.cpp",
"Compress/ZLibCodecompressor.cpp",
"Compress/ZLibDecompressor.cpp",
"Compress/ZLibCompressor.cpp",
"Elements/DiscoInfo.cpp",
"Elements/Presence.cpp",
"Elements/Form.cpp",
"Elements/FormField.cpp",
"Elements/StreamFeatures.cpp",
"Elements/Element.cpp",
"Elements/ToplevelElement.cpp",
"Elements/IQ.cpp",
"Elements/Payload.cpp",
"Elements/PubSubPayload.cpp",
"Elements/PubSubOwnerPayload.cpp",
"Elements/PubSubEventPayload.cpp",
"Elements/RosterItemExchangePayload.cpp",
"Elements/RosterPayload.cpp",
"Elements/SecurityLabel.cpp",
"Elements/Stanza.cpp",
"Elements/StanzaAck.cpp",
"Elements/StatusShow.cpp",
"Elements/StreamManagementEnabled.cpp",
"Elements/StreamResume.cpp",
"Elements/StreamResumed.cpp",
"Elements/UserLocation.cpp",
"Elements/UserTune.cpp",
"Elements/VCard.cpp",
"Elements/MUCOccupant.cpp",
"Elements/ResultSet.cpp",
"Elements/Forwarded.cpp",
"Elements/MAMResult.cpp",
"Elements/MAMQuery.cpp",
"Elements/MAMArchived.cpp",
"Entity/Entity.cpp",
"Entity/PayloadPersister.cpp",
"MUC/MUC.cpp",
"MUC/MUCImpl.cpp",
"MUC/MUCManager.cpp",
"MUC/MUCRegistry.cpp",
"MUC/MUCBookmarkManager.cpp",
"PubSub/PubSubManager.cpp",
"PubSub/PubSubManagerImpl.cpp",
"Queries/IQChannel.cpp",
"Queries/IQHandler.cpp",
"Queries/IQRouter.cpp",
"Queries/Request.cpp",
"Queries/Requests/GetInBandRegistrationFormRequest.cpp",
"Queries/Requests/SubmitInBandRegistrationFormRequest.cpp",
"Queries/Responders/SoftwareVersionResponder.cpp",
"Roster/RosterStorage.cpp",
"Roster/RosterMemoryStorage.cpp",
"Roster/XMPPRoster.cpp",
"Roster/XMPPRosterImpl.cpp",
"Roster/XMPPRosterController.cpp",
"Serializer/AuthRequestSerializer.cpp",
"Serializer/AuthSuccessSerializer.cpp",
"Serializer/AuthChallengeSerializer.cpp",
"Serializer/AuthResponseSerializer.cpp",
"Serializer/CompressRequestSerializer.cpp",
"Serializer/ElementSerializer.cpp",
"Serializer/MessageSerializer.cpp",
"Serializer/StreamManagementEnabledSerializer.cpp",
"Serializer/StreamResumeSerializer.cpp",
"Serializer/StreamResumedSerializer.cpp",
"Serializer/ComponentHandshakeSerializer.cpp",
"Serializer/PayloadSerializer.cpp",
"Serializer/PayloadSerializerCollection.cpp",
"Serializer/PayloadSerializers/IBBSerializer.cpp",
"Serializer/PayloadSerializers/CapsInfoSerializer.cpp",
"Serializer/PayloadSerializers/ChatStateSerializer.cpp",
"Serializer/PayloadSerializers/DiscoInfoSerializer.cpp",
"Serializer/PayloadSerializers/DiscoItemsSerializer.cpp",
"Serializer/PayloadSerializers/ErrorSerializer.cpp",
"Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp",
"Serializer/PayloadSerializers/MUCPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp",
"Serializer/PayloadSerializers/ResourceBindSerializer.cpp",
"Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp",
"Serializer/PayloadSerializers/RosterSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp",
"Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp",
"Serializer/PayloadSerializers/StreamInitiationSerializer.cpp",
"Serializer/PayloadSerializers/BytestreamsSerializer.cpp",
"Serializer/PayloadSerializers/VCardSerializer.cpp",
"Serializer/PayloadSerializers/VCardUpdateSerializer.cpp",
"Serializer/PayloadSerializers/StorageSerializer.cpp",
"Serializer/PayloadSerializers/PrivateStorageSerializer.cpp",
"Serializer/PayloadSerializers/DelaySerializer.cpp",
"Serializer/PayloadSerializers/CommandSerializer.cpp",
"Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp",
"Serializer/PayloadSerializers/SearchPayloadSerializer.cpp",
"Serializer/PayloadSerializers/FormSerializer.cpp",
"Serializer/PayloadSerializers/NicknameSerializer.cpp",
"Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp",
"Serializer/PayloadSerializers/JinglePayloadSerializer.cpp",
"Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp",
"Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp",
"Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.cpp",
"Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp",
"Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp",
"Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp",
"Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp",
"Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp",
"Serializer/PayloadSerializers/UserLocationSerializer.cpp",
"Serializer/PayloadSerializers/UserTuneSerializer.cpp",
"Serializer/PayloadSerializers/WhiteboardSerializer.cpp",
"Serializer/PayloadSerializers/ResultSetSerializer.cpp",
"Serializer/PayloadSerializers/ForwardedSerializer.cpp",
"Serializer/PayloadSerializers/MAMResultSerializer.cpp",
"Serializer/PayloadSerializers/MAMQuerySerializer.cpp",
"Serializer/PayloadSerializers/MAMArchivedSerializer.cpp",
"Serializer/PresenceSerializer.cpp",
"Serializer/StanzaSerializer.cpp",
"Serializer/StreamErrorSerializer.cpp",
"Serializer/StreamFeaturesSerializer.cpp",
"Serializer/XML/XMLElement.cpp",
"Serializer/XML/XMLNode.cpp",
"Serializer/XMPPSerializer.cpp",
"Session/Session.cpp",
"Session/SessionTracer.cpp",
"Session/SessionStream.cpp",
"Session/BasicSessionStream.cpp",
"Session/BOSHSessionStream.cpp",
"StringCodecs/Base64.cpp",
"StringCodecs/Hexify.cpp",
"Whiteboard/WhiteboardResponder.cpp",
"Whiteboard/WhiteboardSession.cpp",
"Whiteboard/IncomingWhiteboardSession.cpp",
"Whiteboard/OutgoingWhiteboardSession.cpp",
"Whiteboard/WhiteboardSessionManager.cpp",
"Whiteboard/WhiteboardServer.cpp",
"Whiteboard/WhiteboardClient.cpp",
"Elements/Whiteboard/WhiteboardColor.cpp",
"Whiteboard/WhiteboardTransformer.cpp",
]
elements = [
"PubSub", "PubSubAffiliations", "PubSubAffiliation", "PubSubConfigure", "PubSubCreate", "PubSubDefault",
"PubSubItems", "PubSubItem", "PubSubOptions", "PubSubPublish", "PubSubRetract", "PubSubSubscribeOptions",
"PubSubSubscribe", "PubSubSubscriptions", "PubSubSubscription", "PubSubUnsubscribe",
"PubSubEvent", "PubSubEventAssociate", "PubSubEventCollection", "PubSubEventConfiguration", "PubSubEventDelete",
"PubSubEventDisassociate", "PubSubEventItem", "PubSubEventItems", "PubSubEventPurge", "PubSubEventRedirect",
"PubSubEventRetract", "PubSubEventSubscription",
"PubSubOwnerAffiliation", "PubSubOwnerAffiliations", "PubSubOwnerConfigure", "PubSubOwnerDefault",
"PubSubOwnerDelete", "PubSubOwnerPubSub", "PubSubOwnerPurge", "PubSubOwnerRedirect",
"PubSubOwnerSubscription", "PubSubOwnerSubscriptions",
"PubSubError",
]
for element in elements :
sources += [
"Elements/" + element + ".cpp",
"Serializer/PayloadSerializers/" + element + "Serializer.cpp",
"Parser/PayloadParsers/" + element + "Parser.cpp",
]
SConscript(dirs = [
"Avatars",
"Base",
"IDN",
"SASL",
"TLS",
"Crypto",
"EventLoop",
"Parser",
"JID",
"Jingle",
"Disco",
"VCards",
"Network",
"Presence",
"FileTransfer",
"History",
"StreamStack",
"LinkLocal",
"StreamManagement",
"Component",
"AdHoc"
])
if env["build_examples"] :
SConscript(dirs = [
"Config",
"Examples"
])
env.SConscript(test_only = True, dirs = [
"QA",
])
myenv = swiften_env.Clone()
if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) :
env.MergeFlags(env["GCONF_FLAGS"])
if myenv["SWIFTEN_DLL"] :
if myenv["PLATFORM"] == "posix" :
myenv.Append(LINKFLAGS = ["-Wl,-soname,libSwiften.so.$SWIFTEN_VERSION_MAJOR"])
myenv["SHLIBSUFFIX"] = ""
elif myenv["PLATFORM"] == "darwin" :
myenv.Append(LINKFLAGS = ["-Wl,-install_name,${SHLIBPREFIX}Swiften.${SWIFTEN_VERSION_MAJOR}${SHLIBSUFFIX}", "-Wl,-compatibility_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}", "-Wl,-current_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}"])
elif myenv["PLATFORM"] == "win32" :
res_env = myenv.Clone()
res_env.Append(CPPDEFINES = [
("SWIFTEN_LIBRARY_FILE", "\"\\\"${SWIFTEN_LIBRARY_FILE}\\\"\""),
("SWIFTEN_COPYRIGHT_YEAR", "\"\\\"2010-%s\\\"\"" % str(time.localtime()[0])),
("SWIFTEN_VERSION_MAJOR", "${SWIFTEN_VERSION_MAJOR}"),
("SWIFTEN_VERSION_MINOR", "${SWIFTEN_VERSION_MINOR}"),
("SWIFTEN_VERSION_PATCH", "${SWIFTEN_VERSION_PATCH}"),
])
res = res_env.RES("Swiften.rc")
# For some reason, SCons isn't picking up the dependency correctly
# Adding it explicitly until i figure out why
res_env.Depends(res, "Version.h")
sources += res
swiften_lib = myenv.SwiftenLibrary(swiften_env["SWIFTEN_LIBRARY_FILE"], sources + swiften_env["SWIFTEN_OBJECTS"])
def symlink(env, target, source) :
if os.path.exists(str(target[0])) :
os.unlink(str(target[0]))
os.symlink(source[0].get_contents(), str(target[0]))
for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] :
myenv.Command(myenv.File(alias), [myenv.Value(swiften_lib[0].name), swiften_lib[0]], symlink)
env.Append(UNITTEST_SOURCES = [
File("Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp"),
File("Avatars/UnitTest/VCardAvatarManagerTest.cpp"),
File("Avatars/UnitTest/CombinedAvatarProviderTest.cpp"),
+ File("Avatars/UnitTest/AvatarManagerImplTest.cpp"),
File("Base/UnitTest/IDGeneratorTest.cpp"),
File("Base/UnitTest/SimpleIDGeneratorTest.cpp"),
File("Base/UnitTest/StringTest.cpp"),
File("Base/UnitTest/DateTimeTest.cpp"),
File("Base/UnitTest/ByteArrayTest.cpp"),
File("Base/UnitTest/URLTest.cpp"),
File("Base/UnitTest/PathTest.cpp"),
File("Chat/UnitTest/ChatStateNotifierTest.cpp"),
# File("Chat/UnitTest/ChatStateTrackerTest.cpp"),
File("Client/UnitTest/ClientSessionTest.cpp"),
File("Client/UnitTest/NickResolverTest.cpp"),
File("Client/UnitTest/ClientBlockListManagerTest.cpp"),
File("Compress/UnitTest/ZLibCompressorTest.cpp"),
File("Compress/UnitTest/ZLibDecompressorTest.cpp"),
File("Component/UnitTest/ComponentHandshakeGeneratorTest.cpp"),
File("Component/UnitTest/ComponentConnectorTest.cpp"),
File("Component/UnitTest/ComponentSessionTest.cpp"),
File("Disco/UnitTest/CapsInfoGeneratorTest.cpp"),
File("Disco/UnitTest/CapsManagerTest.cpp"),
File("Disco/UnitTest/EntityCapsManagerTest.cpp"),
File("Disco/UnitTest/JIDDiscoInfoResponderTest.cpp"),
File("Disco/UnitTest/DiscoInfoResponderTest.cpp"),
File("Elements/UnitTest/IQTest.cpp"),
File("Elements/UnitTest/StanzaTest.cpp"),
File("Elements/UnitTest/FormTest.cpp"),
File("EventLoop/UnitTest/EventLoopTest.cpp"),
File("EventLoop/UnitTest/SimpleEventLoopTest.cpp"),
# File("History/UnitTest/SQLiteHistoryManagerTest.cpp"),
File("JID/UnitTest/JIDTest.cpp"),
File("LinkLocal/UnitTest/LinkLocalConnectorTest.cpp"),
File("LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp"),
File("LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp"),
File("LinkLocal/UnitTest/LinkLocalServiceTest.cpp"),
File("MUC/UnitTest/MUCTest.cpp"),
File("MUC/UnitTest/MockMUC.cpp"),
File("Network/UnitTest/HostAddressTest.cpp"),
File("Network/UnitTest/ConnectorTest.cpp"),
File("Network/UnitTest/ChainedConnectorTest.cpp"),
File("Network/UnitTest/DomainNameServiceQueryTest.cpp"),
File("Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp"),
File("Network/UnitTest/BOSHConnectionTest.cpp"),
File("Network/UnitTest/BOSHConnectionPoolTest.cpp"),
File("Parser/PayloadParsers/UnitTest/BlockParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/BodyParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/FormParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/CommandParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/RosterParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/IBBParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/JingleParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StatusParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ReplaceTest.cpp"),
File("Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/IdleParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/MAMArchivedParserTest.cpp"),
File("Parser/UnitTest/BOSHBodyExtractorTest.cpp"),
File("Parser/UnitTest/AttributeMapTest.cpp"),
File("Parser/UnitTest/EnumParserTest.cpp"),
File("Parser/UnitTest/IQParserTest.cpp"),
File("Parser/UnitTest/GenericPayloadTreeParserTest.cpp"),
File("Parser/UnitTest/MessageParserTest.cpp"),
File("Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp"),
File("Parser/UnitTest/PresenceParserTest.cpp"),
File("Parser/UnitTest/StanzaAckParserTest.cpp"),
File("Parser/UnitTest/SerializingParserTest.cpp"),
File("Parser/UnitTest/StanzaParserTest.cpp"),
File("Parser/UnitTest/StreamFeaturesParserTest.cpp"),
File("Parser/UnitTest/StreamManagementEnabledParserTest.cpp"),
File("Parser/UnitTest/XMLParserTest.cpp"),
File("Parser/UnitTest/XMPPParserTest.cpp"),
File("Presence/UnitTest/PresenceOracleTest.cpp"),
File("Presence/UnitTest/DirectedPresenceSenderTest.cpp"),
File("Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp"),
File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"),
File("Queries/UnitTest/IQRouterTest.cpp"),
File("Queries/UnitTest/RequestTest.cpp"),
File("Queries/UnitTest/ResponderTest.cpp"),
File("Roster/UnitTest/XMPPRosterImplTest.cpp"),
File("Roster/UnitTest/XMPPRosterControllerTest.cpp"),
File("Roster/UnitTest/XMPPRosterSignalHandler.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp"),
File("Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/MAMArchivedSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PubSubItemSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PubSubItemsSerializerTest.cpp"),
File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"),
File("Serializer/UnitTest/AuthSuccessSerializerTest.cpp"),
File("Serializer/UnitTest/AuthChallengeSerializerTest.cpp"),
File("Serializer/UnitTest/AuthRequestSerializerTest.cpp"),
File("Serializer/UnitTest/AuthResponseSerializerTest.cpp"),
File("Serializer/UnitTest/XMPPSerializerTest.cpp"),
File("Serializer/XML/UnitTest/XMLElementTest.cpp"),
File("StreamManagement/UnitTest/StanzaAckRequesterTest.cpp"),
File("StreamManagement/UnitTest/StanzaAckResponderTest.cpp"),
File("StreamStack/UnitTest/StreamStackTest.cpp"),
File("StreamStack/UnitTest/XMPPLayerTest.cpp"),
File("StringCodecs/UnitTest/Base64Test.cpp"),
File("StringCodecs/UnitTest/HexifyTest.cpp"),
File("StringCodecs/UnitTest/PBKDF2Test.cpp"),
File("TLS/UnitTest/ServerIdentityVerifierTest.cpp"),
File("TLS/UnitTest/CertificateTest.cpp"),
File("VCards/UnitTest/VCardManagerTest.cpp"),
File("Whiteboard/UnitTest/WhiteboardServerTest.cpp"),
File("Whiteboard/UnitTest/WhiteboardClientTest.cpp"),
])
# Generate the Swiften header
def relpath(path, start) :
i = len(os.path.commonprefix([path, start]))
return path[i+1:]
swiften_header = "#pragma once\n"
swiften_includes = []
top_path = env.Dir("..").abspath
for root, dirs, files in os.walk(env.Dir(".").abspath) :
if root.endswith("UnitTest") :
continue
for file in files :
if not file.endswith(".h") :
continue
include = relpath(os.path.join(root, file), top_path)
if swiften_env["PLATFORM"] == "win32" :
include = include.replace("\\", "/")
swiften_includes.append(include)
# Private modules
if root.endswith("Config") :
continue
# Library-specfifc private modules
if root.endswith("OpenSSL") or root.endswith("Cocoa") or root.endswith("Qt") or root.endswith("Avahi") or root.endswith("Bonjour") :
continue
# Library-specific files
if file.endswith("_Private.h") or file.startswith("Schannel") or file.startswith("CAPI") or file.startswith("MacOSX") or file.startswith("Windows") or file.endswith("_Windows.h") or file.startswith("SQLite") or file == "ICUConverter.h" or file == "UnboundDomainNameResolver.h" :
continue
# Specific headers we don't want to globally include
if file == "Swiften.h" or file == "foreach.h" or file == "Log.h" or file == "format.h" :
continue
swiften_header += "#include <" + include + ">\n"
swiften_includes.append(include)
swiften_env.WriteVal("Swiften.h", swiften_env.Value(swiften_header))
swiften_includes.append("Swiften/Swiften.h")
version_header = "#pragma once\n\n"
version_header += "#define SWIFTEN_VERSION 0x%02X%02X%02X\n" % (swiften_env["SWIFTEN_VERSION_MAJOR"], swiften_env["SWIFTEN_VERSION_MINOR"], swiften_env["SWIFTEN_VERSION_PATCH"])
version_header += "#define SWIFTEN_VERSION_STRING \"%s\"\n" % swiften_env["SWIFTEN_VERSION"]
swiften_env.WriteVal("Version.h", swiften_env.Value(version_header))
swiften_includes.append("Swiften/Version.h")
# Install swiften
if swiften_env.get("SWIFTEN_INSTALLDIR", "") :
swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib"), swiften_lib)
for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] :
myenv.Command(myenv.File(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib", alias)), [env.Value(swiften_lib[0].name), swiften_lib[0]], symlink)
for include in swiften_includes :
swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "include", os.path.dirname(include)), "#/" + include)