diff options
Diffstat (limited to 'src/unittest/test_authdatabase.cpp')
-rw-r--r-- | src/unittest/test_authdatabase.cpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/src/unittest/test_authdatabase.cpp b/src/unittest/test_authdatabase.cpp new file mode 100644 index 000000000..1e8fd233d --- /dev/null +++ b/src/unittest/test_authdatabase.cpp @@ -0,0 +1,299 @@ +/* +Minetest +Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "test.h" + +#include <algorithm> +#include "database/database-files.h" +#include "database/database-sqlite3.h" +#include "util/string.h" +#include "filesys.h" + +namespace +{ +// Anonymous namespace to create classes that are only +// visible to this file +// +// These are helpers that return a *AuthDatabase and +// allow us to run the same tests on different databases and +// database acquisition strategies. + +class AuthDatabaseProvider +{ +public: + virtual ~AuthDatabaseProvider() = default; + virtual AuthDatabase *getAuthDatabase() = 0; +}; + +class FixedProvider : public AuthDatabaseProvider +{ +public: + FixedProvider(AuthDatabase *auth_db) : auth_db(auth_db){}; + virtual ~FixedProvider(){}; + virtual AuthDatabase *getAuthDatabase() { return auth_db; }; + +private: + AuthDatabase *auth_db; +}; + +class FilesProvider : public AuthDatabaseProvider +{ +public: + FilesProvider(const std::string &dir) : dir(dir){}; + virtual ~FilesProvider() { delete auth_db; }; + virtual AuthDatabase *getAuthDatabase() + { + delete auth_db; + auth_db = new AuthDatabaseFiles(dir); + return auth_db; + }; + +private: + std::string dir; + AuthDatabase *auth_db = nullptr; +}; + +class SQLite3Provider : public AuthDatabaseProvider +{ +public: + SQLite3Provider(const std::string &dir) : dir(dir){}; + virtual ~SQLite3Provider() { delete auth_db; }; + virtual AuthDatabase *getAuthDatabase() + { + delete auth_db; + auth_db = new AuthDatabaseSQLite3(dir); + return auth_db; + }; + +private: + std::string dir; + AuthDatabase *auth_db = nullptr; +}; +} + +class TestAuthDatabase : public TestBase +{ +public: + TestAuthDatabase() + { + TestManager::registerTestModule(this); + // fixed directory, for persistence + test_dir = getTestTempDirectory(); + } + const char *getName() { return "TestAuthDatabase"; } + + void runTests(IGameDef *gamedef); + void runTestsForCurrentDB(); + + void testRecallFail(); + void testCreate(); + void testRecall(); + void testChange(); + void testRecallChanged(); + void testChangePrivileges(); + void testRecallChangedPrivileges(); + void testListNames(); + void testDelete(); + +private: + std::string test_dir; + AuthDatabaseProvider *auth_provider; +}; + +static TestAuthDatabase g_test_instance; + +void TestAuthDatabase::runTests(IGameDef *gamedef) +{ + // Each set of tests is run twice for each database type: + // one where we reuse the same AuthDatabase object (to test local caching), + // and one where we create a new AuthDatabase object for each call + // (to test actual persistence). + + rawstream << "-------- Files database (same object)" << std::endl; + + AuthDatabase *auth_db = new AuthDatabaseFiles(test_dir); + auth_provider = new FixedProvider(auth_db); + + runTestsForCurrentDB(); + + delete auth_db; + delete auth_provider; + + // reset database + fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.txt"); + + rawstream << "-------- Files database (new objects)" << std::endl; + + auth_provider = new FilesProvider(test_dir); + + runTestsForCurrentDB(); + + delete auth_provider; + + rawstream << "-------- SQLite3 database (same object)" << std::endl; + + auth_db = new AuthDatabaseSQLite3(test_dir); + auth_provider = new FixedProvider(auth_db); + + runTestsForCurrentDB(); + + delete auth_db; + delete auth_provider; + + // reset database + fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.sqlite"); + + rawstream << "-------- SQLite3 database (new objects)" << std::endl; + + auth_provider = new SQLite3Provider(test_dir); + + runTestsForCurrentDB(); + + delete auth_provider; +} + +//////////////////////////////////////////////////////////////////////////////// + +void TestAuthDatabase::runTestsForCurrentDB() +{ + TEST(testRecallFail); + TEST(testCreate); + TEST(testRecall); + TEST(testChange); + TEST(testRecallChanged); + TEST(testChangePrivileges); + TEST(testRecallChangedPrivileges); + TEST(testListNames); + TEST(testDelete); + TEST(testRecallFail); +} + +void TestAuthDatabase::testRecallFail() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + // no such user yet + UASSERT(!auth_db->getAuth("TestName", authEntry)); +} + +void TestAuthDatabase::testCreate() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + authEntry.name = "TestName"; + authEntry.password = "TestPassword"; + authEntry.privileges.emplace_back("shout"); + authEntry.privileges.emplace_back("interact"); + authEntry.last_login = 1000; + UASSERT(auth_db->createAuth(authEntry)); +} + +void TestAuthDatabase::testRecall() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + UASSERT(auth_db->getAuth("TestName", authEntry)); + UASSERTEQ(std::string, authEntry.name, "TestName"); + UASSERTEQ(std::string, authEntry.password, "TestPassword"); + // the order of privileges is unimportant + std::sort(authEntry.privileges.begin(), authEntry.privileges.end()); + UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout"); +} + +void TestAuthDatabase::testChange() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + UASSERT(auth_db->getAuth("TestName", authEntry)); + authEntry.password = "NewPassword"; + authEntry.last_login = 1002; + UASSERT(auth_db->saveAuth(authEntry)); +} + +void TestAuthDatabase::testRecallChanged() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + UASSERT(auth_db->getAuth("TestName", authEntry)); + UASSERTEQ(std::string, authEntry.password, "NewPassword"); + // the order of privileges is unimportant + std::sort(authEntry.privileges.begin(), authEntry.privileges.end()); + UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout"); + UASSERTEQ(u64, authEntry.last_login, 1002); +} + +void TestAuthDatabase::testChangePrivileges() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + UASSERT(auth_db->getAuth("TestName", authEntry)); + authEntry.privileges.clear(); + authEntry.privileges.emplace_back("interact"); + authEntry.privileges.emplace_back("fly"); + authEntry.privileges.emplace_back("dig"); + UASSERT(auth_db->saveAuth(authEntry)); +} + +void TestAuthDatabase::testRecallChangedPrivileges() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + AuthEntry authEntry; + + UASSERT(auth_db->getAuth("TestName", authEntry)); + // the order of privileges is unimportant + std::sort(authEntry.privileges.begin(), authEntry.privileges.end()); + UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "dig,fly,interact"); +} + +void TestAuthDatabase::testListNames() +{ + + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + std::vector<std::string> list; + + AuthEntry authEntry; + + authEntry.name = "SecondName"; + authEntry.password = "SecondPassword"; + authEntry.privileges.emplace_back("shout"); + authEntry.privileges.emplace_back("interact"); + authEntry.last_login = 1003; + auth_db->createAuth(authEntry); + + auth_db->listNames(list); + // not necessarily sorted, so sort before comparing + std::sort(list.begin(), list.end()); + UASSERTEQ(std::string, str_join(list, ","), "SecondName,TestName"); +} + +void TestAuthDatabase::testDelete() +{ + AuthDatabase *auth_db = auth_provider->getAuthDatabase(); + + UASSERT(!auth_db->deleteAuth("NoSuchName")); + UASSERT(auth_db->deleteAuth("TestName")); + // second try, expect failure + UASSERT(!auth_db->deleteAuth("TestName")); +} |