From 75bc454c85c2bde4eab56c9ff70842ea5012a4f1 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 25 Aug 2011 11:24:03 +0200 Subject: [PATCH] UserRegistry test --- .../Network/DummyConnectionFactory.cpp | 19 ++ .../Swiften/Network/DummyConnectionFactory.h | 26 +++ .../Swiften/Network/DummyConnectionServer.cpp | 40 ++++ .../Swiften/Network/DummyConnectionServer.h | 49 +++++ .../Network/DummyConnectionServerFactory.cpp | 23 +++ .../Network/DummyConnectionServerFactory.h | 28 +++ .../Swiften/Network/DummyNetworkFactories.cpp | 29 +++ .../Swiften/Network/DummyNetworkFactories.h | 41 ++++ include/Swiften/Server/Server.cpp | 7 +- include/Swiften/Server/Server.h | 4 + src/tests/main.cpp | 10 + src/tests/userregistry.cpp | 191 +++++++++++++++++- 12 files changed, 457 insertions(+), 10 deletions(-) create mode 100644 include/Swiften/Network/DummyConnectionFactory.cpp create mode 100644 include/Swiften/Network/DummyConnectionFactory.h create mode 100644 include/Swiften/Network/DummyConnectionServer.cpp create mode 100644 include/Swiften/Network/DummyConnectionServer.h create mode 100644 include/Swiften/Network/DummyConnectionServerFactory.cpp create mode 100644 include/Swiften/Network/DummyConnectionServerFactory.h create mode 100644 include/Swiften/Network/DummyNetworkFactories.cpp create mode 100644 include/Swiften/Network/DummyNetworkFactories.h diff --git a/include/Swiften/Network/DummyConnectionFactory.cpp b/include/Swiften/Network/DummyConnectionFactory.cpp new file mode 100644 index 00000000..e458d179 --- /dev/null +++ b/include/Swiften/Network/DummyConnectionFactory.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include + +namespace Swift { + +DummyConnectionFactory::DummyConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { +} + +boost::shared_ptr DummyConnectionFactory::createConnection() { + return boost::shared_ptr(new DummyConnection(eventLoop)); +} + +} diff --git a/include/Swiften/Network/DummyConnectionFactory.h b/include/Swiften/Network/DummyConnectionFactory.h new file mode 100644 index 00000000..6f1a91d5 --- /dev/null +++ b/include/Swiften/Network/DummyConnectionFactory.h @@ -0,0 +1,26 @@ +/* + * 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 + +#include +#include + +namespace Swift { + class DummyConnection; + + class DummyConnectionFactory : public ConnectionFactory { + public: + DummyConnectionFactory(EventLoop* eventLoop); + + virtual boost::shared_ptr createConnection(); + + private: + EventLoop* eventLoop; + }; +} diff --git a/include/Swiften/Network/DummyConnectionServer.cpp b/include/Swiften/Network/DummyConnectionServer.cpp new file mode 100644 index 00000000..7250dce3 --- /dev/null +++ b/include/Swiften/Network/DummyConnectionServer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include + +#include +#include +#include + +#include + +namespace Swift { + +DummyConnectionServer::DummyConnectionServer(EventLoop* eventLoop) : eventLoop(eventLoop) { +} + +void DummyConnectionServer::start() { +} + + +void DummyConnectionServer::stop() { + +} + +void DummyConnectionServer::acceptConnection(boost::shared_ptr connection) { + eventLoop->postEvent( + boost::bind(boost::ref(onNewConnection), connection), + shared_from_this()); +// connection->listen(); +} + + +HostAddressPort DummyConnectionServer::getAddressPort() const { + return HostAddressPort(); +} + +} diff --git a/include/Swiften/Network/DummyConnectionServer.h b/include/Swiften/Network/DummyConnectionServer.h new file mode 100644 index 00000000..0e2a141c --- /dev/null +++ b/include/Swiften/Network/DummyConnectionServer.h @@ -0,0 +1,49 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include + +namespace Swift { + class DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this { + public: + typedef boost::shared_ptr ref; + + enum Error { + Conflict, + UnknownError + }; + + static ref create(EventLoop* eventLoop) { + return ref(new DummyConnectionServer(eventLoop)); + } + + void acceptConnection(boost::shared_ptr connection); + + virtual void start(); + virtual void stop(); + + virtual HostAddressPort getAddressPort() const; + + + private: + DummyConnectionServer(EventLoop* eventLoop); + + + private: + HostAddress address_; + EventLoop* eventLoop; + }; +} diff --git a/include/Swiften/Network/DummyConnectionServerFactory.cpp b/include/Swiften/Network/DummyConnectionServerFactory.cpp new file mode 100644 index 00000000..4fbabbc2 --- /dev/null +++ b/include/Swiften/Network/DummyConnectionServerFactory.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include +#include + +namespace Swift { + +DummyConnectionServerFactory::DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { +} + +boost::shared_ptr DummyConnectionServerFactory::createConnectionServer(int port) { + return DummyConnectionServer::create(eventLoop); +} + +boost::shared_ptr DummyConnectionServerFactory::createConnectionServer(const Swift::HostAddress &hostAddress, int port) { + return DummyConnectionServer::create(eventLoop); +} + +} diff --git a/include/Swiften/Network/DummyConnectionServerFactory.h b/include/Swiften/Network/DummyConnectionServerFactory.h new file mode 100644 index 00000000..a4bdbfd2 --- /dev/null +++ b/include/Swiften/Network/DummyConnectionServerFactory.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include + +#include +#include + +namespace Swift { + class ConnectionServer; + + class DummyConnectionServerFactory : public ConnectionServerFactory { + public: + DummyConnectionServerFactory(EventLoop* eventLoop); + + virtual boost::shared_ptr createConnectionServer(int port); + + virtual boost::shared_ptr createConnectionServer(const Swift::HostAddress &hostAddress, int port); + + private: + EventLoop* eventLoop; + }; +} diff --git a/include/Swiften/Network/DummyNetworkFactories.cpp b/include/Swiften/Network/DummyNetworkFactories.cpp new file mode 100644 index 00000000..cf47d7cc --- /dev/null +++ b/include/Swiften/Network/DummyNetworkFactories.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include +#include +#include +#include + +namespace Swift { + +DummyNetworkFactories::DummyNetworkFactories(EventLoop* eventLoop) { + timerFactory = new DummyTimerFactory(); + connectionFactory = new DummyConnectionFactory(eventLoop); + domainNameResolver = new PlatformDomainNameResolver(eventLoop); + connectionServerFactory = new DummyConnectionServerFactory(eventLoop); +} + +DummyNetworkFactories::~DummyNetworkFactories() { + delete connectionServerFactory; + delete domainNameResolver; + delete connectionFactory; + delete timerFactory; +} + +} diff --git a/include/Swiften/Network/DummyNetworkFactories.h b/include/Swiften/Network/DummyNetworkFactories.h new file mode 100644 index 00000000..50b9f338 --- /dev/null +++ b/include/Swiften/Network/DummyNetworkFactories.h @@ -0,0 +1,41 @@ +/* + * 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 + +namespace Swift { + class EventLoop; + + class DummyNetworkFactories : public NetworkFactories { + public: + DummyNetworkFactories(EventLoop *eventLoop); + ~DummyNetworkFactories(); + + virtual TimerFactory* getTimerFactory() const { + return timerFactory; + } + + virtual ConnectionFactory* getConnectionFactory() const { + return connectionFactory; + } + + DomainNameResolver* getDomainNameResolver() const { + return domainNameResolver; + } + + ConnectionServerFactory* getConnectionServerFactory() const { + return connectionServerFactory; + } + + private: + TimerFactory* timerFactory; + ConnectionFactory* connectionFactory; + DomainNameResolver* domainNameResolver; + ConnectionServerFactory* connectionServerFactory; + }; +} diff --git a/include/Swiften/Server/Server.cpp b/include/Swiften/Server/Server.cpp index ff623b62..4323263e 100644 --- a/include/Swiften/Server/Server.cpp +++ b/include/Swiften/Server/Server.cpp @@ -79,9 +79,9 @@ void Server::stop() { stopping = true; - foreach(boost::shared_ptr session, serverFromClientSessions) { - session->finishSession(); - } +// foreach(boost::shared_ptr session, serverFromClientSessions) { +// session->finishSession(); +// } serverFromClientSessions.clear(); if (serverFromClientConnectionServer) { @@ -141,7 +141,6 @@ void Server::handleSessionFinished(boost::shared_ptr se // dynamic_cast(stanzaChannel_)->onPresenceReceived(presence); // } serverFromClientSessions.erase(std::remove(serverFromClientSessions.begin(), serverFromClientSessions.end(), session), serverFromClientSessions.end()); - std::cout << "FINISH SESSION2 " << serverFromClientSessions.size() << "\n"; session->onSessionStarted.disconnect( boost::bind(&Server::handleSessionStarted, this, session)); session->onSessionFinished.disconnect( diff --git a/include/Swiften/Server/Server.h b/include/Swiften/Server/Server.h index aa605a42..a3e664e1 100644 --- a/include/Swiften/Server/Server.h +++ b/include/Swiften/Server/Server.h @@ -52,6 +52,10 @@ namespace Swift { return iqRouter_; } + boost::shared_ptr getConnectionServer() const { + return serverFromClientConnectionServer; + } + boost::signal onDataRead; boost::signal onDataWritten; diff --git a/src/tests/main.cpp b/src/tests/main.cpp index dd1c5f27..55ba41ae 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -5,9 +5,19 @@ #include #include #include +#include "log4cxx/logger.h" +#include "log4cxx/fileappender.h" +#include "log4cxx/patternlayout.h" +#include "log4cxx/propertyconfigurator.h" + +using namespace log4cxx; + int main (int argc, char* argv[]) { + LoggerPtr root = Logger::getRootLogger(); + root->addAppender(new FileAppender(new PatternLayout("%d %-5p %c: %m%n"), "libtransport_test.log", false)); + // informs test-listener about testresults CPPUNIT_NS :: TestResult testresult; diff --git a/src/tests/userregistry.cpp b/src/tests/userregistry.cpp index 3bf485ef..d394ae1f 100644 --- a/src/tests/userregistry.cpp +++ b/src/tests/userregistry.cpp @@ -2,31 +2,210 @@ #include "transport/config.h" #include #include +#include +#include +#include +#include using namespace Transport; class UserRegistryTest : public CPPUNIT_NS :: TestFixture { - CPPUNIT_TEST_SUITE (UserRegistryTest); -// CPPUNIT_TEST (storeBuddies); -// CPPUNIT_TEST (storeBuddiesRemove); - CPPUNIT_TEST_SUITE_END (); + CPPUNIT_TEST_SUITE(UserRegistryTest); + CPPUNIT_TEST(login); + CPPUNIT_TEST(loginInvalidPassword); + CPPUNIT_TEST(loginTwoClientsValidPasswords); + CPPUNIT_TEST(loginTwoClientsDifferentPasswords); + CPPUNIT_TEST(loginDisconnect); + CPPUNIT_TEST(removeLater); + CPPUNIT_TEST_SUITE_END(); public: void setUp (void) { + state1 = Init; + state2 = Init; std::istringstream ifs; cfg = new Config(); cfg->load(ifs); -// userRegistry = new UserRegistry(cfg); + + loop = new Swift::DummyEventLoop(); + factories = new Swift::DummyNetworkFactories(loop); + + userRegistry = new UserRegistry(cfg, factories); + userRegistry->onConnectUser.connect(bind(&UserRegistryTest::handleConnectUser, this, _1)); + userRegistry->onDisconnectUser.connect(bind(&UserRegistryTest::handleDisconnectUser, this, _1)); + + server = new Swift::Server(loop, factories, userRegistry, "localhost", 5222); + server->start(); + connectionServer = server->getConnectionServer(); + + client1 = factories->getConnectionFactory()->createConnection(); + dynamic_cast(connectionServer.get())->acceptConnection(client1); + + dynamic_cast(client1.get())->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client1)); + + client2 = factories->getConnectionFactory()->createConnection(); + dynamic_cast(connectionServer.get())->acceptConnection(client2); + + dynamic_cast(client2.get())->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client2)); + + loop->processEvents(); } void tearDown (void) { -// delete userRegistry; + delete server; + dynamic_cast(client1.get())->onDataSent.disconnect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client1)); + client1.reset(); + dynamic_cast(client2.get())->onDataSent.disconnect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client2)); + client2.reset(); + connectionServer.reset(); + delete userRegistry; + delete factories; + delete loop; delete cfg; + received1.clear(); + received2.clear(); } + void send(boost::shared_ptr conn, const std::string &data) { + dynamic_cast(conn.get())->receive(Swift::createSafeByteArray(data)); + loop->processEvents(); + } + + void sendCredentials(boost::shared_ptr conn, const std::string &username, const std::string &password, const std::string &b64) { + std::vector &received = conn == client1 ? received1 : received2; + send(conn, ""); + CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); + CPPUNIT_ASSERT(received[0].find("") == 0); + CPPUNIT_ASSERT(received[1].find("PLAIN") != std::string::npos); + received.clear(); + + // username:test + send(conn, "" + b64 + ""); + if (conn == client1) + CPPUNIT_ASSERT_EQUAL(Connecting, state1); +// else +// CPPUNIT_ASSERT_EQUAL(Connecting, state2); + CPPUNIT_ASSERT_EQUAL(password, userRegistry->getUserPassword(username)); + CPPUNIT_ASSERT_EQUAL(std::string(""), userRegistry->getUserPassword("unknown@localhost")); + } + + void handleDataReceived(const Swift::SafeByteArray &data, boost::shared_ptr conn) { + if (conn == client1) { + received1.push_back(safeByteArrayToString(data)); +// std::cout << received1.back() << "\n"; + } + else { + received2.push_back(safeByteArrayToString(data)); +// std::cout << received2.back() << "\n"; + } + } + + void handleConnectUser(const Swift::JID &user) { + state1 = Connecting; + } + + void handleDisconnectUser(const Swift::JID &user) { + state1 = Disconnected; + } + + void login() { + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + + userRegistry->onPasswordValid("username@localhost"); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(std::string(""), userRegistry->getUserPassword("username@localhost")); + CPPUNIT_ASSERT_EQUAL(1, (int) received1.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[0]); + + // TODO: resource binding +// AHVzZXJuYW1lMgB0ZXN0 username2:test + } + + void loginInvalidPassword() { + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + + userRegistry->onPasswordInvalid("username@localhost"); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(std::string(""), userRegistry->getUserPassword("username@localhost")); + CPPUNIT_ASSERT_EQUAL(2, (int) received1.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[0]); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[1]); + } + + void loginTwoClientsValidPasswords() { + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + sendCredentials(client2, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + CPPUNIT_ASSERT_EQUAL(2, (int) received1.size()); + CPPUNIT_ASSERT_EQUAL(0, (int) received2.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[0]); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[1]); + + userRegistry->onPasswordValid("username@localhost"); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(std::string(""), userRegistry->getUserPassword("username@localhost")); + CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received2[0]); + } + + void loginTwoClientsDifferentPasswords() { + // first is valid, second invalid. + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + sendCredentials(client2, "username@localhost", "test2", "AHVzZXJuYW1lAHRlc3Qy"); + CPPUNIT_ASSERT_EQUAL(2, (int) received1.size()); + CPPUNIT_ASSERT_EQUAL(0, (int) received2.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[0]); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[1]); + userRegistry->onPasswordValid("username@localhost"); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(std::string(""), userRegistry->getUserPassword("username@localhost")); + CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received2[0]); + } + + void loginDisconnect() { + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + + client1->onDisconnected(boost::optional()); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(Disconnected, state1); + } + + void removeLater() { + sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q="); + + userRegistry->removeLater("username@localhost"); + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(0, (int) received1.size()); + + dynamic_cast(factories->getTimerFactory())->setTime(10); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(2, (int) received1.size()); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[0]); + CPPUNIT_ASSERT_EQUAL(std::string(""), received1[1]); + } + + + private: + typedef enum { + Init, + Connecting, + Disconnected, + } State; + UserRegistry *userRegistry; Config *cfg; + Swift::Server *server; + Swift::DummyNetworkFactories *factories; + Swift::DummyEventLoop *loop; + boost::shared_ptr connectionServer; + boost::shared_ptr client1; + boost::shared_ptr client2; + std::vector received1; + std::vector received2; + State state1; + State state2; };