diff options
| author | Remko Tronçon <git@el-tramo.be> | 2010-10-23 21:08:19 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2010-11-03 12:17:40 (GMT) | 
| commit | 9d9fb66aefef85a1c5ad432391014d15011747d1 (patch) | |
| tree | 55b1ebe7dcb0108008a28ebf8fee773b27e60547 | |
| parent | d509598b0f0edf5e103caedbab8662edc834445e (diff) | |
| download | swift-9d9fb66aefef85a1c5ad432391014d15011747d1.zip swift-9d9fb66aefef85a1c5ad432391014d15011747d1.tar.bz2 | |
Added ClientDiscoManager.
| -rw-r--r-- | Swift/Controllers/MainController.cpp | 17 | ||||
| -rw-r--r-- | Swift/Controllers/MainController.h | 5 | ||||
| -rw-r--r-- | Swiften/Client/Client.cpp | 5 | ||||
| -rw-r--r-- | Swiften/Client/Client.h | 6 | ||||
| -rw-r--r-- | Swiften/Client/DummyStanzaChannel.h | 4 | ||||
| -rw-r--r-- | Swiften/Disco/ClientDiscoManager.cpp | 39 | ||||
| -rw-r--r-- | Swiften/Disco/ClientDiscoManager.h | 67 | ||||
| -rw-r--r-- | Swiften/Disco/DiscoInfoResponder.cpp | 5 | ||||
| -rw-r--r-- | Swiften/Disco/DiscoInfoResponder.h | 6 | ||||
| -rw-r--r-- | Swiften/Disco/SConscript | 1 | ||||
| -rw-r--r-- | Swiften/Elements/Body.h | 7 | ||||
| -rw-r--r-- | Swiften/Elements/CapsInfo.h | 5 | ||||
| -rw-r--r-- | Swiften/Elements/Payload.h | 9 | ||||
| -rw-r--r-- | Swiften/Presence/PayloadAddingPresenceSender.cpp | 44 | ||||
| -rw-r--r-- | Swiften/Presence/PayloadAddingPresenceSender.h | 34 | ||||
| -rw-r--r-- | Swiften/Presence/SConscript | 11 | ||||
| -rw-r--r-- | Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp | 131 | ||||
| -rw-r--r-- | Swiften/SConscript | 7 | 
18 files changed, 366 insertions, 37 deletions
| diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index f3b9977..5556a00 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -48,9 +48,9 @@  #include "Swiften/Elements/VCardUpdate.h"  #include "Swift/Controllers/Settings/SettingsProvider.h"  #include "Swiften/Elements/DiscoInfo.h" -#include "Swiften/Disco/DiscoInfoResponder.h"  #include "Swiften/Disco/CapsInfoGenerator.h"  #include "Swiften/Disco/GetDiscoInfoRequest.h" +#include "Swiften/Disco/ClientDiscoManager.h"  #include "Swiften/VCards/GetVCardRequest.h"  #include "Swiften/StringCodecs/SHA1.h"  #include "Swiften/StringCodecs/Hexify.h" @@ -99,7 +99,6 @@ MainController::MainController(  	rosterController_ = NULL;  	chatsManager_ = NULL;  	eventWindowController_ = NULL; -	discoResponder_ = NULL;  	mucSearchController_ = NULL;  	quitRequested_ = false; @@ -173,11 +172,6 @@ void MainController::resetClient() {  	resetPendingReconnects();  	delete mucSearchController_;  	mucSearchController_ = NULL; -	if (discoResponder_) { -		discoResponder_->stop(); -		delete discoResponder_; -		discoResponder_ = NULL; -	}  	delete eventWindowController_;  	eventWindowController_ = NULL;  	delete chatsManager_; @@ -247,12 +241,8 @@ void MainController::handleConnected() {  		discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));  		discoInfo.addFeature("urn:xmpp:sec-label:0");  		discoInfo.addFeature(ChatState::getFeatureNamespace()); -		capsInfo_ = boost::shared_ptr<CapsInfo>(new CapsInfo(CapsInfoGenerator(CLIENT_NODE).generateCapsInfo(discoInfo))); - -		discoResponder_ = new DiscoInfoResponder(client_->getIQRouter()); -		discoResponder_->setDiscoInfo(discoInfo); -		discoResponder_->setDiscoInfo(capsInfo_->getNode() + "#" + capsInfo_->getVersion(), discoInfo); -		discoResponder_->start(); +		client_->getDiscoManager()->setCapsNode(CLIENT_NODE); +		client_->getDiscoManager()->setDiscoInfo(discoInfo);  		mucSearchController_ = new MUCSearchController(jid_, uiEventStream_, mucSearchWindowFactory_, client_->getIQRouter());  	} @@ -317,7 +307,6 @@ void MainController::sendPresence(boost::shared_ptr<Presence> presence) {  	if (!vCardPhotoHash_.isEmpty()) {  		presence->updatePayload(boost::shared_ptr<VCardUpdate>(new VCardUpdate(vCardPhotoHash_)));  	} -	presence->updatePayload(capsInfo_);  	client_->getPresenceSender()->sendPresence(presence);  	if (presence->getType() == Presence::Unavailable) {  		logout(); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index c36c136..c05d098 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -17,8 +17,8 @@  #include "Swiften/Base/String.h"  #include "Swiften/Client/ClientError.h"  #include "Swiften/JID/JID.h" -#include "Swiften/Elements/VCard.h"  #include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Elements/VCard.h"  #include "Swiften/Elements/ErrorPayload.h"  #include "Swiften/Elements/Presence.h"  #include "Swift/Controllers/Settings/SettingsProvider.h" @@ -38,7 +38,6 @@ namespace Swift {  	class MainWindowFactory;  	class MainWindow;  	class RosterController; -	class DiscoInfoResponder;  	class LoginWindow;  	class EventLoop;  	class LoginWindowFactory; @@ -132,11 +131,9 @@ namespace Swift {  			EventController* eventController_;  			EventWindowController* eventWindowController_;  			LoginWindow* loginWindow_; -			DiscoInfoResponder* discoResponder_;  			UIEventStream* uiEventStream_;  			XMLConsoleController* xmlConsoleController_;  			ChatsManager* chatsManager_; -			boost::shared_ptr<CapsInfo> capsInfo_;  			JID jid_;  			JID boundJID_;  			SystemTrayController* systemTrayController_; diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index 7dbcb70..fd01e25 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -20,6 +20,7 @@  #include "Swiften/Avatars/AvatarManagerImpl.h"  #include "Swiften/Disco/CapsManager.h"  #include "Swiften/Disco/EntityCapsManager.h" +#include "Swiften/Disco/ClientDiscoManager.h"  #include "Swiften/Client/NickResolver.h"  #include "Swiften/Presence/SubscriptionManager.h" @@ -41,6 +42,7 @@ Client::Client(EventLoop* eventLoop, const JID& jid, const String& password, Sto  	stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel());  	directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); +	discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender);  	mucRegistry = new MUCRegistry();  	mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); @@ -64,6 +66,7 @@ Client::~Client() {  	delete mucManager;  	delete mucRegistry; +	delete discoManager;  	delete directedPresenceSender;  	delete stanzaChannelPresenceSender; @@ -106,7 +109,7 @@ Storages* Client::getStorages() const {  }  PresenceSender* Client::getPresenceSender() const { -	return directedPresenceSender; +	return discoManager->getPresenceSender();  }  } diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index adfd549..a17fe24 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -27,6 +27,7 @@ namespace Swift {  	class EntityCapsManager;  	class NickResolver;  	class SubscriptionManager; +	class ClientDiscoManager;  	/**  	 * Provides the core functionality for writing XMPP client software. @@ -122,6 +123,10 @@ namespace Swift {  				return subscriptionManager;  			} +			ClientDiscoManager* getDiscoManager() const { +				return discoManager; +			} +  		public:  			/**  			 * This signal is emitted when a JID changes presence. @@ -151,5 +156,6 @@ namespace Swift {  			NickResolver* nickResolver;  			SubscriptionManager* subscriptionManager;  			MUCManager* mucManager; +			ClientDiscoManager* discoManager;  	};  } diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index b8ae545..d9fb138 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -56,6 +56,10 @@ namespace Swift {  				return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>();  			} +			template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) { +				return boost::dynamic_pointer_cast<T>(sentStanzas[index]); +			} +  			std::vector<boost::shared_ptr<Stanza> > sentStanzas;  			bool available_;  	}; diff --git a/Swiften/Disco/ClientDiscoManager.cpp b/Swiften/Disco/ClientDiscoManager.cpp new file mode 100644 index 0000000..6753df2 --- /dev/null +++ b/Swiften/Disco/ClientDiscoManager.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Disco/ClientDiscoManager.h" + +#include "Swiften/Disco/DiscoInfoResponder.h" +#include "Swiften/Disco/CapsInfoGenerator.h" +#include "Swiften/Presence/PayloadAddingPresenceSender.h" + +namespace Swift { + +ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender) { +	discoInfoResponder = new DiscoInfoResponder(iqRouter); +	discoInfoResponder->start(); +	this->presenceSender = new PayloadAddingPresenceSender(presenceSender); +} + +ClientDiscoManager::~ClientDiscoManager() { +	delete presenceSender; +	discoInfoResponder->stop(); +	delete discoInfoResponder; +} + +void ClientDiscoManager::setCapsNode(const String& node) { +	capsNode = node; +} + +void ClientDiscoManager::setDiscoInfo(const DiscoInfo& discoInfo) { +	capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode).generateCapsInfo(discoInfo))); +	discoInfoResponder->clearDiscoInfo(); +	discoInfoResponder->setDiscoInfo(discoInfo); +	discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); +	presenceSender->setPayload(capsInfo); +} + +} diff --git a/Swiften/Disco/ClientDiscoManager.h b/Swiften/Disco/ClientDiscoManager.h new file mode 100644 index 0000000..b997374 --- /dev/null +++ b/Swiften/Disco/ClientDiscoManager.h @@ -0,0 +1,67 @@ +/* + * 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/Elements/CapsInfo.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Presence/PayloadAddingPresenceSender.h" + +namespace Swift { +	class IQRouter; +	class DiscoInfoResponder; +	class PayloadAddingPresenceSender; +	class PresenceSender; + +	/** +	 * Class responsible for managing outgoing disco information for a client. +	 * +	 * The manager will respond to disco#info requests, and add entity capabilities information +	 * to outgoing presence. +	 * +	 * To use this class, call setCapsNode() once with the caps URI of the client. After this, +	 * call setDiscoInfo() with the capabilities for the client. This can be +	 * called whenever the capabilities change. +	 */ +	class ClientDiscoManager { +		public: +			/** +			 * Constructs the manager +			 * +			 * \param iqRouter the router on which requests will be answered +			 * \param presenceSender the presence sender to which all outgoing presence +			 *   (with caps information) will be sent. +			 */ +			ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender); +			~ClientDiscoManager(); + +			/** +			 * Needs to be called before calling setDiscoInfo(). +			 */ +			void setCapsNode(const String& node); + +			/** +			 * Sets the capabilities of the client. +			 */ +			void setDiscoInfo(const DiscoInfo& info); + +			/** +			 * Returns the presence sender through which all outgoing presence +			 * should be sent. +			 * The manager will add the necessary caps information, and forward it to +			 * the presence sender passed at construction time. +			 */ +			PresenceSender* getPresenceSender() const { +				return presenceSender; +			} + +		private: +			PayloadAddingPresenceSender* presenceSender; +			DiscoInfoResponder* discoInfoResponder; +			String capsNode; +			CapsInfo::ref capsInfo; +	}; +} diff --git a/Swiften/Disco/DiscoInfoResponder.cpp b/Swiften/Disco/DiscoInfoResponder.cpp index 154eded..2e686c7 100644 --- a/Swiften/Disco/DiscoInfoResponder.cpp +++ b/Swiften/Disco/DiscoInfoResponder.cpp @@ -13,6 +13,11 @@ namespace Swift {  DiscoInfoResponder::DiscoInfoResponder(IQRouter* router) : GetResponder<DiscoInfo>(router) {  } +void DiscoInfoResponder::clearDiscoInfo() { +	info_ = DiscoInfo(); +	nodeInfo_.clear(); +} +  void DiscoInfoResponder::setDiscoInfo(const DiscoInfo& info) {  	info_ = info;  } diff --git a/Swiften/Disco/DiscoInfoResponder.h b/Swiften/Disco/DiscoInfoResponder.h index 4a7d271..0dc1172 100644 --- a/Swiften/Disco/DiscoInfoResponder.h +++ b/Swiften/Disco/DiscoInfoResponder.h @@ -4,8 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#ifndef SWIFTEN_DiscoInfoResponder_H -#define SWIFTEN_DiscoInfoResponder_H +#pragma once  #include <map> @@ -19,6 +18,7 @@ namespace Swift {  		public:  			DiscoInfoResponder(IQRouter* router); +			void clearDiscoInfo();  			void setDiscoInfo(const DiscoInfo& info);  			void setDiscoInfo(const String& node, const DiscoInfo& info); @@ -30,5 +30,3 @@ namespace Swift {  			std::map<String, DiscoInfo> nodeInfo_;  	};  } - -#endif diff --git a/Swiften/Disco/SConscript b/Swiften/Disco/SConscript index 3838d0e..a791946 100644 --- a/Swiften/Disco/SConscript +++ b/Swiften/Disco/SConscript @@ -7,6 +7,7 @@ objects = swiften_env.StaticObject([  			"EntityCapsProvider.cpp",  			"CapsStorage.cpp",  			"CapsFileStorage.cpp", +			"ClientDiscoManager.cpp",  			"DiscoInfoResponder.cpp",  		])  swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Elements/Body.h b/Swiften/Elements/Body.h index e3610c8..8262e09 100644 --- a/Swiften/Elements/Body.h +++ b/Swiften/Elements/Body.h @@ -4,8 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#ifndef SWIFTEN_Body_H -#define SWIFTEN_Body_H +#pragma once  #include "Swiften/Elements/Payload.h"  #include "Swiften/Base/String.h" @@ -13,6 +12,8 @@  namespace Swift {  	class Body : public Payload {  		public: +			typedef boost::shared_ptr<Body> ref; +  			Body(const String& text = "") : text_(text) {  			} @@ -28,5 +29,3 @@ namespace Swift {  			String text_;  	};  } - -#endif diff --git a/Swiften/Elements/CapsInfo.h b/Swiften/Elements/CapsInfo.h index 1968a29..dc3cc2e 100644 --- a/Swiften/Elements/CapsInfo.h +++ b/Swiften/Elements/CapsInfo.h @@ -6,13 +6,16 @@  #pragma once -#include "Swiften/Base/String.h" +#include <boost/shared_ptr.hpp> +#include "Swiften/Base/String.h"  #include "Swiften/Elements/Payload.h"  namespace Swift {  	class CapsInfo : public Payload {  		public: +			typedef boost::shared_ptr<CapsInfo> ref; +  			CapsInfo(const String& node = "", const String& version = "", const String& hash = "sha-1") : node_(node), version_(version), hash_(hash) {}  			bool operator==(const CapsInfo& o) const { diff --git a/Swiften/Elements/Payload.h b/Swiften/Elements/Payload.h index 9d7ed16..c87b899 100644 --- a/Swiften/Elements/Payload.h +++ b/Swiften/Elements/Payload.h @@ -4,14 +4,15 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#ifndef SWIFTEN_PAYLOAD_H -#define SWIFTEN_PAYLOAD_H +#pragma once + +#include <boost/shared_ptr.hpp>  namespace Swift {  	class Payload {  		public: +			typedef boost::shared_ptr<Payload> ref; +  			virtual ~Payload();  	};  } - -#endif diff --git a/Swiften/Presence/PayloadAddingPresenceSender.cpp b/Swiften/Presence/PayloadAddingPresenceSender.cpp new file mode 100644 index 0000000..c3d1638 --- /dev/null +++ b/Swiften/Presence/PayloadAddingPresenceSender.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Presence/PayloadAddingPresenceSender.h" + +namespace Swift { + +PayloadAddingPresenceSender::PayloadAddingPresenceSender(PresenceSender* sender) : sender(sender) { +} + +void PayloadAddingPresenceSender::sendPresence(Presence::ref presence) { +	if (presence->isAvailable()) { +		if (!presence->getTo().isValid()) { +			lastSentPresence = presence; +		} +	} +	else { +		lastSentPresence.reset(); +	} +	if (payload) { +		Presence::ref sentPresence = Presence::create(presence); +		sentPresence->updatePayload(payload); +		sender->sendPresence(sentPresence); +	} +	else { +		sender->sendPresence(presence); +	} +} + +bool PayloadAddingPresenceSender::isAvailable() const { +	return sender->isAvailable(); +} + +void PayloadAddingPresenceSender::setPayload(Payload::ref payload) { +	this->payload = payload; +	if (lastSentPresence) { +		sendPresence(lastSentPresence); +	} +} + +} diff --git a/Swiften/Presence/PayloadAddingPresenceSender.h b/Swiften/Presence/PayloadAddingPresenceSender.h new file mode 100644 index 0000000..5602ebe --- /dev/null +++ b/Swiften/Presence/PayloadAddingPresenceSender.h @@ -0,0 +1,34 @@ +/* + * 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/Presence/PresenceSender.h" +#include "Swiften/Elements/Payload.h" + +namespace Swift { +	class StanzaChannel; + +	/** +	 * This presence sender adds payloads to outgoing presences. +	 * +	 * +	 */ +	class PayloadAddingPresenceSender : public PresenceSender { +		public: +			PayloadAddingPresenceSender(PresenceSender*); + +			void sendPresence(Presence::ref); +			bool isAvailable() const; + +			void setPayload(Payload::ref); + +		private: +			Presence::ref lastSentPresence; +			PresenceSender* sender; +			Payload::ref payload; +	}; +} diff --git a/Swiften/Presence/SConscript b/Swiften/Presence/SConscript new file mode 100644 index 0000000..6911d45 --- /dev/null +++ b/Swiften/Presence/SConscript @@ -0,0 +1,11 @@ +Import("swiften_env") + +objects = swiften_env.StaticObject([ +			"PresenceOracle.cpp", +			"PresenceSender.cpp", +			"DirectedPresenceSender.cpp", +			"PayloadAddingPresenceSender.cpp", +			"StanzaChannelPresenceSender.cpp", +			"SubscriptionManager.cpp", +		]) +swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp b/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp new file mode 100644 index 0000000..3a6487a --- /dev/null +++ b/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp @@ -0,0 +1,131 @@ +/* + * 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 <vector> +#include <boost/bind.hpp> + +#include "Swiften/Presence/PayloadAddingPresenceSender.h" +#include "Swiften/Presence/StanzaChannelPresenceSender.h" +#include "Swiften/Elements/Body.h" +#include "Swiften/Client/DummyStanzaChannel.h" + +using namespace Swift; + +class PayloadAddingPresenceSenderTest : public CppUnit::TestFixture { +		CPPUNIT_TEST_SUITE(PayloadAddingPresenceSenderTest); +		CPPUNIT_TEST(testSetPayloadAddsPayloadOnPresenceSend); +		CPPUNIT_TEST(testSetNullPayloadDoesNotAddPayloadOnPresenceSend); +		CPPUNIT_TEST(testSendPresenceDoesNotAlterOriginalPayload); +		CPPUNIT_TEST(testSetPayloadAfterInitialPresenceResendsPresence); +		CPPUNIT_TEST(testSetPayloadAfterUnavailablePresenceDoesNotResendPresence); +		CPPUNIT_TEST(testSendDirectedPresenceIsNotResent); +		CPPUNIT_TEST_SUITE_END(); + +	public: +		void setUp() { +			stanzaChannel = new DummyStanzaChannel(); +			presenceSender = new StanzaChannelPresenceSender(stanzaChannel); +		} + +		void tearDown() { +			delete presenceSender; +			delete stanzaChannel; +		} + +		void testSetPayloadAddsPayloadOnPresenceSend() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			testling->setPayload(MyPayload::create("foo")); +			testling->sendPresence(Presence::create("bar")); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); +			CPPUNIT_ASSERT_EQUAL(String("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); +			CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); +		} + +		void testSetNullPayloadDoesNotAddPayloadOnPresenceSend() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			testling->setPayload(MyPayload::ref()); +			testling->sendPresence(Presence::create("bar")); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); +			CPPUNIT_ASSERT_EQUAL(String("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); +			CPPUNIT_ASSERT(!stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); +		} + +		void testSendPresenceDoesNotAlterOriginalPayload() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			testling->setPayload(MyPayload::create("foo")); +			Presence::ref presence(Presence::create("bar")); +			testling->sendPresence(presence); + +			CPPUNIT_ASSERT(!presence->getPayload<MyPayload>()); +		} + +		void testSetPayloadAfterInitialPresenceResendsPresence() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			testling->sendPresence(Presence::create("bar")); +			testling->setPayload(MyPayload::create("foo")); + +			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); +			CPPUNIT_ASSERT_EQUAL(String("bar"), stanzaChannel->getStanzaAtIndex<Presence>(1)->getStatus()); +			CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(1)->getPayload<MyPayload>()); +		} + +		void testSetPayloadAfterUnavailablePresenceDoesNotResendPresence() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			Presence::ref presence = Presence::create("bar"); +			presence->setType(Presence::Unavailable); +			testling->sendPresence(presence); + +			testling->setPayload(MyPayload::create("foo")); + +			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); +		} + +		void testSendDirectedPresenceIsNotResent() { +			std::auto_ptr<PayloadAddingPresenceSender> testling(createSender()); + +			testling->sendPresence(Presence::create("bar")); +			Presence::ref directedPresence = Presence::create("baz"); +			directedPresence->setTo(JID("foo@bar.com")); +			testling->sendPresence(directedPresence); +			testling->setPayload(MyPayload::create("foo")); + +			CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); +			CPPUNIT_ASSERT_EQUAL(String("bar"), stanzaChannel->getStanzaAtIndex<Presence>(2)->getStatus()); +		} + +	private: +		std::auto_ptr<PayloadAddingPresenceSender> createSender() { +			std::auto_ptr<PayloadAddingPresenceSender> sender(new PayloadAddingPresenceSender(presenceSender)); +			return sender; +		} + +		struct MyPayload : public Payload { +				typedef boost::shared_ptr<MyPayload> ref; + +				MyPayload(const String& body) : body(body) {} + +				static ref create(const String& body) { +					return ref(new MyPayload(body)); +				} + +				String body; +		}; + +	private: +		DummyStanzaChannel* stanzaChannel; +		StanzaChannelPresenceSender* presenceSender; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PayloadAddingPresenceSenderTest); diff --git a/Swiften/SConscript b/Swiften/SConscript index 5790672..9744f45 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -51,11 +51,6 @@ if env["SCONS_STAGE"] == "build" :  			"MUC/MUCOccupant.cpp",  			"MUC/MUCRegistry.cpp",  			"MUC/MUCBookmarkManager.cpp", -			"Presence/PresenceOracle.cpp", -			"Presence/PresenceSender.cpp", -			"Presence/DirectedPresenceSender.cpp", -			"Presence/StanzaChannelPresenceSender.cpp", -			"Presence/SubscriptionManager.cpp",  			"Queries/IQChannel.cpp",  			"Queries/IQHandler.cpp",  			"Queries/IQRouter.cpp", @@ -139,6 +134,7 @@ if env["SCONS_STAGE"] == "build" :  			"Disco",  			"VCards",  			"Network", +			"Presence",  			"FileTransfer",  			"History",  			"StreamStack", @@ -223,6 +219,7 @@ if env["SCONS_STAGE"] == "build" :  			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("Disco/UnitTest/DiscoInfoResponderTest.cpp"),  			File("Queries/UnitTest/IQRouterTest.cpp"), | 
 Swift
 Swift