UserRegistry test

This commit is contained in:
Jan Kaluza 2011-08-25 11:24:03 +02:00
parent 6189401158
commit 75bc454c85
12 changed files with 457 additions and 10 deletions

View file

@ -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 <Swiften/Network/DummyConnectionFactory.h>
#include <Swiften/Network/DummyConnection.h>
namespace Swift {
DummyConnectionFactory::DummyConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
}
boost::shared_ptr<Connection> DummyConnectionFactory::createConnection() {
return boost::shared_ptr<Connection>(new DummyConnection(eventLoop));
}
}

View file

@ -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 <boost/asio/io_service.hpp>
#include <Swiften/Network/ConnectionFactory.h>
#include <Swiften/Network/DummyConnection.h>
namespace Swift {
class DummyConnection;
class DummyConnectionFactory : public ConnectionFactory {
public:
DummyConnectionFactory(EventLoop* eventLoop);
virtual boost::shared_ptr<Connection> createConnection();
private:
EventLoop* eventLoop;
};
}

View file

@ -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 <Swiften/Network/DummyConnectionServer.h>
#include <boost/bind.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/placeholders.hpp>
#include <Swiften/EventLoop/EventLoop.h>
namespace Swift {
DummyConnectionServer::DummyConnectionServer(EventLoop* eventLoop) : eventLoop(eventLoop) {
}
void DummyConnectionServer::start() {
}
void DummyConnectionServer::stop() {
}
void DummyConnectionServer::acceptConnection(boost::shared_ptr<Connection> connection) {
eventLoop->postEvent(
boost::bind(boost::ref(onNewConnection), connection),
shared_from_this());
// connection->listen();
}
HostAddressPort DummyConnectionServer::getAddressPort() const {
return HostAddressPort();
}
}

View file

@ -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 <boost/shared_ptr.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Network/DummyConnection.h>
#include <Swiften/Network/ConnectionServer.h>
#include <Swiften/EventLoop/EventOwner.h>
namespace Swift {
class DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<DummyConnectionServer> {
public:
typedef boost::shared_ptr<DummyConnectionServer> ref;
enum Error {
Conflict,
UnknownError
};
static ref create(EventLoop* eventLoop) {
return ref(new DummyConnectionServer(eventLoop));
}
void acceptConnection(boost::shared_ptr<Connection> connection);
virtual void start();
virtual void stop();
virtual HostAddressPort getAddressPort() const;
private:
DummyConnectionServer(EventLoop* eventLoop);
private:
HostAddress address_;
EventLoop* eventLoop;
};
}

View file

@ -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 <Swiften/Network/DummyConnectionServerFactory.h>
#include <Swiften/Network/DummyConnectionServer.h>
namespace Swift {
DummyConnectionServerFactory::DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
}
boost::shared_ptr<ConnectionServer> DummyConnectionServerFactory::createConnectionServer(int port) {
return DummyConnectionServer::create(eventLoop);
}
boost::shared_ptr<ConnectionServer> DummyConnectionServerFactory::createConnectionServer(const Swift::HostAddress &hostAddress, int port) {
return DummyConnectionServer::create(eventLoop);
}
}

View file

@ -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 <boost/asio/io_service.hpp>
#include <Swiften/Network/ConnectionServerFactory.h>
#include <Swiften/Network/DummyConnectionServer.h>
namespace Swift {
class ConnectionServer;
class DummyConnectionServerFactory : public ConnectionServerFactory {
public:
DummyConnectionServerFactory(EventLoop* eventLoop);
virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port);
virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress &hostAddress, int port);
private:
EventLoop* eventLoop;
};
}

View file

@ -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 <Swiften/Network/DummyNetworkFactories.h>
#include <Swiften/Network/DummyTimerFactory.h>
#include <Swiften/Network/DummyConnectionFactory.h>
#include <Swiften/Network/PlatformDomainNameResolver.h>
#include <Swiften/Network/DummyConnectionServerFactory.h>
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;
}
}

View file

@ -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 <Swiften/Network/NetworkFactories.h>
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;
};
}

View file

@ -79,9 +79,9 @@ void Server::stop() {
stopping = true;
foreach(boost::shared_ptr<ServerFromClientSession> session, serverFromClientSessions) {
session->finishSession();
}
// foreach(boost::shared_ptr<ServerFromClientSession> session, serverFromClientSessions) {
// session->finishSession();
// }
serverFromClientSessions.clear();
if (serverFromClientConnectionServer) {
@ -141,7 +141,6 @@ void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession> se
// dynamic_cast<ServerStanzaChannel *>(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(

View file

@ -52,6 +52,10 @@ namespace Swift {
return iqRouter_;
}
boost::shared_ptr<ConnectionServer> getConnectionServer() const {
return serverFromClientConnectionServer;
}
boost::signal<void (const SafeByteArray&)> onDataRead;
boost::signal<void (const SafeByteArray&)> onDataWritten;

View file

@ -5,9 +5,19 @@
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>
#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;

View file

@ -2,31 +2,210 @@
#include "transport/config.h"
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <Swiften/EventLoop/DummyEventLoop.h>
#include <Swiften/Server/Server.h>
#include <Swiften/Network/DummyNetworkFactories.h>
#include <Swiften/Network/DummyConnectionServer.h>
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<Swift::DummyConnectionServer *>(connectionServer.get())->acceptConnection(client1);
dynamic_cast<Swift::DummyConnection *>(client1.get())->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client1));
client2 = factories->getConnectionFactory()->createConnection();
dynamic_cast<Swift::DummyConnectionServer *>(connectionServer.get())->acceptConnection(client2);
dynamic_cast<Swift::DummyConnection *>(client2.get())->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client2));
loop->processEvents();
}
void tearDown (void) {
// delete userRegistry;
delete server;
dynamic_cast<Swift::DummyConnection *>(client1.get())->onDataSent.disconnect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client1));
client1.reset();
dynamic_cast<Swift::DummyConnection *>(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<Swift::Connection> conn, const std::string &data) {
dynamic_cast<Swift::DummyConnection *>(conn.get())->receive(Swift::createSafeByteArray(data));
loop->processEvents();
}
void sendCredentials(boost::shared_ptr<Swift::Connection> conn, const std::string &username, const std::string &password, const std::string &b64) {
std::vector<std::string> &received = conn == client1 ? received1 : received2;
send(conn, "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
CPPUNIT_ASSERT(received[0].find("<?xml version=\"1.0\"?>") == 0);
CPPUNIT_ASSERT(received[1].find("PLAIN") != std::string::npos);
received.clear();
// username:test
send(conn, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" + b64 + "</auth>");
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<Swift::Connection> 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("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"></success>"), 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("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>"), received1[0]);
CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), 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("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>"), received1[0]);
CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), 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("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"></success>"), 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("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>"), received1[0]);
CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), 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("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"></success>"), received2[0]);
}
void loginDisconnect() {
sendCredentials(client1, "username@localhost", "test", "AHVzZXJuYW1lAHRlc3Q=");
client1->onDisconnected(boost::optional<Swift::Connection::Error>());
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<Swift::DummyTimerFactory *>(factories->getTimerFactory())->setTime(10);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(2, (int) received1.size());
CPPUNIT_ASSERT_EQUAL(std::string("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>"), received1[0]);
CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), 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<Swift::ConnectionServer> connectionServer;
boost::shared_ptr<Swift::Connection> client1;
boost::shared_ptr<Swift::Connection> client2;
std::vector<std::string> received1;
std::vector<std::string> received2;
State state1;
State state2;
};