diff options
author | Ben Deutsch <ben@bendeutsch.de> | 2018-08-05 13:13:38 +0200 |
---|---|---|
committer | Loïc Blot <nerzhul@users.noreply.github.com> | 2018-08-05 13:13:38 +0200 |
commit | 153fb211ac2342907eb766a79c1f41824f981ab5 (patch) | |
tree | 58a927bbf9a7d3d3811df6a703de02362b6474fb /src/unittest | |
parent | 18368824958139f1428d534082852d778982b4c9 (diff) | |
download | minetest-153fb211ac2342907eb766a79c1f41824f981ab5.tar.gz minetest-153fb211ac2342907eb766a79c1f41824f981ab5.tar.bz2 minetest-153fb211ac2342907eb766a79c1f41824f981ab5.zip |
Replace auth.txt with SQLite auth database (#7279)
* Replace auth.txt with SQLite auth database
Diffstat (limited to 'src/unittest')
-rw-r--r-- | src/unittest/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/unittest/test_authdatabase.cpp | 299 | ||||
-rw-r--r-- | src/unittest/test_utilities.cpp | 23 |
3 files changed, 323 insertions, 0 deletions
diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt index 311204e32..3ffe1978e 100644 --- a/src/unittest/CMakeLists.txt +++ b/src/unittest/CMakeLists.txt @@ -1,5 +1,6 @@ set (UNITTEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_authdatabase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_activeobject.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_areastore.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_ban.cpp 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")); +} diff --git a/src/unittest/test_utilities.cpp b/src/unittest/test_utilities.cpp index 315cbf0fc..6f4a01432 100644 --- a/src/unittest/test_utilities.cpp +++ b/src/unittest/test_utilities.cpp @@ -51,6 +51,7 @@ public: void testIsNumber(); void testIsPowerOfTwo(); void testMyround(); + void testStringJoin(); }; static TestUtilities g_test_instance; @@ -78,6 +79,7 @@ void TestUtilities::runTests(IGameDef *gamedef) TEST(testIsNumber); TEST(testIsPowerOfTwo); TEST(testMyround); + TEST(testStringJoin); } //////////////////////////////////////////////////////////////////////////////// @@ -328,3 +330,24 @@ void TestUtilities::testMyround() UASSERT(myround(-6.5f) == -7); } +void TestUtilities::testStringJoin() +{ + std::vector<std::string> input; + UASSERT(str_join(input, ",") == ""); + + input.emplace_back("one"); + UASSERT(str_join(input, ",") == "one"); + + input.emplace_back("two"); + UASSERT(str_join(input, ",") == "one,two"); + + input.emplace_back("three"); + UASSERT(str_join(input, ",") == "one,two,three"); + + input[1] = ""; + UASSERT(str_join(input, ",") == "one,,three"); + + input[1] = "two"; + UASSERT(str_join(input, " and ") == "one and two and three"); +} + |