test_authdatabase.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. Minetest
  3. Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "test.h"
  17. #include <algorithm>
  18. #include "database/database-files.h"
  19. #include "database/database-sqlite3.h"
  20. #include "util/string.h"
  21. #include "filesys.h"
  22. namespace
  23. {
  24. // Anonymous namespace to create classes that are only
  25. // visible to this file
  26. //
  27. // These are helpers that return a *AuthDatabase and
  28. // allow us to run the same tests on different databases and
  29. // database acquisition strategies.
  30. class AuthDatabaseProvider
  31. {
  32. public:
  33. virtual ~AuthDatabaseProvider() = default;
  34. virtual AuthDatabase *getAuthDatabase() = 0;
  35. };
  36. class FixedProvider : public AuthDatabaseProvider
  37. {
  38. public:
  39. FixedProvider(AuthDatabase *auth_db) : auth_db(auth_db){};
  40. virtual ~FixedProvider(){};
  41. virtual AuthDatabase *getAuthDatabase() { return auth_db; };
  42. private:
  43. AuthDatabase *auth_db;
  44. };
  45. class FilesProvider : public AuthDatabaseProvider
  46. {
  47. public:
  48. FilesProvider(const std::string &dir) : dir(dir){};
  49. virtual ~FilesProvider() { delete auth_db; };
  50. virtual AuthDatabase *getAuthDatabase()
  51. {
  52. delete auth_db;
  53. auth_db = new AuthDatabaseFiles(dir);
  54. return auth_db;
  55. };
  56. private:
  57. std::string dir;
  58. AuthDatabase *auth_db = nullptr;
  59. };
  60. class SQLite3Provider : public AuthDatabaseProvider
  61. {
  62. public:
  63. SQLite3Provider(const std::string &dir) : dir(dir){};
  64. virtual ~SQLite3Provider() { delete auth_db; };
  65. virtual AuthDatabase *getAuthDatabase()
  66. {
  67. delete auth_db;
  68. auth_db = new AuthDatabaseSQLite3(dir);
  69. return auth_db;
  70. };
  71. private:
  72. std::string dir;
  73. AuthDatabase *auth_db = nullptr;
  74. };
  75. }
  76. class TestAuthDatabase : public TestBase
  77. {
  78. public:
  79. TestAuthDatabase() { TestManager::registerTestModule(this); }
  80. const char *getName() { return "TestAuthDatabase"; }
  81. void runTests(IGameDef *gamedef);
  82. void runTestsForCurrentDB();
  83. void testRecallFail();
  84. void testCreate();
  85. void testRecall();
  86. void testChange();
  87. void testRecallChanged();
  88. void testChangePrivileges();
  89. void testRecallChangedPrivileges();
  90. void testListNames();
  91. void testDelete();
  92. private:
  93. AuthDatabaseProvider *auth_provider;
  94. };
  95. static TestAuthDatabase g_test_instance;
  96. void TestAuthDatabase::runTests(IGameDef *gamedef)
  97. {
  98. // fixed directory, for persistence
  99. thread_local const std::string test_dir = getTestTempDirectory();
  100. // Each set of tests is run twice for each database type:
  101. // one where we reuse the same AuthDatabase object (to test local caching),
  102. // and one where we create a new AuthDatabase object for each call
  103. // (to test actual persistence).
  104. rawstream << "-------- Files database (same object)" << std::endl;
  105. AuthDatabase *auth_db = new AuthDatabaseFiles(test_dir);
  106. auth_provider = new FixedProvider(auth_db);
  107. runTestsForCurrentDB();
  108. delete auth_db;
  109. delete auth_provider;
  110. // reset database
  111. fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.txt");
  112. rawstream << "-------- Files database (new objects)" << std::endl;
  113. auth_provider = new FilesProvider(test_dir);
  114. runTestsForCurrentDB();
  115. delete auth_provider;
  116. rawstream << "-------- SQLite3 database (same object)" << std::endl;
  117. auth_db = new AuthDatabaseSQLite3(test_dir);
  118. auth_provider = new FixedProvider(auth_db);
  119. runTestsForCurrentDB();
  120. delete auth_db;
  121. delete auth_provider;
  122. // reset database
  123. fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "auth.sqlite");
  124. rawstream << "-------- SQLite3 database (new objects)" << std::endl;
  125. auth_provider = new SQLite3Provider(test_dir);
  126. runTestsForCurrentDB();
  127. delete auth_provider;
  128. }
  129. ////////////////////////////////////////////////////////////////////////////////
  130. void TestAuthDatabase::runTestsForCurrentDB()
  131. {
  132. TEST(testRecallFail);
  133. TEST(testCreate);
  134. TEST(testRecall);
  135. TEST(testChange);
  136. TEST(testRecallChanged);
  137. TEST(testChangePrivileges);
  138. TEST(testRecallChangedPrivileges);
  139. TEST(testListNames);
  140. TEST(testDelete);
  141. TEST(testRecallFail);
  142. }
  143. void TestAuthDatabase::testRecallFail()
  144. {
  145. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  146. AuthEntry authEntry;
  147. // no such user yet
  148. UASSERT(!auth_db->getAuth("TestName", authEntry));
  149. }
  150. void TestAuthDatabase::testCreate()
  151. {
  152. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  153. AuthEntry authEntry;
  154. authEntry.name = "TestName";
  155. authEntry.password = "TestPassword";
  156. authEntry.privileges.emplace_back("shout");
  157. authEntry.privileges.emplace_back("interact");
  158. authEntry.last_login = 1000;
  159. UASSERT(auth_db->createAuth(authEntry));
  160. }
  161. void TestAuthDatabase::testRecall()
  162. {
  163. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  164. AuthEntry authEntry;
  165. UASSERT(auth_db->getAuth("TestName", authEntry));
  166. UASSERTEQ(std::string, authEntry.name, "TestName");
  167. UASSERTEQ(std::string, authEntry.password, "TestPassword");
  168. // the order of privileges is unimportant
  169. std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
  170. UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
  171. }
  172. void TestAuthDatabase::testChange()
  173. {
  174. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  175. AuthEntry authEntry;
  176. UASSERT(auth_db->getAuth("TestName", authEntry));
  177. authEntry.password = "NewPassword";
  178. authEntry.last_login = 1002;
  179. UASSERT(auth_db->saveAuth(authEntry));
  180. }
  181. void TestAuthDatabase::testRecallChanged()
  182. {
  183. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  184. AuthEntry authEntry;
  185. UASSERT(auth_db->getAuth("TestName", authEntry));
  186. UASSERTEQ(std::string, authEntry.password, "NewPassword");
  187. // the order of privileges is unimportant
  188. std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
  189. UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "interact,shout");
  190. UASSERTEQ(u64, authEntry.last_login, 1002);
  191. }
  192. void TestAuthDatabase::testChangePrivileges()
  193. {
  194. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  195. AuthEntry authEntry;
  196. UASSERT(auth_db->getAuth("TestName", authEntry));
  197. authEntry.privileges.clear();
  198. authEntry.privileges.emplace_back("interact");
  199. authEntry.privileges.emplace_back("fly");
  200. authEntry.privileges.emplace_back("dig");
  201. UASSERT(auth_db->saveAuth(authEntry));
  202. }
  203. void TestAuthDatabase::testRecallChangedPrivileges()
  204. {
  205. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  206. AuthEntry authEntry;
  207. UASSERT(auth_db->getAuth("TestName", authEntry));
  208. // the order of privileges is unimportant
  209. std::sort(authEntry.privileges.begin(), authEntry.privileges.end());
  210. UASSERTEQ(std::string, str_join(authEntry.privileges, ","), "dig,fly,interact");
  211. }
  212. void TestAuthDatabase::testListNames()
  213. {
  214. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  215. std::vector<std::string> list;
  216. AuthEntry authEntry;
  217. authEntry.name = "SecondName";
  218. authEntry.password = "SecondPassword";
  219. authEntry.privileges.emplace_back("shout");
  220. authEntry.privileges.emplace_back("interact");
  221. authEntry.last_login = 1003;
  222. auth_db->createAuth(authEntry);
  223. auth_db->listNames(list);
  224. // not necessarily sorted, so sort before comparing
  225. std::sort(list.begin(), list.end());
  226. UASSERTEQ(std::string, str_join(list, ","), "SecondName,TestName");
  227. }
  228. void TestAuthDatabase::testDelete()
  229. {
  230. AuthDatabase *auth_db = auth_provider->getAuthDatabase();
  231. UASSERT(!auth_db->deleteAuth("NoSuchName"));
  232. UASSERT(auth_db->deleteAuth("TestName"));
  233. // second try, expect failure
  234. UASSERT(!auth_db->deleteAuth("TestName"));
  235. }