Changeset - 2f542b507719
[Not reviewed]
0 5 0
HanzZ - 13 years ago 2012-09-22 18:09:25
hanzz.k@gmail.com
Unit tests can now test more resources interaction
5 files changed with 91 insertions and 5 deletions:
0 comments (0 inline, 0 general)
include/transport/user.h
Show inline comments
 
@@ -17,127 +17,131 @@
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <time.h>
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include "storagebackend.h"
 
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class RosterManager;
 
class ConversationManager;
 
class UserManager;
 
class PresenceOracle;
 
struct UserInfo;
 

	
 
/// Represents online XMPP user.
 
class User : public Swift::EntityCapsProvider {
 
	public:
 
		/// Creates new User class.
 
		/// \param jid XMPP JID associated with this user
 
		/// \param userInfo UserInfo struct with informations needed to connect
 
		/// this user to legacy network
 
		/// \param component Component associated with this user
 
		User(const Swift::JID &jid, UserInfo &userInfo, Component * component, UserManager *userManager);
 

	
 
		/// Destroyes User.
 
		virtual ~User();
 

	
 
		/// Returns JID of XMPP user who is currently connected using this User class.
 
		/// \return full JID
 
		const Swift::JID &getJID();
 

	
 
		/// Returns full JID which supports particular feature or invalid JID.
 
		/// \param feature disco#info feature.
 
		/// \return full JID which supports particular feature or invalid JID.
 
		Swift::JID getJIDWithFeature(const std::string &feature);
 

	
 
		Swift::DiscoInfo::ref getCaps(const Swift::JID &jid) const;
 

	
 
		/// Returns UserInfo struct with informations needed to connect the legacy network.
 
		/// \return UserInfo struct
 
		UserInfo &getUserInfo() { return m_userInfo; }
 

	
 
		RosterManager *getRosterManager() { return m_rosterManager; }
 

	
 
		ConversationManager *getConversationManager() { return m_conversationManager; }
 

	
 
		Component *getComponent() { return m_component; }
 

	
 
		void setData(void *data) { m_data = data; }
 
		void *getData() { return m_data; }
 

	
 
		/// Handles presence from XMPP JID associated with this user.
 
		/// \param presence Swift::Presence.
 
		void handlePresence(Swift::Presence::ref presence);
 

	
 
		void handleSubscription(Swift::Presence::ref presence);
 

	
 
		void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
 

	
 
		time_t &getLastActivity() {
 
			return m_lastActivity;
 
		}
 

	
 
		void updateLastActivity() {
 
			m_lastActivity = time(NULL);
 
		}
 

	
 
		/// Returns language.
 
		/// \return language
 
		const char *getLang() { return "en"; }
 

	
 
		void handleDisconnected(const std::string &error, Swift::SpectrumErrorPayload::Error e = Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR);
 

	
 
		bool isReadyToConnect() {
 
			return m_readyForConnect;
 
		}
 

	
 
		void setConnected(bool connected);
 

	
 
		void sendCurrentPresence();
 

	
 
		void setIgnoreDisconnect(bool ignoreDisconnect);
 

	
 
		bool isConnected() {
 
			return m_connected;
 
		}
 

	
 
		int getResourceCount() {
 
			return m_resources;
 
		}
 

	
 
		boost::signal<void ()> onReadyToConnect;
 
		boost::signal<void (Swift::Presence::ref presence)> onPresenceChanged;
 
		boost::signal<void (const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password)> onRoomJoined;
 
		boost::signal<void (const std::string &room)> onRoomLeft;
 
		boost::signal<void ()> onDisconnected;
 

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;
 
		RosterManager *m_rosterManager;
 
		UserManager *m_userManager;
 
		ConversationManager *m_conversationManager;
 
		Swift::EntityCapsManager *m_entityCapsManager;
 
		PresenceOracle *m_presenceOracle;
 
		UserInfo m_userInfo;
 
		void *m_data;
 
		bool m_connected;
 
		bool m_readyForConnect;
 
		bool m_ignoreDisconnect;
 
		Swift::Timer::ref m_reconnectTimer;
 
		boost::shared_ptr<Swift::Connection> connection;
 
		time_t m_lastActivity;
 
		std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
 
		std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
 
		int m_resources;
 
		int m_reconnectCounter;
 
};
 

	
 
}
src/tests/basictest.cpp
Show inline comments
 
#include "basictest.h"
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 

	
 
#include "Swiften/Serializer/GenericPayloadSerializer.h"
 

	
 
#include "../storageparser.h"
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "transport/BlockParser.h"
 
#include "transport/BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 

	
 
using namespace Transport;
 

	
 
void BasicTest::setMeUp (void) {
 
	streamEnded = false;
 
	std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost");
 
	std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost\nservice.more_resources=1\n");
 
	cfg = new Config();
 
	cfg->load(ifs);
 

	
 
	factory = new TestingFactory();
 

	
 
	storage = new TestingStorageBackend();
 

	
 
	loop = new Swift::DummyEventLoop();
 
	factories = new Swift::DummyNetworkFactories(loop);
 

	
 
	userRegistry = new UserRegistry(cfg, factories);
 

	
 
	component = new Component(loop, factories, cfg, factory, userRegistry);
 
	component->start();
 

	
 
	userManager = new UserManager(component, userRegistry, storage);
 

	
 
	userRegistration = new UserRegistration(component, userManager, storage);
 
	userRegistration->start();
 

	
 
	itemsResponder = new DiscoItemsResponder(component);
 
	itemsResponder->start();
 

	
 
	payloadSerializers = new Swift::FullPayloadSerializerCollection();
 
	payloadParserFactories = new Swift::FullPayloadParserFactoryCollection();
 

	
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 

	
 
	payloadSerializers->addSerializer(new Swift::AttentionSerializer());
 
	payloadSerializers->addSerializer(new Swift::XHTMLIMSerializer());
 
	payloadSerializers->addSerializer(new Transport::BlockSerializer());
 
	payloadSerializers->addSerializer(new Swift::InvisibleSerializer());
 
	payloadSerializers->addSerializer(new Swift::StatsSerializer());
 
	payloadSerializers->addSerializer(new Swift::SpectrumErrorSerializer());
 
	payloadSerializers->addSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
	parser = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 
	parser2 = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 

	
 
	serverFromClientSession = boost::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
			payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource")));
 
	serverFromClientSession->startSession();
 

	
 
	serverFromClientSession->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived, this, _1));
 

	
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->addSession(serverFromClientSession);
 
	parser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	parser2->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	loop->processEvents();
 
}
 

	
 
void BasicTest::tearMeDown (void) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->removeSession(serverFromClientSession);
 
	if (serverFromClientSession2) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->removeSession(serverFromClientSession2);
 
		serverFromClientSession2.reset();
 
	}
 
	delete component;
 
	delete userRegistry;
 
	delete factories;
 
	delete factory;
 
	delete loop;
 
	delete cfg;
 
	delete parser;
 
	delete parser2;
 
	delete storage;
 
	delete userRegistration;
 
	delete itemsResponder;
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	receivedData2.clear();
 
}
 

	
 
void BasicTest::handleDataReceived(const Swift::SafeByteArray &data) {
 
// 	std::cout << safeByteArrayToString(data) << "\n";
 
	stream1_active = true;
 
	receivedData += safeByteArrayToString(data) + "\n";
 
	parser->parse(safeByteArrayToString(data));
 
}
 

	
 
void BasicTest::handleDataReceived2(const Swift::SafeByteArray &data) {
 
// 	std::cout << safeByteArrayToString(data) << "\n";
 
	stream1_active = false;
 
	receivedData2 += safeByteArrayToString(data) + "\n";
 
	parser2->parse(safeByteArrayToString(data));
 
}
 

	
 
void BasicTest::handleStreamStart(const Swift::ProtocolHeader&) {
 

	
 
}
 

	
 
void BasicTest::dumpReceived() {
 
	std::cout << "\nStream1:\n";
 
	std::cout << receivedData << "\n";
 
	std::cout << "Stream2:\n";
 
	std::cout << receivedData2 << "\n";
 
}
 

	
 
void BasicTest::handleElement(boost::shared_ptr<Swift::Element> element) {
 
	if (stream1_active) {
 
		received.push_back(element);
 
	}
 
	else {
 
		received2.push_back(element);
 
	}
 
}
 

	
 
void BasicTest::handleStreamEnd() {
 
	streamEnded = true;
 
}
 

	
 
void BasicTest::injectPresence(boost::shared_ptr<Swift::Presence> &response) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
}
 

	
 
void BasicTest::injectIQ(boost::shared_ptr<Swift::IQ> iq) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onIQReceived(iq);
 
}
 

	
 
void BasicTest::injectMessage(boost::shared_ptr<Swift::Message> msg) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onMessageReceived(msg);
 
}
 

	
 
Swift::Stanza *BasicTest::getStanza(boost::shared_ptr<Swift::Element> element) {
 
	Swift::Stanza *stanza = dynamic_cast<Swift::Stanza *>(element.get());
 
	CPPUNIT_ASSERT(stanza);
 
	return stanza;
 
}
 

	
 
void BasicTest::connectUser() {
 
	CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
	userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
	userRegistry->onPasswordValid(Swift::JID("user@localhost/resource"));
 
	loop->processEvents();
 
	CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount());
 

	
 
	User *user = userManager->getUser("user@localhost");
 
	CPPUNIT_ASSERT(user);
 

	
 
	UserInfo userInfo = user->getUserInfo();
 
	CPPUNIT_ASSERT_EQUAL(std::string("password"), userInfo.password);
 
	CPPUNIT_ASSERT(user->isReadyToConnect() == true);
 
	CPPUNIT_ASSERT(user->isConnected() == false);
 

	
 
	user->setConnected(true);
 
	CPPUNIT_ASSERT(user->isConnected() == true);
 

	
 
	CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
	CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
	CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
	received.clear();
 
	receivedData.clear();
 
}
 

	
 
void BasicTest::connectSecondResource() {
 
	serverFromClientSession2 = boost::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
			payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource2")));
 
	serverFromClientSession2->startSession();
 

	
 
	serverFromClientSession2->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived2, this, _1));
 

	
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->addSession(serverFromClientSession2);
 

	
 
	userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource2"), serverFromClientSession2.get(), Swift::createSafeByteArray("password"));
 
	userRegistry->onPasswordValid(Swift::JID("user@localhost/resource2"));
 

	
 
	loop->processEvents();
 

	
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo("localhost");
 
	response->setFrom("user@localhost/resource2");
 
	injectPresence(response);
 
	loop->processEvents();
 

	
 
	CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount());
 

	
 
	User *user = userManager->getUser("user@localhost");
 
	CPPUNIT_ASSERT(user);
 
	CPPUNIT_ASSERT_EQUAL(2, user->getResourceCount());
 

	
 
	CPPUNIT_ASSERT(getStanza(received2[1])->getPayload<Swift::DiscoInfo>());
 
}
 

	
 
void BasicTest::disconnectUser() {
 
	userManager->disconnectUser("user@localhost");
 
	dynamic_cast<Swift::DummyTimerFactory *>(factories->getTimerFactory())->setTime(10);
 
	loop->processEvents();
 

	
 
	CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
	CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
	CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
}
 

	
 
void BasicTest::add2Buddies() {
 
	User *user = userManager->getUser("user@localhost");
 
	CPPUNIT_ASSERT(user);
 

	
 
	std::vector<std::string> grp;
 
	grp.push_back("group1");
 
	LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "Buddy 1", grp, BUDDY_JID_ESCAPING);
 
	buddy->setStatus(Swift::StatusShow(Swift::StatusShow::Away), "status1");
 
	user->getRosterManager()->setBuddy(buddy);
 

	
 
	std::vector<std::string> grp2;
 
	grp2.push_back("group2");
 
	buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy2", "Buddy 2", grp2, BUDDY_JID_ESCAPING);
 
	buddy->setStatus(Swift::StatusShow(Swift::StatusShow::Away), "status2");
 
	user->getRosterManager()->setBuddy(buddy);
 
}
 

	
src/tests/basictest.h
Show inline comments
 
@@ -112,145 +112,152 @@ class TestingStorageBackend : public StorageBackend {
 
			return true;
 
		}
 

	
 
		/// createDatabase
 
		virtual bool createDatabase() {return true;}
 

	
 
		/// setUser
 
		virtual void setUser(const UserInfo &user) {
 
			users[user.jid] = user;
 
		}
 

	
 
		/// getuser
 
		virtual bool getUser(const std::string &barejid, UserInfo &user) {
 
			if (users.find(barejid) == users.end()) {
 
				return false;
 
			}
 
			user = users[barejid];
 
			return true;
 
		}
 

	
 
		std::string findUserByID(long id) {
 
			for (std::map<std::string, UserInfo>::const_iterator it = users.begin(); it != users.end(); it++) {
 
				if (it->second.id == id) {
 
					return it->first;
 
				}
 
			}
 
			return "";
 
		}
 

	
 
		/// setUserOnline
 
		virtual void setUserOnline(long id, bool online) {
 
			std::string user = findUserByID(id);
 
			if (user.empty()) {
 
				return;
 
			}
 
			online_users[user] = online;
 
		}
 

	
 
		/// removeUser
 
		virtual bool removeUser(long id) {
 
			std::string user = findUserByID(id);
 
			if (user.empty()) {
 
				return false;
 
			}
 
			users.erase(user);
 
			return true;
 
		}
 

	
 
		/// getBuddies
 
		virtual bool getBuddies(long id, std::list<BuddyInfo> &roster) {
 
			return true;
 
		}
 

	
 
		/// getOnlineUsers
 
		virtual bool getOnlineUsers(std::vector<std::string> &users) {
 
			return true;
 
		}
 

	
 
		virtual long addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
			return buddyid++;
 
		}
 
		virtual void updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
			
 
		}
 

	
 
		virtual void removeBuddy(long id) {
 
			
 
		}
 

	
 
		virtual void getBuddySetting(long userId, long buddyId, const std::string &variable, int &type, std::string &value) {}
 
		virtual void updateBuddySetting(long userId, long buddyId, const std::string &variable, int type, const std::string &value) {}
 

	
 
		virtual void getUserSetting(long userId, const std::string &variable, int &type, std::string &value) {
 
			if (settings[userId].find(variable) == settings[userId].end()) {
 
				settings[userId][variable] = value;
 
				return;
 
			}
 
			value = settings[userId][variable];
 
		}
 

	
 
		virtual void updateUserSetting(long userId, const std::string &variable, const std::string &value) {
 
			settings[userId][variable] = value;
 
		}
 

	
 
		virtual void beginTransaction() {}
 
		virtual void commitTransaction() {}
 
};
 

	
 
class BasicTest : public Swift::XMPPParserClient {
 

	
 
	public:
 
		void setMeUp (void);
 

	
 
		void tearMeDown (void);
 

	
 
	void handleDataReceived(const Swift::SafeByteArray &data);
 
	void handleDataReceived2(const Swift::SafeByteArray &data);
 

	
 
	void handleStreamStart(const Swift::ProtocolHeader&);
 

	
 
	void handleElement(boost::shared_ptr<Swift::Element> element);
 

	
 
	void handleStreamEnd();
 

	
 
	void injectPresence(boost::shared_ptr<Swift::Presence> &response);
 
	void injectIQ(boost::shared_ptr<Swift::IQ> iq);
 
	void injectMessage(boost::shared_ptr<Swift::Message> msg);
 

	
 
	void dumpReceived();
 

	
 
	void addUser() {
 
		UserInfo user;
 
		user.id = 1;
 
		user.jid = "user@localhost";
 
		user.uin = "legacyname";
 
		user.password = "password";
 
		storage->setUser(user);
 
	}
 

	
 
	void connectUser();
 
	void connectSecondResource();
 
	void disconnectUser();
 
	void add2Buddies();
 

	
 
	Swift::Stanza *getStanza(boost::shared_ptr<Swift::Element> element);
 

	
 
	protected:
 
		bool streamEnded;
 
		UserManager *userManager;
 
		boost::shared_ptr<Swift::ServerFromClientSession> serverFromClientSession;
 
		boost::shared_ptr<Swift::ServerFromClientSession> serverFromClientSession2;
 
		Swift::FullPayloadSerializerCollection* payloadSerializers;
 
		Swift::FullPayloadParserFactoryCollection* payloadParserFactories;
 
		Swift::XMPPParser *parser;
 
		Swift::XMPPParser *parser2;
 
		UserRegistry *userRegistry;
 
		Config *cfg;
 
		Swift::Server *server;
 
		Swift::DummyNetworkFactories *factories;
 
		Swift::DummyEventLoop *loop;
 
		TestingFactory *factory;
 
		Component *component;
 
		std::vector<boost::shared_ptr<Swift::Element> > received;
 
		std::vector<boost::shared_ptr<Swift::Element> > received2;
 
		std::string receivedData;
 
		std::string receivedData2;
 
		StorageBackend *storage;
 
		UserRegistration *userRegistration;
 
		DiscoItemsResponder *itemsResponder;
 
		bool stream1_active;
 
};
 

	
src/tests/usermanager.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(UserManagerTest);
 
	CPPUNIT_TEST(connectUser);
 
	CPPUNIT_TEST(connectTwoResources);
 
	CPPUNIT_TEST(connectUserTransportDisabled);
 
	CPPUNIT_TEST(connectUserRegistrationNeeded);
 
	CPPUNIT_TEST(connectUserRegistrationNeededRegistered);
 
	CPPUNIT_TEST(handleProbePresence);
 
	CPPUNIT_TEST(disconnectUser);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
			setMeUp();
 
		}
 

	
 
		void tearDown (void) {
 
			tearMeDown();
 
		}
 

	
 
	void connectUserTransportDisabled() {
 
		addUser();
 
		storage->updateUserSetting(1, "enable_transport", "0");
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 

	
 
		User *user = userManager->getUser("user@localhost");
 
		CPPUNIT_ASSERT(!user);
 
	}
 

	
 
	void connectUserRegistrationNeeded() {
 
		cfg->updateBackendConfig("[registration]\nneedRegistration=1\n");
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		CPPUNIT_ASSERT(streamEnded);
 
	}
 

	
 
	void connectUserRegistrationNeededRegistered() {
 
		addUser();
 
		cfg->updateBackendConfig("[registration]\nneedRegistration=1\n");
 
		CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
		userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(1, userManager->getUserCount());
 
		CPPUNIT_ASSERT(!streamEnded);
 
	}
 

	
 
	void handleProbePresence() {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		response->setType(Swift::Presence::Probe);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 

	
 
		Swift::Presence *presence = dynamic_cast<Swift::Presence *>(getStanza(received[1]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, presence->getType());
 
	}
 

	
 
	void connectTwoResources() {
 
		connectUser();
 
		add2Buddies();
 
		connectSecondResource();
 

	
 
		// we should get presences
 
		CPPUNIT_ASSERT_EQUAL(4, (int) received2.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received2[2])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received2[2]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast<Swift::Presence *>(getStanza(received2[2]))->getStatus());
 

	
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received2[3])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received2[3]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast<Swift::Presence *>(getStanza(received2[3]))->getStatus());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (UserManagerTest);
src/user.cpp
Show inline comments
 
@@ -173,197 +173,198 @@ void User::setConnected(bool connected) {
 
	m_connected = connected;
 
	m_reconnectCounter = 0;
 
	setIgnoreDisconnect(false);
 
	updateLastActivity();
 

	
 
	sendCurrentPresence();
 
}
 

	
 
void User::handlePresence(Swift::Presence::ref presence) {
 

	
 
	int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
 

	
 
	m_conversationManager->resetResources();
 

	
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			
 
			// Forward status message to legacy network, but only if it's sent from active resource
 
// 					if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
 
// 						forwardStatus(presenceShow, stanzaStatus);
 
// 					}
 
			boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>();
 
			if (capsInfo && capsInfo->getHash() == "sha-1") {
 
				if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) {
 
					LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
					m_readyForConnect = true;
 
					onReadyToConnect();
 
				}
 
				else {
 
					m_reconnectTimer->start();
 
				}
 
			}
 
			else if (m_component->inServerMode()) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 
			else {
 
				m_reconnectTimer->start();
 
			}
 
		}
 
	}
 

	
 
	bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
	if (isMUC) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
			std::string room = Buddy::JIDToLegacyName(presence->getTo());
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room);
 
			onRoomLeft(room);
 

	
 
			Conversation *conv = m_conversationManager->getConversation(room);
 
			if (conv) {
 
				m_conversationManager->removeConversation(conv);
 
				delete conv;
 
			}
 
		}
 
		else {
 
			// force connection to legacy network to let backend to handle auto-join on connect.
 
			if (!m_readyForConnect) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 
			std::string room = Buddy::JIDToLegacyName(presence->getTo());
 
			if (m_conversationManager->getConversation(room) != NULL) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource());
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource());
 
			std::string password = "";
 
			if (presence->getPayload<Swift::MUCPayload>() != NULL) {
 
				password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
 
			}
 
			onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
 
		}
 
		return;
 
	}
 

	
 

	
 
	// User wants to disconnect this resource
 
	if (!m_component->inServerMode()) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
				// Send unavailable presences for online contacts
 
				m_rosterManager->sendUnavailablePresences(presence->getFrom());
 

	
 
				// Send unavailable presence for transport contact itself
 
				Swift::Presence::ref response = Swift::Presence::create();
 
				response->setTo(presence->getFrom());
 
				response->setFrom(m_component->getJID());
 
				response->setType(Swift::Presence::Unavailable);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
		}
 
		else {
 
			sendCurrentPresence();
 
			// This resource is new, so we have to send buddies presences
 
			if (currentResourcesCount != m_resources) {
 
				m_rosterManager->sendCurrentPresences(presence->getFrom());
 
		}
 
	}
 

	
 
	// This resource is new, so we have to send buddies presences
 
	if (presence->getType() != Swift::Presence::Unavailable && currentResourcesCount != m_resources) {
 
		m_rosterManager->sendCurrentPresences(presence->getFrom());
 
	}
 

	
 
	m_resources = currentResourcesCount;
 

	
 

	
 
	// Change legacy network presence
 
	if (m_readyForConnect) {
 
		Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 
		if (highest) {
 
			Swift::Presence::ref response = Swift::Presence::create(highest);
 
			response->setTo(m_jid);
 
			response->setFrom(m_component->getJID());
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType());
 
			onPresenceChanged(highest);
 
		}
 
		else {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(m_jid.toBare());
 
			response->setFrom(m_component->getJID());
 
			response->setType(Swift::Presence::Unavailable);
 
			onPresenceChanged(response);
 
		}
 
	}
 
}
 

	
 
void User::handleSubscription(Swift::Presence::ref presence) {
 
	m_rosterManager->handleSubscription(presence);
 
}
 

	
 
void User::handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info) {
 
	LOG4CXX_INFO(logger, jid.toString() << ": got disco#info");
 
#ifdef SUPPORT_LEGACY_CAPS
 
	Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid);
 
	// This is old legacy cap which is not stored in entityCapsManager,
 
	// we have to store it in our user class.
 
	if (!discoInfo) {
 
		LOG4CXX_INFO(logger, jid.toString() << ": LEGACY");
 
		m_legacyCaps[jid] = info;
 
	}
 
#endif
 

	
 
	onConnectingTimeout();
 
}
 

	
 
void User::onConnectingTimeout() {
 
	if (m_connected || m_readyForConnect)
 
		return;
 
	m_reconnectTimer->stop();
 
	m_readyForConnect = true;
 
	onReadyToConnect();
 

	
 
	Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 
	if (highest) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << highest->getType());
 
		onPresenceChanged(highest);
 
	}
 
}
 

	
 
void User::setIgnoreDisconnect(bool ignoreDisconnect) {
 
	m_ignoreDisconnect = ignoreDisconnect;
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Setting ignoreDisconnect=" << m_ignoreDisconnect);
 
}
 

	
 
void User::handleDisconnected(const std::string &error, Swift::SpectrumErrorPayload::Error e) {
 
	if (m_ignoreDisconnect) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network ignored (probably moving between backends)");
 
		return;
 
	}
 

	
 
	if (e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR || e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR) {
 
		if (m_reconnectCounter < 3) {
 
			m_reconnectCounter++;
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network " << error << ", trying to reconnect automatically.");
 
			// Simulate destruction/resurrection :)
 
			// TODO: If this stops working, create onReconnect signal
 
			m_userManager->onUserDestroyed(this);
 
			m_userManager->onUserCreated(this);
 
			onReadyToConnect();
 
			return;
 
		}
 
	}
 

	
 
	if (error.empty()) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network");
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network with error " << error);
 
	}
 
	onDisconnected();
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(error);
 
	msg->setTo(m_jid.toBare());
 
	msg->setFrom(m_component->getJID());
 
	msg->addPayload(boost::make_shared<Swift::SpectrumErrorPayload>(e));
 
	m_component->getStanzaChannel()->sendMessage(msg);
0 comments (0 inline, 0 general)