#include #include #include #include #include #include #include #include #include "basictest.h" using namespace Transport; class UserRegistryTest : public CPPUNIT_NS :: TestFixture { 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); 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", "0.0.0.0", 5222); server->start(); connectionServer = server->getConnectionServer(); client1 = factories->getConnectionFactory()->createConnection(); SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(connectionServer)->acceptConnection(client1); SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(client1)->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client1)); client2 = factories->getConnectionFactory()->createConnection(); SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(connectionServer)->acceptConnection(client2); SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(client2)->onDataSent.connect(boost::bind(&UserRegistryTest::handleDataReceived, this, _1, client2)); loop->processEvents(); } void tearDown (void) { delete server; SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(client1)->onDataSent.disconnect_all_slots(); client1.reset(); SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(client2)->onDataSent.disconnect_all_slots(); client2.reset(); connectionServer.reset(); delete userRegistry; delete factories; delete loop; delete cfg; received1.clear(); received2.clear(); } void send(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr conn, const std::string &data) { SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast(conn)->receive(Swift::createSafeByteArray(data)); loop->processEvents(); } void sendCredentials(SWIFTEN_SHRPTR_NAMESPACE::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 bindSession(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr conn) { 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("urn:ietf:params:xml:ns:xmpp-bind") != std::string::npos); CPPUNIT_ASSERT(received[1].find("urn:ietf:params:xml:ns:xmpp-session") != std::string::npos); } void handleDataReceived(const Swift::SafeByteArray &data, SWIFTEN_SHRPTR_NAMESPACE::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]); received1.clear(); bindSession(client1); } 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; SWIFTEN_SHRPTR_NAMESPACE::shared_ptr connectionServer; SWIFTEN_SHRPTR_NAMESPACE::shared_ptr client1; SWIFTEN_SHRPTR_NAMESPACE::shared_ptr client2; std::vector received1; std::vector received2; State state1; State state2; }; CPPUNIT_TEST_SUITE_REGISTRATION (UserRegistryTest);