aboutsummaryrefslogtreecommitdiff
path: root/src/unittest
diff options
context:
space:
mode:
authorBen Deutsch <ben@bendeutsch.de>2018-08-05 13:13:38 +0200
committerLoïc Blot <nerzhul@users.noreply.github.com>2018-08-05 13:13:38 +0200
commit153fb211ac2342907eb766a79c1f41824f981ab5 (patch)
tree58a927bbf9a7d3d3811df6a703de02362b6474fb /src/unittest
parent18368824958139f1428d534082852d778982b4c9 (diff)
downloadminetest-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.txt1
-rw-r--r--src/unittest/test_authdatabase.cpp299
-rw-r--r--src/unittest/test_utilities.cpp23
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");
+}
+