3 Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "database/database-files.h"
24 #include "database/database-sqlite3.h"
25 #include "util/string.h"
30 // Anonymous namespace to create classes that are only
31 // visible to this file
33 // These are helpers that return a *AuthDatabase and
34 // allow us to run the same tests on different databases and
35 // database acquisition strategies.
37 class AuthDatabaseProvider
40 virtual ~AuthDatabaseProvider() = default;
41 virtual AuthDatabase *getAuthDatabase() = 0;
44 class FixedProvider : public AuthDatabaseProvider
47 FixedProvider(AuthDatabase *auth_db) : auth_db(auth_db){};
48 virtual ~FixedProvider(){};
49 virtual AuthDatabase *getAuthDatabase() { return auth_db; };
52 AuthDatabase *auth_db;
55 class FilesProvider : public AuthDatabaseProvider
58 FilesProvider(const std::string &dir) : dir(dir){};
59 virtual ~FilesProvider() { delete auth_db; };
60 virtual AuthDatabase *getAuthDatabase()
63 auth_db = new AuthDatabaseFiles(dir);
69 AuthDatabase *auth_db = nullptr;
72 class SQLite3Provider : public AuthDatabaseProvider
75 SQLite3Provider(const std::string &dir) : dir(dir){};
76 virtual ~SQLite3Provider() { delete auth_db; };
77 virtual AuthDatabase *getAuthDatabase()
80 auth_db = new AuthDatabaseSQLite3(dir);
86 AuthDatabase *auth_db = nullptr;
90 class TestAuthDatabase : public TestBase
93 TestAuthDatabase() { TestManager::registerTestModule(this); }
94 const char *getName() { return "TestAuthDatabase"; }
96 void runTests(IGameDef *gamedef);
97 void runTestsForCurrentDB();
99 void testRecallFail();
103 void testRecallChanged();
104 void testChangePrivileges();
105 void testRecallChangedPrivileges();
106 void testListNames();
110 AuthDatabaseProvider *auth_provider;
113 static TestAuthDatabase g_test_instance;
115 void TestAuthDatabase::runTests(IGameDef *gamedef)
117 // fixed directory, for persistence
118 thread_local const std::string test_dir = getTestTempDirectory();
120 // Each set of tests is run twice for each database type:
121 // one where we reuse the same AuthDatabase object (to test local caching),
122 // and one where we create a new AuthDatabase object for each call
123 // (to test actual persistence).
125 rawstream << "-------- Files database (same object)" << std::endl;
127 AuthDatabase *auth_db = new AuthDatabaseFiles(test_dir);
128 auth_provider = new FixedProvider(auth_db);
130 runTestsForCurrentDB();
133 delete auth_provider;
136 fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.txt");
138 rawstream << "-------- Files database (new objects)" << std::endl;
140 auth_provider = new FilesProvider(test_dir);
142 runTestsForCurrentDB();
144 delete auth_provider;
146 rawstream << "-------- SQLite3 database (same object)" << std::endl;
148 auth_db = new AuthDatabaseSQLite3(test_dir);
149 auth_provider = new FixedProvider(auth_db);
151 runTestsForCurrentDB();
154 delete auth_provider;
157 fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.sqlite");
159 rawstream << "-------- SQLite3 database (new objects)" << std::endl;
161 auth_provider = new SQLite3Provider(test_dir);
163 runTestsForCurrentDB();
165 delete auth_provider;
168 ////////////////////////////////////////////////////////////////////////////////
170 void TestAuthDatabase::runTestsForCurrentDB()
172 TEST(testRecallFail);
176 TEST(testRecallChanged);
177 TEST(testChangePrivileges);
178 TEST(testRecallChangedPrivileges);
181 TEST(testRecallFail);
184 void TestAuthDatabase::testRecallFail()
186 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
190 UASSERT(!auth_db->getAuth("TestName", authEntry));
193 void TestAuthDatabase::testCreate()
195 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
198 authEntry.name = "TestName";
199 authEntry.password = "TestPassword";
200 authEntry.privileges.emplace_back("shout");
201 authEntry.privileges.emplace_back("interact");
202 authEntry.last_login = 1000;
203 UASSERT(auth_db->createAuth(authEntry));
206 void TestAuthDatabase::testRecall()
208 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
211 UASSERT(auth_db->getAuth("TestName", authEntry));
212 UASSERTEQ(std::string, authEntry.name, "TestName");
213 UASSERTEQ(std::string, authEntry.password, "TestPassword");
214 // the order of privileges is unimportant
215 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
216 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
219 void TestAuthDatabase::testChange()
221 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
224 UASSERT(auth_db->getAuth("TestName", authEntry));
225 authEntry.password = "NewPassword";
226 authEntry.last_login = 1002;
227 UASSERT(auth_db->saveAuth(authEntry));
230 void TestAuthDatabase::testRecallChanged()
232 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
235 UASSERT(auth_db->getAuth("TestName", authEntry));
236 UASSERTEQ(std::string, authEntry.password, "NewPassword");
237 // the order of privileges is unimportant
238 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
239 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
240 UASSERTEQ(u64, authEntry.last_login, 1002);
243 void TestAuthDatabase::testChangePrivileges()
245 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
248 UASSERT(auth_db->getAuth("TestName", authEntry));
249 authEntry.privileges.clear();
250 authEntry.privileges.emplace_back("interact");
251 authEntry.privileges.emplace_back("fly");
252 authEntry.privileges.emplace_back("dig");
253 UASSERT(auth_db->saveAuth(authEntry));
256 void TestAuthDatabase::testRecallChangedPrivileges()
258 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
261 UASSERT(auth_db->getAuth("TestName", authEntry));
262 // the order of privileges is unimportant
263 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
264 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "dig,fly,interact");
267 void TestAuthDatabase::testListNames()
270 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
271 std::vector<std::string> list;
275 authEntry.name = "SecondName";
276 authEntry.password = "SecondPassword";
277 authEntry.privileges.emplace_back("shout");
278 authEntry.privileges.emplace_back("interact");
279 authEntry.last_login = 1003;
280 auth_db->createAuth(authEntry);
282 auth_db->listNames(list);
283 // not necessarily sorted, so sort before comparing
284 std::sort(list.begin(), list.end());
285 UASSERTEQ(std::string, str_join(list, ","), "SecondName,TestName");
288 void TestAuthDatabase::testDelete()
290 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
292 UASSERT(!auth_db->deleteAuth("NoSuchName"));
293 UASSERT(auth_db->deleteAuth("TestName"));
294 // second try, expect failure
295 UASSERT(!auth_db->deleteAuth("TestName"));