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
95 TestManager::registerTestModule(this);
96 // fixed directory, for persistence
97 test_dir = getTestTempDirectory();
99 const char *getName() { return "TestAuthDatabase"; }
101 void runTests(IGameDef *gamedef);
102 void runTestsForCurrentDB();
104 void testRecallFail();
108 void testRecallChanged();
109 void testChangePrivileges();
110 void testRecallChangedPrivileges();
111 void testListNames();
115 std::string test_dir;
116 AuthDatabaseProvider *auth_provider;
119 static TestAuthDatabase g_test_instance;
121 void TestAuthDatabase::runTests(IGameDef *gamedef)
123 // Each set of tests is run twice for each database type:
124 // one where we reuse the same AuthDatabase object (to test local caching),
125 // and one where we create a new AuthDatabase object for each call
126 // (to test actual persistence).
128 rawstream << "-------- Files database (same object)" << std::endl;
130 AuthDatabase *auth_db = new AuthDatabaseFiles(test_dir);
131 auth_provider = new FixedProvider(auth_db);
133 runTestsForCurrentDB();
136 delete auth_provider;
139 fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.txt");
141 rawstream << "-------- Files database (new objects)" << std::endl;
143 auth_provider = new FilesProvider(test_dir);
145 runTestsForCurrentDB();
147 delete auth_provider;
149 rawstream << "-------- SQLite3 database (same object)" << std::endl;
151 auth_db = new AuthDatabaseSQLite3(test_dir);
152 auth_provider = new FixedProvider(auth_db);
154 runTestsForCurrentDB();
157 delete auth_provider;
160 fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.sqlite");
162 rawstream << "-------- SQLite3 database (new objects)" << std::endl;
164 auth_provider = new SQLite3Provider(test_dir);
166 runTestsForCurrentDB();
168 delete auth_provider;
171 ////////////////////////////////////////////////////////////////////////////////
173 void TestAuthDatabase::runTestsForCurrentDB()
175 TEST(testRecallFail);
179 TEST(testRecallChanged);
180 TEST(testChangePrivileges);
181 TEST(testRecallChangedPrivileges);
184 TEST(testRecallFail);
187 void TestAuthDatabase::testRecallFail()
189 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
193 UASSERT(!auth_db->getAuth("TestName", authEntry));
196 void TestAuthDatabase::testCreate()
198 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
201 authEntry.name = "TestName";
202 authEntry.password = "TestPassword";
203 authEntry.privileges.emplace_back("shout");
204 authEntry.privileges.emplace_back("interact");
205 authEntry.last_login = 1000;
206 UASSERT(auth_db->createAuth(authEntry));
209 void TestAuthDatabase::testRecall()
211 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
214 UASSERT(auth_db->getAuth("TestName", authEntry));
215 UASSERTEQ(std::string, authEntry.name, "TestName");
216 UASSERTEQ(std::string, authEntry.password, "TestPassword");
217 // the order of privileges is unimportant
218 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
219 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
222 void TestAuthDatabase::testChange()
224 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
227 UASSERT(auth_db->getAuth("TestName", authEntry));
228 authEntry.password = "NewPassword";
229 authEntry.last_login = 1002;
230 UASSERT(auth_db->saveAuth(authEntry));
233 void TestAuthDatabase::testRecallChanged()
235 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
238 UASSERT(auth_db->getAuth("TestName", authEntry));
239 UASSERTEQ(std::string, authEntry.password, "NewPassword");
240 // the order of privileges is unimportant
241 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
242 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
243 UASSERTEQ(u64, authEntry.last_login, 1002);
246 void TestAuthDatabase::testChangePrivileges()
248 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
251 UASSERT(auth_db->getAuth("TestName", authEntry));
252 authEntry.privileges.clear();
253 authEntry.privileges.emplace_back("interact");
254 authEntry.privileges.emplace_back("fly");
255 authEntry.privileges.emplace_back("dig");
256 UASSERT(auth_db->saveAuth(authEntry));
259 void TestAuthDatabase::testRecallChangedPrivileges()
261 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
264 UASSERT(auth_db->getAuth("TestName", authEntry));
265 // the order of privileges is unimportant
266 std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
267 UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "dig,fly,interact");
270 void TestAuthDatabase::testListNames()
273 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
274 std::vector<std::string> list;
278 authEntry.name = "SecondName";
279 authEntry.password = "SecondPassword";
280 authEntry.privileges.emplace_back("shout");
281 authEntry.privileges.emplace_back("interact");
282 authEntry.last_login = 1003;
283 auth_db->createAuth(authEntry);
285 auth_db->listNames(list);
286 // not necessarily sorted, so sort before comparing
287 std::sort(list.begin(), list.end());
288 UASSERTEQ(std::string, str_join(list, ","), "SecondName,TestName");
291 void TestAuthDatabase::testDelete()
293 AuthDatabase *auth_db = auth_provider->getAuthDatabase();
295 UASSERT(!auth_db->deleteAuth("NoSuchName"));
296 UASSERT(auth_db->deleteAuth("TestName"));
297 // second try, expect failure
298 UASSERT(!auth_db->deleteAuth("TestName"));