From 7c21347a40ede4427d9a9ba69c768ffb9c41d264 Mon Sep 17 00:00:00 2001 From: Jude Melton-Houghton Date: Wed, 23 Nov 2022 17:25:34 -0500 Subject: [PATCH] Rename "mod metadata" to "mod storage" everywhere --- src/client/client.cpp | 4 +- src/client/client.h | 4 +- src/content/mods.cpp | 14 +- src/content/mods.h | 12 +- src/database/database-dummy.cpp | 32 +- src/database/database-dummy.h | 4 +- src/database/database-files.cpp | 44 +-- src/database/database-files.h | 8 +- src/database/database-postgresql.cpp | 24 +- src/database/database-postgresql.h | 6 +- src/database/database-sqlite3.cpp | 26 +- src/database/database-sqlite3.h | 6 +- src/database/database.h | 4 +- src/dummygamedef.h | 4 +- src/gamedef.h | 6 +- src/script/lua_api/l_storage.cpp | 2 +- src/script/lua_api/l_storage.h | 6 +- src/server.cpp | 14 +- src/server.h | 8 +- src/unittest/CMakeLists.txt | 2 +- src/unittest/test_modmetadatadatabase.cpp | 359 --------------------- src/unittest/test_modstoragedatabase.cpp | 365 ++++++++++++++++++++++ 22 files changed, 480 insertions(+), 474 deletions(-) delete mode 100644 src/unittest/test_modmetadatadatabase.cpp create mode 100644 src/unittest/test_modstoragedatabase.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index 016fb3a8d..04686c43c 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -134,7 +134,7 @@ Client::Client( // Make the mod storage database and begin the save for later m_mod_storage_database = - new ModMetadataDatabaseSQLite3(porting::path_user + DIR_DELIM + "client"); + new ModStorageDatabaseSQLite3(porting::path_user + DIR_DELIM + "client"); m_mod_storage_database->beginSave(); if (g_settings->getBool("enable_minimap")) { @@ -151,7 +151,7 @@ void Client::migrateModStorage() if (fs::IsDir(old_mod_storage)) { infostream << "Migrating client mod storage to SQLite3 database" << std::endl; { - ModMetadataDatabaseFiles files_db(mod_storage_dir); + ModStorageDatabaseFiles files_db(mod_storage_dir); std::vector mod_list; files_db.listMods(&mod_list); for (const std::string &modname : mod_list) { diff --git a/src/client/client.h b/src/client/client.h index 4342a0087..52ca87625 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -381,7 +381,7 @@ public: { return checkPrivilege(priv); } virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false); const std::string* getModFile(std::string filename); - ModMetadataDatabase *getModStorageDatabase() override { return m_mod_storage_database; } + ModStorageDatabase *getModStorageDatabase() override { return m_mod_storage_database; } // Migrates away old files-based mod storage if necessary void migrateModStorage(); @@ -590,7 +590,7 @@ private: // Client modding ClientScripting *m_script = nullptr; - ModMetadataDatabase *m_mod_storage_database = nullptr; + ModStorageDatabase *m_mod_storage_database = nullptr; float m_mod_storage_save_timer = 10.0f; std::vector m_mods; StringMap m_mod_vfs; diff --git a/src/content/mods.cpp b/src/content/mods.cpp index 57ccaaf2e..21c7bcfe2 100644 --- a/src/content/mods.cpp +++ b/src/content/mods.cpp @@ -217,22 +217,22 @@ std::vector flattenMods(const std::map &mods) } -ModMetadata::ModMetadata(const std::string &mod_name, ModMetadataDatabase *database): +ModStorage::ModStorage(const std::string &mod_name, ModStorageDatabase *database): m_mod_name(mod_name), m_database(database) { } -void ModMetadata::clear() +void ModStorage::clear() { m_database->removeModEntries(m_mod_name); } -bool ModMetadata::contains(const std::string &name) const +bool ModStorage::contains(const std::string &name) const { return m_database->hasModEntry(m_mod_name, name); } -bool ModMetadata::setString(const std::string &name, const std::string &var) +bool ModStorage::setString(const std::string &name, const std::string &var) { if (var.empty()) return m_database->removeModEntry(m_mod_name, name); @@ -240,21 +240,21 @@ bool ModMetadata::setString(const std::string &name, const std::string &var) return m_database->setModEntry(m_mod_name, name, var); } -const StringMap &ModMetadata::getStrings(StringMap *place) const +const StringMap &ModStorage::getStrings(StringMap *place) const { place->clear(); m_database->getModEntries(m_mod_name, place); return *place; } -const std::vector &ModMetadata::getKeys(std::vector *place) const +const std::vector &ModStorage::getKeys(std::vector *place) const { place->clear(); m_database->getModKeys(m_mod_name, place); return *place; } -const std::string *ModMetadata::getStringRaw(const std::string &name, std::string *place) const +const std::string *ModStorage::getStringRaw(const std::string &name, std::string *place) const { return m_database->getModEntry(m_mod_name, name, place) ? place : nullptr; } diff --git a/src/content/mods.h b/src/content/mods.h index a45081f57..fb714ca75 100644 --- a/src/content/mods.h +++ b/src/content/mods.h @@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "metadata.h" #include "subgames.h" -class ModMetadataDatabase; +class ModStorageDatabase; #define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_" @@ -110,12 +110,12 @@ std::map getModsInPath(const std::string &path, std::vector flattenMods(const std::map &mods); -class ModMetadata : public IMetadata +class ModStorage : public IMetadata { public: - ModMetadata() = delete; - ModMetadata(const std::string &mod_name, ModMetadataDatabase *database); - ~ModMetadata() = default; + ModStorage() = delete; + ModStorage(const std::string &mod_name, ModStorageDatabase *database); + ~ModStorage() = default; const std::string &getModName() const { return m_mod_name; } @@ -135,5 +135,5 @@ protected: private: std::string m_mod_name; - ModMetadataDatabase *m_database; + ModStorageDatabase *m_database; }; diff --git a/src/database/database-dummy.cpp b/src/database/database-dummy.cpp index a8daaca88..9fa325b93 100644 --- a/src/database/database-dummy.cpp +++ b/src/database/database-dummy.cpp @@ -83,8 +83,8 @@ void Database_Dummy::listPlayers(std::vector &res) bool Database_Dummy::getModEntries(const std::string &modname, StringMap *storage) { - const auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair != m_mod_meta_database.cend()) { + const auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair != m_mod_storage_database.cend()) { for (const auto &pair : mod_pair->second) { (*storage)[pair.first] = pair.second; } @@ -94,8 +94,8 @@ bool Database_Dummy::getModEntries(const std::string &modname, StringMap *storag bool Database_Dummy::getModKeys(const std::string &modname, std::vector *storage) { - const auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair != m_mod_meta_database.cend()) { + const auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair != m_mod_storage_database.cend()) { storage->reserve(storage->size() + mod_pair->second.size()); for (const auto &pair : mod_pair->second) storage->push_back(pair.first); @@ -106,8 +106,8 @@ bool Database_Dummy::getModKeys(const std::string &modname, std::vectorsecond; @@ -121,8 +121,8 @@ bool Database_Dummy::getModEntry(const std::string &modname, bool Database_Dummy::hasModEntry(const std::string &modname, const std::string &key) { - auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair == m_mod_meta_database.end()) + auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair == m_mod_storage_database.end()) return false; const StringMap &meta = mod_pair->second; @@ -132,9 +132,9 @@ bool Database_Dummy::hasModEntry(const std::string &modname, const std::string & bool Database_Dummy::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { - auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair == m_mod_meta_database.end()) { - m_mod_meta_database[modname] = StringMap({{key, value}}); + auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair == m_mod_storage_database.end()) { + m_mod_storage_database[modname] = StringMap({{key, value}}); } else { mod_pair->second[key] = value; } @@ -143,16 +143,16 @@ bool Database_Dummy::setModEntry(const std::string &modname, bool Database_Dummy::removeModEntry(const std::string &modname, const std::string &key) { - auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair != m_mod_meta_database.end()) + auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair != m_mod_storage_database.end()) return mod_pair->second.erase(key) > 0; return false; } bool Database_Dummy::removeModEntries(const std::string &modname) { - auto mod_pair = m_mod_meta_database.find(modname); - if (mod_pair != m_mod_meta_database.end() && !mod_pair->second.empty()) { + auto mod_pair = m_mod_storage_database.find(modname); + if (mod_pair != m_mod_storage_database.end() && !mod_pair->second.empty()) { mod_pair->second.clear(); return true; } @@ -161,7 +161,7 @@ bool Database_Dummy::removeModEntries(const std::string &modname) void Database_Dummy::listMods(std::vector *res) { - for (const auto &pair : m_mod_meta_database) { + for (const auto &pair : m_mod_storage_database) { res->push_back(pair.first); } } diff --git a/src/database/database-dummy.h b/src/database/database-dummy.h index b77911d55..42964b5bc 100644 --- a/src/database/database-dummy.h +++ b/src/database/database-dummy.h @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "database.h" #include "irrlichttypes.h" -class Database_Dummy : public MapDatabase, public PlayerDatabase, public ModMetadataDatabase +class Database_Dummy : public MapDatabase, public PlayerDatabase, public ModStorageDatabase { public: bool saveBlock(const v3s16 &pos, const std::string &data); @@ -54,5 +54,5 @@ public: private: std::map m_database; std::set m_player_database; - std::unordered_map m_mod_meta_database; + std::unordered_map m_mod_storage_database; }; diff --git a/src/database/database-files.cpp b/src/database/database-files.cpp index 0b94b28f2..e90a50619 100644 --- a/src/database/database-files.cpp +++ b/src/database/database-files.cpp @@ -376,12 +376,12 @@ bool AuthDatabaseFiles::writeAuthFile() return true; } -ModMetadataDatabaseFiles::ModMetadataDatabaseFiles(const std::string &savedir): +ModStorageDatabaseFiles::ModStorageDatabaseFiles(const std::string &savedir): m_storage_dir(savedir + DIR_DELIM + "mod_storage") { } -bool ModMetadataDatabaseFiles::getModEntries(const std::string &modname, StringMap *storage) +bool ModStorageDatabaseFiles::getModEntries(const std::string &modname, StringMap *storage) { Json::Value *meta = getOrCreateJson(modname); if (!meta) @@ -396,7 +396,7 @@ bool ModMetadataDatabaseFiles::getModEntries(const std::string &modname, StringM return true; } -bool ModMetadataDatabaseFiles::getModKeys(const std::string &modname, +bool ModStorageDatabaseFiles::getModKeys(const std::string &modname, std::vector *storage) { Json::Value *meta = getOrCreateJson(modname); @@ -411,7 +411,7 @@ bool ModMetadataDatabaseFiles::getModKeys(const std::string &modname, return true; } -bool ModMetadataDatabaseFiles::getModEntry(const std::string &modname, +bool ModStorageDatabaseFiles::getModEntry(const std::string &modname, const std::string &key, std::string *value) { Json::Value *meta = getOrCreateJson(modname); @@ -425,13 +425,13 @@ bool ModMetadataDatabaseFiles::getModEntry(const std::string &modname, return false; } -bool ModMetadataDatabaseFiles::hasModEntry(const std::string &modname, const std::string &key) +bool ModStorageDatabaseFiles::hasModEntry(const std::string &modname, const std::string &key) { Json::Value *meta = getOrCreateJson(modname); return meta && meta->isMember(key); } -bool ModMetadataDatabaseFiles::setModEntry(const std::string &modname, +bool ModStorageDatabaseFiles::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { Json::Value *meta = getOrCreateJson(modname); @@ -444,7 +444,7 @@ bool ModMetadataDatabaseFiles::setModEntry(const std::string &modname, return true; } -bool ModMetadataDatabaseFiles::removeModEntry(const std::string &modname, +bool ModStorageDatabaseFiles::removeModEntry(const std::string &modname, const std::string &key) { Json::Value *meta = getOrCreateJson(modname); @@ -459,7 +459,7 @@ bool ModMetadataDatabaseFiles::removeModEntry(const std::string &modname, return false; } -bool ModMetadataDatabaseFiles::removeModEntries(const std::string &modname) +bool ModStorageDatabaseFiles::removeModEntries(const std::string &modname) { Json::Value *meta = getOrCreateJson(modname); if (!meta || meta->empty()) @@ -470,22 +470,22 @@ bool ModMetadataDatabaseFiles::removeModEntries(const std::string &modname) return true; } -void ModMetadataDatabaseFiles::beginSave() +void ModStorageDatabaseFiles::beginSave() { } -void ModMetadataDatabaseFiles::endSave() +void ModStorageDatabaseFiles::endSave() { if (m_modified.empty()) return; if (!fs::CreateAllDirs(m_storage_dir)) { - errorstream << "ModMetadataDatabaseFiles: Unable to save. '" + errorstream << "ModStorageDatabaseFiles: Unable to save. '" << m_storage_dir << "' cannot be created." << std::endl; return; } if (!fs::IsDir(m_storage_dir)) { - errorstream << "ModMetadataDatabaseFiles: Unable to save. '" + errorstream << "ModStorageDatabaseFiles: Unable to save. '" << m_storage_dir << "' is not a directory." << std::endl; return; } @@ -493,10 +493,10 @@ void ModMetadataDatabaseFiles::endSave() for (auto it = m_modified.begin(); it != m_modified.end();) { const std::string &modname = *it; - const Json::Value &json = m_mod_meta[modname]; + const Json::Value &json = m_mod_storage[modname]; if (!fs::safeWriteToFile(m_storage_dir + DIR_DELIM + modname, fastWriteJson(json))) { - errorstream << "ModMetadataDatabaseFiles[" << modname + errorstream << "ModStorageDatabaseFiles[" << modname << "]: failed to write file." << std::endl; ++it; continue; @@ -506,24 +506,24 @@ void ModMetadataDatabaseFiles::endSave() } } -void ModMetadataDatabaseFiles::listMods(std::vector *res) +void ModStorageDatabaseFiles::listMods(std::vector *res) { // List in-memory metadata first. - for (const auto &pair : m_mod_meta) { + for (const auto &pair : m_mod_storage) { res->push_back(pair.first); } // List other metadata present in the filesystem. for (const auto &entry : fs::GetDirListing(m_storage_dir)) { - if (!entry.dir && m_mod_meta.count(entry.name) == 0) + if (!entry.dir && m_mod_storage.count(entry.name) == 0) res->push_back(entry.name); } } -Json::Value *ModMetadataDatabaseFiles::getOrCreateJson(const std::string &modname) +Json::Value *ModStorageDatabaseFiles::getOrCreateJson(const std::string &modname) { - auto found = m_mod_meta.find(modname); - if (found != m_mod_meta.end()) + auto found = m_mod_storage.find(modname); + if (found != m_mod_storage.end()) return &found->second; Json::Value meta(Json::objectValue); @@ -537,11 +537,11 @@ Json::Value *ModMetadataDatabaseFiles::getOrCreateJson(const std::string &modnam std::string errs; if (!Json::parseFromStream(builder, is, &meta, &errs)) { - errorstream << "ModMetadataDatabaseFiles[" << modname + errorstream << "ModStorageDatabaseFiles[" << modname << "]: failed to decode data: " << errs << std::endl; return nullptr; } } - return &(m_mod_meta[modname] = std::move(meta)); + return &(m_mod_storage[modname] = std::move(meta)); } diff --git a/src/database/database-files.h b/src/database/database-files.h index 2f74cc2e1..20b0b5896 100644 --- a/src/database/database-files.h +++ b/src/database/database-files.h @@ -72,11 +72,11 @@ private: bool writeAuthFile(); }; -class ModMetadataDatabaseFiles : public ModMetadataDatabase +class ModStorageDatabaseFiles : public ModStorageDatabase { public: - ModMetadataDatabaseFiles(const std::string &savedir); - virtual ~ModMetadataDatabaseFiles() = default; + ModStorageDatabaseFiles(const std::string &savedir); + virtual ~ModStorageDatabaseFiles() = default; virtual bool getModEntries(const std::string &modname, StringMap *storage); virtual bool getModKeys(const std::string &modname, std::vector *storage); @@ -97,6 +97,6 @@ private: bool writeJson(const std::string &modname, const Json::Value &json); std::string m_storage_dir; - std::unordered_map m_mod_meta; + std::unordered_map m_mod_storage; std::unordered_set m_modified; }; diff --git a/src/database/database-postgresql.cpp b/src/database/database-postgresql.cpp index a1ced8927..1c51a8d85 100644 --- a/src/database/database-postgresql.cpp +++ b/src/database/database-postgresql.cpp @@ -813,14 +813,14 @@ void AuthDatabasePostgreSQL::writePrivileges(const AuthEntry &authEntry) } } -ModMetadataDatabasePostgreSQL::ModMetadataDatabasePostgreSQL(const std::string &connect_string): +ModStorageDatabasePostgreSQL::ModStorageDatabasePostgreSQL(const std::string &connect_string): Database_PostgreSQL(connect_string, "_mod_storage"), - ModMetadataDatabase() + ModStorageDatabase() { connectToDatabase(); } -void ModMetadataDatabasePostgreSQL::createDatabase() +void ModStorageDatabasePostgreSQL::createDatabase() { createTableIfNotExists("mod_storage", "CREATE TABLE mod_storage (" @@ -833,7 +833,7 @@ void ModMetadataDatabasePostgreSQL::createDatabase() infostream << "PostgreSQL: Mod Storage Database was initialized." << std::endl; } -void ModMetadataDatabasePostgreSQL::initStatements() +void ModStorageDatabasePostgreSQL::initStatements() { prepareStatement("get_all", "SELECT key, value FROM mod_storage WHERE modname = $1"); @@ -866,7 +866,7 @@ void ModMetadataDatabasePostgreSQL::initStatements() "SELECT DISTINCT modname FROM mod_storage"); } -bool ModMetadataDatabasePostgreSQL::getModEntries(const std::string &modname, StringMap *storage) +bool ModStorageDatabasePostgreSQL::getModEntries(const std::string &modname, StringMap *storage) { verifyDatabase(); @@ -886,7 +886,7 @@ bool ModMetadataDatabasePostgreSQL::getModEntries(const std::string &modname, St return true; } -bool ModMetadataDatabasePostgreSQL::getModKeys(const std::string &modname, +bool ModStorageDatabasePostgreSQL::getModKeys(const std::string &modname, std::vector *storage) { verifyDatabase(); @@ -908,7 +908,7 @@ bool ModMetadataDatabasePostgreSQL::getModKeys(const std::string &modname, return true; } -bool ModMetadataDatabasePostgreSQL::getModEntry(const std::string &modname, +bool ModStorageDatabasePostgreSQL::getModEntry(const std::string &modname, const std::string &key, std::string *value) { verifyDatabase(); @@ -929,7 +929,7 @@ bool ModMetadataDatabasePostgreSQL::getModEntry(const std::string &modname, return found; } -bool ModMetadataDatabasePostgreSQL::hasModEntry(const std::string &modname, +bool ModStorageDatabasePostgreSQL::hasModEntry(const std::string &modname, const std::string &key) { verifyDatabase(); @@ -947,7 +947,7 @@ bool ModMetadataDatabasePostgreSQL::hasModEntry(const std::string &modname, return found; } -bool ModMetadataDatabasePostgreSQL::setModEntry(const std::string &modname, +bool ModStorageDatabasePostgreSQL::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { verifyDatabase(); @@ -969,7 +969,7 @@ bool ModMetadataDatabasePostgreSQL::setModEntry(const std::string &modname, return true; } -bool ModMetadataDatabasePostgreSQL::removeModEntry(const std::string &modname, +bool ModStorageDatabasePostgreSQL::removeModEntry(const std::string &modname, const std::string &key) { verifyDatabase(); @@ -986,7 +986,7 @@ bool ModMetadataDatabasePostgreSQL::removeModEntry(const std::string &modname, return affected > 0; } -bool ModMetadataDatabasePostgreSQL::removeModEntries(const std::string &modname) +bool ModStorageDatabasePostgreSQL::removeModEntries(const std::string &modname) { verifyDatabase(); @@ -1002,7 +1002,7 @@ bool ModMetadataDatabasePostgreSQL::removeModEntries(const std::string &modname) return affected > 0; } -void ModMetadataDatabasePostgreSQL::listMods(std::vector *res) +void ModStorageDatabasePostgreSQL::listMods(std::vector *res) { verifyDatabase(); diff --git a/src/database/database-postgresql.h b/src/database/database-postgresql.h index 278379f5d..a587f3d9e 100644 --- a/src/database/database-postgresql.h +++ b/src/database/database-postgresql.h @@ -175,11 +175,11 @@ private: virtual void writePrivileges(const AuthEntry &authEntry); }; -class ModMetadataDatabasePostgreSQL : private Database_PostgreSQL, public ModMetadataDatabase +class ModStorageDatabasePostgreSQL : private Database_PostgreSQL, public ModStorageDatabase { public: - ModMetadataDatabasePostgreSQL(const std::string &connect_string); - ~ModMetadataDatabasePostgreSQL() = default; + ModStorageDatabasePostgreSQL(const std::string &connect_string); + ~ModStorageDatabasePostgreSQL() = default; bool getModEntries(const std::string &modname, StringMap *storage); bool getModKeys(const std::string &modname, std::vector *storage); diff --git a/src/database/database-sqlite3.cpp b/src/database/database-sqlite3.cpp index 5511a46de..636864d82 100644 --- a/src/database/database-sqlite3.cpp +++ b/src/database/database-sqlite3.cpp @@ -763,12 +763,12 @@ void AuthDatabaseSQLite3::writePrivileges(const AuthEntry &authEntry) } } -ModMetadataDatabaseSQLite3::ModMetadataDatabaseSQLite3(const std::string &savedir): - Database_SQLite3(savedir, "mod_storage"), ModMetadataDatabase() +ModStorageDatabaseSQLite3::ModStorageDatabaseSQLite3(const std::string &savedir): + Database_SQLite3(savedir, "mod_storage"), ModStorageDatabase() { } -ModMetadataDatabaseSQLite3::~ModMetadataDatabaseSQLite3() +ModStorageDatabaseSQLite3::~ModStorageDatabaseSQLite3() { FINALIZE_STATEMENT(m_stmt_remove_all) FINALIZE_STATEMENT(m_stmt_remove) @@ -779,7 +779,7 @@ ModMetadataDatabaseSQLite3::~ModMetadataDatabaseSQLite3() FINALIZE_STATEMENT(m_stmt_get_all) } -void ModMetadataDatabaseSQLite3::createDatabase() +void ModStorageDatabaseSQLite3::createDatabase() { assert(m_database); // Pre-condition @@ -794,7 +794,7 @@ void ModMetadataDatabaseSQLite3::createDatabase() "Failed to create database table"); } -void ModMetadataDatabaseSQLite3::initStatements() +void ModStorageDatabaseSQLite3::initStatements() { PREPARE_STATEMENT(get_all, "SELECT `key`, `value` FROM `entries` WHERE `modname` = ?"); PREPARE_STATEMENT(get_keys, "SELECT `key` FROM `entries` WHERE `modname` = ?"); @@ -808,7 +808,7 @@ void ModMetadataDatabaseSQLite3::initStatements() PREPARE_STATEMENT(remove_all, "DELETE FROM `entries` WHERE `modname` = ?"); } -bool ModMetadataDatabaseSQLite3::getModEntries(const std::string &modname, StringMap *storage) +bool ModStorageDatabaseSQLite3::getModEntries(const std::string &modname, StringMap *storage) { verifyDatabase(); @@ -827,7 +827,7 @@ bool ModMetadataDatabaseSQLite3::getModEntries(const std::string &modname, Strin return true; } -bool ModMetadataDatabaseSQLite3::getModKeys(const std::string &modname, +bool ModStorageDatabaseSQLite3::getModKeys(const std::string &modname, std::vector *storage) { verifyDatabase(); @@ -845,7 +845,7 @@ bool ModMetadataDatabaseSQLite3::getModKeys(const std::string &modname, return true; } -bool ModMetadataDatabaseSQLite3::getModEntry(const std::string &modname, +bool ModStorageDatabaseSQLite3::getModEntry(const std::string &modname, const std::string &key, std::string *value) { verifyDatabase(); @@ -866,7 +866,7 @@ bool ModMetadataDatabaseSQLite3::getModEntry(const std::string &modname, return found; } -bool ModMetadataDatabaseSQLite3::hasModEntry(const std::string &modname, +bool ModStorageDatabaseSQLite3::hasModEntry(const std::string &modname, const std::string &key) { verifyDatabase(); @@ -883,7 +883,7 @@ bool ModMetadataDatabaseSQLite3::hasModEntry(const std::string &modname, return found; } -bool ModMetadataDatabaseSQLite3::setModEntry(const std::string &modname, +bool ModStorageDatabaseSQLite3::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { verifyDatabase(); @@ -900,7 +900,7 @@ bool ModMetadataDatabaseSQLite3::setModEntry(const std::string &modname, return true; } -bool ModMetadataDatabaseSQLite3::removeModEntry(const std::string &modname, +bool ModStorageDatabaseSQLite3::removeModEntry(const std::string &modname, const std::string &key) { verifyDatabase(); @@ -916,7 +916,7 @@ bool ModMetadataDatabaseSQLite3::removeModEntry(const std::string &modname, return changes > 0; } -bool ModMetadataDatabaseSQLite3::removeModEntries(const std::string &modname) +bool ModStorageDatabaseSQLite3::removeModEntries(const std::string &modname) { verifyDatabase(); @@ -929,7 +929,7 @@ bool ModMetadataDatabaseSQLite3::removeModEntries(const std::string &modname) return changes > 0; } -void ModMetadataDatabaseSQLite3::listMods(std::vector *res) +void ModStorageDatabaseSQLite3::listMods(std::vector *res) { verifyDatabase(); diff --git a/src/database/database-sqlite3.h b/src/database/database-sqlite3.h index 20488f0f0..3eaacbe11 100644 --- a/src/database/database-sqlite3.h +++ b/src/database/database-sqlite3.h @@ -233,11 +233,11 @@ private: sqlite3_stmt *m_stmt_last_insert_rowid = nullptr; }; -class ModMetadataDatabaseSQLite3 : private Database_SQLite3, public ModMetadataDatabase +class ModStorageDatabaseSQLite3 : private Database_SQLite3, public ModStorageDatabase { public: - ModMetadataDatabaseSQLite3(const std::string &savedir); - virtual ~ModMetadataDatabaseSQLite3(); + ModStorageDatabaseSQLite3(const std::string &savedir); + virtual ~ModStorageDatabaseSQLite3(); virtual bool getModEntries(const std::string &modname, StringMap *storage); virtual bool getModKeys(const std::string &modname, std::vector *storage); diff --git a/src/database/database.h b/src/database/database.h index bf5a3da2b..123cdadda 100644 --- a/src/database/database.h +++ b/src/database/database.h @@ -86,10 +86,10 @@ public: virtual void reload() = 0; }; -class ModMetadataDatabase : public Database +class ModStorageDatabase : public Database { public: - virtual ~ModMetadataDatabase() = default; + virtual ~ModStorageDatabase() = default; virtual bool getModEntries(const std::string &modname, StringMap *storage) = 0; virtual bool getModKeys(const std::string &modname, std::vector *storage) = 0; diff --git a/src/dummygamedef.h b/src/dummygamedef.h index b27e6e64c..567c30534 100644 --- a/src/dummygamedef.h +++ b/src/dummygamedef.h @@ -61,7 +61,7 @@ public: return emptymodspec; } const ModSpec* getModSpec(const std::string &modname) const override { return nullptr; } - ModMetadataDatabase *getModStorageDatabase() override { return m_mod_storage_database; } + ModStorageDatabase *getModStorageDatabase() override { return m_mod_storage_database; } bool joinModChannel(const std::string &channel) override { return false; } bool leaveModChannel(const std::string &channel) override { return false; } @@ -75,5 +75,5 @@ protected: IItemDefManager *m_itemdef = nullptr; NodeDefManager *m_nodedef = nullptr; ICraftDefManager *m_craftdef = nullptr; - ModMetadataDatabase *m_mod_storage_database = nullptr; + ModStorageDatabase *m_mod_storage_database = nullptr; }; diff --git a/src/gamedef.h b/src/gamedef.h index 690ff1257..e32d10509 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -32,8 +32,8 @@ class IRollbackManager; class EmergeManager; class Camera; class ModChannel; -class ModMetadata; -class ModMetadataDatabase; +class ModStorage; +class ModStorageDatabase; namespace irr { namespace scene { class IAnimatedMesh; @@ -73,7 +73,7 @@ public: virtual const std::vector &getMods() const = 0; virtual const ModSpec* getModSpec(const std::string &modname) const = 0; virtual std::string getWorldPath() const { return ""; } - virtual ModMetadataDatabase *getModStorageDatabase() = 0; + virtual ModStorageDatabase *getModStorageDatabase() = 0; virtual bool joinModChannel(const std::string &channel) = 0; virtual bool leaveModChannel(const std::string &channel) = 0; diff --git a/src/script/lua_api/l_storage.cpp b/src/script/lua_api/l_storage.cpp index e1d47ba72..dd2a4123d 100644 --- a/src/script/lua_api/l_storage.cpp +++ b/src/script/lua_api/l_storage.cpp @@ -41,7 +41,7 @@ void ModApiStorage::Initialize(lua_State *L, int top) API_FCT(get_mod_storage); } -void StorageRef::create(lua_State *L, const std::string &mod_name, ModMetadataDatabase *db) +void StorageRef::create(lua_State *L, const std::string &mod_name, ModStorageDatabase *db) { StorageRef *o = new StorageRef(mod_name, db); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; diff --git a/src/script/lua_api/l_storage.h b/src/script/lua_api/l_storage.h index d7f717363..ce41adb08 100644 --- a/src/script/lua_api/l_storage.h +++ b/src/script/lua_api/l_storage.h @@ -36,7 +36,7 @@ public: class StorageRef : public MetaDataRef { private: - ModMetadata m_object; + ModStorage m_object; static const luaL_Reg methods[]; @@ -44,11 +44,11 @@ private: virtual void clearMeta(); public: - StorageRef(const std::string &mod_name, ModMetadataDatabase *db): m_object(mod_name, db) {} + StorageRef(const std::string &mod_name, ModStorageDatabase *db): m_object(mod_name, db) {} ~StorageRef() = default; static void Register(lua_State *L); - static void create(lua_State *L, const std::string &mod_name, ModMetadataDatabase *db); + static void create(lua_State *L, const std::string &mod_name, ModStorageDatabase *db); static const char className[]; }; diff --git a/src/server.cpp b/src/server.cpp index 416e51f30..fb2e0db95 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4004,7 +4004,7 @@ Translations *Server::getTranslationLanguage(const std::string &lang_code) return translations; } -ModMetadataDatabase *Server::openModStorageDatabase(const std::string &world_path) +ModStorageDatabase *Server::openModStorageDatabase(const std::string &world_path) { std::string world_mt_path = world_path + DIR_DELIM + "world.mt"; Settings world_mt; @@ -4022,22 +4022,22 @@ ModMetadataDatabase *Server::openModStorageDatabase(const std::string &world_pat return openModStorageDatabase(backend, world_path, world_mt); } -ModMetadataDatabase *Server::openModStorageDatabase(const std::string &backend, +ModStorageDatabase *Server::openModStorageDatabase(const std::string &backend, const std::string &world_path, const Settings &world_mt) { if (backend == "sqlite3") - return new ModMetadataDatabaseSQLite3(world_path); + return new ModStorageDatabaseSQLite3(world_path); #if USE_POSTGRESQL if (backend == "postgresql") { std::string connect_string; world_mt.getNoEx("pgsql_mod_storage_connection", connect_string); - return new ModMetadataDatabasePostgreSQL(connect_string); + return new ModStorageDatabasePostgreSQL(connect_string); } #endif // USE_POSTGRESQL if (backend == "files") - return new ModMetadataDatabaseFiles(world_path); + return new ModStorageDatabaseFiles(world_path); if (backend == "dummy") return new Database_Dummy(); @@ -4063,8 +4063,8 @@ bool Server::migrateModStorageDatabase(const GameParams &game_params, const Sett return false; } - ModMetadataDatabase *srcdb = nullptr; - ModMetadataDatabase *dstdb = nullptr; + ModStorageDatabase *srcdb = nullptr; + ModStorageDatabase *dstdb = nullptr; bool succeeded = false; diff --git a/src/server.h b/src/server.h index 2d20c52a0..06da14a9a 100644 --- a/src/server.h +++ b/src/server.h @@ -276,7 +276,7 @@ public: virtual u16 allocateUnknownNodeId(const std::string &name); IRollbackManager *getRollbackManager() { return m_rollback; } virtual EmergeManager *getEmergeManager() { return m_emerge; } - virtual ModMetadataDatabase *getModStorageDatabase() { return m_mod_storage_database; } + virtual ModStorageDatabase *getModStorageDatabase() { return m_mod_storage_database; } IWritableItemDefManager* getWritableItemDefManager(); NodeDefManager* getWritableNodeDefManager(); @@ -368,9 +368,9 @@ public: // Get or load translations for a language Translations *getTranslationLanguage(const std::string &lang_code); - static ModMetadataDatabase *openModStorageDatabase(const std::string &world_path); + static ModStorageDatabase *openModStorageDatabase(const std::string &world_path); - static ModMetadataDatabase *openModStorageDatabase(const std::string &backend, + static ModStorageDatabase *openModStorageDatabase(const std::string &backend, const std::string &world_path, const Settings &world_mt); static bool migrateModStorageDatabase(const GameParams &game_params, @@ -694,7 +694,7 @@ private: s32 m_next_sound_id = 0; // positive values only s32 nextSoundId(); - ModMetadataDatabase *m_mod_storage_database = nullptr; + ModStorageDatabase *m_mod_storage_database = nullptr; float m_mod_storage_save_timer = 10.0f; // CSM restrictions byteflag diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt index 61f08f3ba..0f80bcf1a 100644 --- a/src/unittest/CMakeLists.txt +++ b/src/unittest/CMakeLists.txt @@ -16,7 +16,7 @@ set (UNITTEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test_map_settings_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_mapnode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_modchannels.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/test_modmetadatadatabase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_modstoragedatabase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_moveaction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_nodedef.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_noderesolver.cpp diff --git a/src/unittest/test_modmetadatadatabase.cpp b/src/unittest/test_modmetadatadatabase.cpp deleted file mode 100644 index 1a443e51b..000000000 --- a/src/unittest/test_modmetadatadatabase.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* -Minetest -Copyright (C) 2018 bendeutsch, Ben Deutsch -Copyright (C) 2021 TurkeyMcMac, Jude Melton-Houghton - -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. -*/ - -// This file is an edited copy of test_authdatabase.cpp - -#include "cmake_config.h" - -#include "test.h" - -#include -#include -#include "database/database-dummy.h" -#include "database/database-files.h" -#include "database/database-sqlite3.h" -#if USE_POSTGRESQL -#include "database/database-postgresql.h" -#endif -#include "filesys.h" - -namespace -{ -// Anonymous namespace to create classes that are only -// visible to this file -// -// These are helpers that return a *ModMetadataDatabase and -// allow us to run the same tests on different databases and -// database acquisition strategies. - -class ModMetadataDatabaseProvider -{ -public: - virtual ~ModMetadataDatabaseProvider() = default; - virtual ModMetadataDatabase *getModMetadataDatabase() = 0; -}; - -class FixedProvider : public ModMetadataDatabaseProvider -{ -public: - FixedProvider(ModMetadataDatabase *mod_meta_db) : mod_meta_db(mod_meta_db){}; - virtual ~FixedProvider(){}; - virtual ModMetadataDatabase *getModMetadataDatabase() { return mod_meta_db; }; - -private: - ModMetadataDatabase *mod_meta_db; -}; - -class FilesProvider : public ModMetadataDatabaseProvider -{ -public: - FilesProvider(const std::string &dir) : dir(dir){}; - virtual ~FilesProvider() - { - if (mod_meta_db) - mod_meta_db->endSave(); - delete mod_meta_db; - } - virtual ModMetadataDatabase *getModMetadataDatabase() - { - if (mod_meta_db) - mod_meta_db->endSave(); - delete mod_meta_db; - mod_meta_db = new ModMetadataDatabaseFiles(dir); - mod_meta_db->beginSave(); - return mod_meta_db; - }; - -private: - std::string dir; - ModMetadataDatabase *mod_meta_db = nullptr; -}; - -class SQLite3Provider : public ModMetadataDatabaseProvider -{ -public: - SQLite3Provider(const std::string &dir) : dir(dir){}; - virtual ~SQLite3Provider() - { - if (mod_meta_db) - mod_meta_db->endSave(); - delete mod_meta_db; - } - virtual ModMetadataDatabase *getModMetadataDatabase() - { - if (mod_meta_db) - mod_meta_db->endSave(); - delete mod_meta_db; - mod_meta_db = new ModMetadataDatabaseSQLite3(dir); - mod_meta_db->beginSave(); - return mod_meta_db; - }; - -private: - std::string dir; - ModMetadataDatabase *mod_meta_db = nullptr; -}; - -#if USE_POSTGRESQL -void clearPostgreSQLDatabase(const std::string &connect_string) -{ - ModMetadataDatabasePostgreSQL db(connect_string); - std::vector modnames; - db.beginSave(); - db.listMods(&modnames); - for (const std::string &modname : modnames) - db.removeModEntries(modname); - db.endSave(); -} - -class PostgreSQLProvider : public ModMetadataDatabaseProvider -{ -public: - PostgreSQLProvider(const std::string &connect_string): m_connect_string(connect_string) {} - - ~PostgreSQLProvider() - { - if (m_db) - m_db->endSave(); - delete m_db; - } - - ModMetadataDatabase *getModMetadataDatabase() override - { - if (m_db) - m_db->endSave(); - delete m_db; - m_db = new ModMetadataDatabasePostgreSQL(m_connect_string); - m_db->beginSave(); - return m_db; - }; - -private: - std::string m_connect_string; - ModMetadataDatabase *m_db = nullptr; -}; -#endif // USE_POSTGRESQL -} - -class TestModMetadataDatabase : public TestBase -{ -public: - TestModMetadataDatabase() { TestManager::registerTestModule(this); } - const char *getName() { return "TestModMetadataDatabase"; } - - void runTests(IGameDef *gamedef); - void runTestsForCurrentDB(); - - void testRecallFail(); - void testCreate(); - void testRecall(); - void testChange(); - void testRecallChanged(); - void testListMods(); - void testRemove(); - -private: - ModMetadataDatabaseProvider *mod_meta_provider; -}; - -static TestModMetadataDatabase g_test_instance; - -void TestModMetadataDatabase::runTests(IGameDef *gamedef) -{ - // fixed directory, for persistence - thread_local const std::string test_dir = getTestTempDirectory(); - - // Each set of tests is run twice for each database type except dummy: - // one where we reuse the same ModMetadataDatabase object (to test local caching), - // and one where we create a new ModMetadataDatabase object for each call - // (to test actual persistence). - // Since the dummy database is only in-memory, it has no persistence to test. - - ModMetadataDatabase *mod_meta_db; - - rawstream << "-------- Dummy database (same object only)" << std::endl; - - mod_meta_db = new Database_Dummy(); - mod_meta_provider = new FixedProvider(mod_meta_db); - - runTestsForCurrentDB(); - - delete mod_meta_db; - delete mod_meta_provider; - - rawstream << "-------- Files database (same object)" << std::endl; - - mod_meta_db = new ModMetadataDatabaseFiles(test_dir); - mod_meta_provider = new FixedProvider(mod_meta_db); - - runTestsForCurrentDB(); - - delete mod_meta_db; - delete mod_meta_provider; - - // reset database - fs::RecursiveDelete(test_dir + DIR_DELIM + "mod_storage"); - - rawstream << "-------- Files database (new objects)" << std::endl; - - mod_meta_provider = new FilesProvider(test_dir); - - runTestsForCurrentDB(); - - delete mod_meta_provider; - - rawstream << "-------- SQLite3 database (same object)" << std::endl; - - mod_meta_db = new ModMetadataDatabaseSQLite3(test_dir); - mod_meta_provider = new FixedProvider(mod_meta_db); - - runTestsForCurrentDB(); - - delete mod_meta_db; - delete mod_meta_provider; - - // reset database - fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "mod_storage.sqlite"); - - rawstream << "-------- SQLite3 database (new objects)" << std::endl; - - mod_meta_provider = new SQLite3Provider(test_dir); - - runTestsForCurrentDB(); - - delete mod_meta_provider; - -#if USE_POSTGRESQL - const char *env_postgresql_connect_string = getenv("MINETEST_POSTGRESQL_CONNECT_STRING"); - if (env_postgresql_connect_string) { - std::string connect_string(env_postgresql_connect_string); - - rawstream << "-------- PostgreSQL database (same object)" << std::endl; - - clearPostgreSQLDatabase(connect_string); - mod_meta_db = new ModMetadataDatabasePostgreSQL(connect_string); - mod_meta_provider = new FixedProvider(mod_meta_db); - - runTestsForCurrentDB(); - - delete mod_meta_db; - delete mod_meta_provider; - - rawstream << "-------- PostgreSQL database (new objects)" << std::endl; - - clearPostgreSQLDatabase(connect_string); - mod_meta_provider = new PostgreSQLProvider(connect_string); - - runTestsForCurrentDB(); - - delete mod_meta_provider; - } -#endif // USE_POSTGRESQL -} - -//////////////////////////////////////////////////////////////////////////////// - -void TestModMetadataDatabase::runTestsForCurrentDB() -{ - TEST(testRecallFail); - TEST(testCreate); - TEST(testRecall); - TEST(testChange); - TEST(testRecallChanged); - TEST(testListMods); - TEST(testRemove); - TEST(testRecallFail); -} - -void TestModMetadataDatabase::testRecallFail() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - StringMap recalled; - std::vector recalled_keys; - mod_meta_db->getModEntries("mod1", &recalled); - mod_meta_db->getModKeys("mod1", &recalled_keys); - UASSERT(recalled.empty()); - UASSERT(recalled_keys.empty()); - std::string key1_value; - UASSERT(!mod_meta_db->getModEntry("mod1", "key1", &key1_value)); - UASSERT(!mod_meta_db->hasModEntry("mod1", "key1")); -} - -void TestModMetadataDatabase::testCreate() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - UASSERT(mod_meta_db->setModEntry("mod1", "key1", "value1")); -} - -void TestModMetadataDatabase::testRecall() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - StringMap recalled; - std::vector recalled_keys; - mod_meta_db->getModEntries("mod1", &recalled); - mod_meta_db->getModKeys("mod1", &recalled_keys); - UASSERTCMP(std::size_t, ==, recalled.size(), 1); - UASSERTCMP(std::size_t, ==, recalled_keys.size(), 1); - UASSERTCMP(std::string, ==, recalled["key1"], "value1"); - UASSERTCMP(std::string, ==, recalled_keys[0], "key1"); - std::string key1_value; - UASSERT(mod_meta_db->getModEntry("mod1", "key1", &key1_value)); - UASSERTCMP(std::string, ==, key1_value, "value1"); - UASSERT(mod_meta_db->hasModEntry("mod1", "key1")); -} - -void TestModMetadataDatabase::testChange() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - UASSERT(mod_meta_db->setModEntry("mod1", "key1", "value2")); -} - -void TestModMetadataDatabase::testRecallChanged() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - StringMap recalled; - mod_meta_db->getModEntries("mod1", &recalled); - UASSERTCMP(std::size_t, ==, recalled.size(), 1); - UASSERTCMP(std::string, ==, recalled["key1"], "value2"); - std::string key1_value; - UASSERT(mod_meta_db->getModEntry("mod1", "key1", &key1_value)); - UASSERTCMP(std::string, ==, key1_value, "value2"); - UASSERT(mod_meta_db->hasModEntry("mod1", "key1")); -} - -void TestModMetadataDatabase::testListMods() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - UASSERT(mod_meta_db->setModEntry("mod2", "key1", "value1")); - UASSERT(mod_meta_db->setModEntry("mod2", "key2", "value1")); - std::vector mod_list; - mod_meta_db->listMods(&mod_list); - UASSERTCMP(size_t, ==, mod_list.size(), 2); - UASSERT(std::find(mod_list.cbegin(), mod_list.cend(), "mod1") != mod_list.cend()); - UASSERT(std::find(mod_list.cbegin(), mod_list.cend(), "mod2") != mod_list.cend()); -} - -void TestModMetadataDatabase::testRemove() -{ - ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase(); - UASSERT(mod_meta_db->removeModEntry("mod1", "key1")); - UASSERT(!mod_meta_db->removeModEntries("mod1")); - UASSERT(mod_meta_db->removeModEntries("mod2")); -} diff --git a/src/unittest/test_modstoragedatabase.cpp b/src/unittest/test_modstoragedatabase.cpp new file mode 100644 index 000000000..7d2e6e4e0 --- /dev/null +++ b/src/unittest/test_modstoragedatabase.cpp @@ -0,0 +1,365 @@ +/* +Minetest +Copyright (C) 2018 bendeutsch, Ben Deutsch +Copyright (C) 2021 TurkeyMcMac, Jude Melton-Houghton + +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. +*/ + +// This file is an edited copy of test_authdatabase.cpp + +#include "cmake_config.h" + +#include "test.h" + +#include +#include +#include "database/database-dummy.h" +#include "database/database-files.h" +#include "database/database-sqlite3.h" +#if USE_POSTGRESQL +#include "database/database-postgresql.h" +#endif +#include "filesys.h" + +namespace +{ +// Anonymous namespace to create classes that are only +// visible to this file +// +// These are helpers that return a *ModStorageDatabase and +// allow us to run the same tests on different databases and +// database acquisition strategies. + +class ModStorageDatabaseProvider +{ +public: + virtual ~ModStorageDatabaseProvider() = default; + virtual ModStorageDatabase *getModStorageDatabase() = 0; +}; + +class FixedProvider : public ModStorageDatabaseProvider +{ +public: + FixedProvider(ModStorageDatabase *db): m_db(db) {} + + ~FixedProvider() = default; + + ModStorageDatabase *getModStorageDatabase() override { return m_db; } + +private: + ModStorageDatabase *m_db; +}; + +class FilesProvider : public ModStorageDatabaseProvider +{ +public: + FilesProvider(const std::string &dir): m_dir(dir) {} + + ~FilesProvider() + { + if (m_db) + m_db->endSave(); + delete m_db; + } + + ModStorageDatabase *getModStorageDatabase() override + { + if (m_db) + m_db->endSave(); + delete m_db; + m_db = new ModStorageDatabaseFiles(m_dir); + m_db->beginSave(); + return m_db; + } + +private: + std::string m_dir; + ModStorageDatabase *m_db = nullptr; +}; + +class SQLite3Provider : public ModStorageDatabaseProvider +{ +public: + SQLite3Provider(const std::string &dir): m_dir(dir) {} + + ~SQLite3Provider() + { + if (m_db) + m_db->endSave(); + delete m_db; + } + + ModStorageDatabase *getModStorageDatabase() override + { + if (m_db) + m_db->endSave(); + delete m_db; + m_db = new ModStorageDatabaseSQLite3(m_dir); + m_db->beginSave(); + return m_db; + } + +private: + std::string m_dir; + ModStorageDatabase *m_db = nullptr; +}; + +#if USE_POSTGRESQL +void clearPostgreSQLDatabase(const std::string &connect_string) +{ + ModStorageDatabasePostgreSQL db(connect_string); + std::vector modnames; + db.beginSave(); + db.listMods(&modnames); + for (const std::string &modname : modnames) + db.removeModEntries(modname); + db.endSave(); +} + +class PostgreSQLProvider : public ModStorageDatabaseProvider +{ +public: + PostgreSQLProvider(const std::string &connect_string): m_connect_string(connect_string) {} + + ~PostgreSQLProvider() + { + if (m_db) + m_db->endSave(); + delete m_db; + } + + ModStorageDatabase *getModStorageDatabase() override + { + if (m_db) + m_db->endSave(); + delete m_db; + m_db = new ModStorageDatabasePostgreSQL(m_connect_string); + m_db->beginSave(); + return m_db; + }; + +private: + std::string m_connect_string; + ModStorageDatabase *m_db = nullptr; +}; +#endif // USE_POSTGRESQL +} + +class TestModStorageDatabase : public TestBase +{ +public: + TestModStorageDatabase() { TestManager::registerTestModule(this); } + const char *getName() { return "TestModStorageDatabase"; } + + void runTests(IGameDef *gamedef); + void runTestsForCurrentDB(); + + void testRecallFail(); + void testCreate(); + void testRecall(); + void testChange(); + void testRecallChanged(); + void testListMods(); + void testRemove(); + +private: + ModStorageDatabaseProvider *mod_storage_provider; +}; + +static TestModStorageDatabase g_test_instance; + +void TestModStorageDatabase::runTests(IGameDef *gamedef) +{ + // fixed directory, for persistence + thread_local const std::string test_dir = getTestTempDirectory(); + + // Each set of tests is run twice for each database type except dummy: + // one where we reuse the same ModStorageDatabase object (to test local caching), + // and one where we create a new ModStorageDatabase object for each call + // (to test actual persistence). + // Since the dummy database is only in-memory, it has no persistence to test. + + ModStorageDatabase *mod_storage_db; + + rawstream << "-------- Dummy database (same object only)" << std::endl; + + mod_storage_db = new Database_Dummy(); + mod_storage_provider = new FixedProvider(mod_storage_db); + + runTestsForCurrentDB(); + + delete mod_storage_db; + delete mod_storage_provider; + + rawstream << "-------- Files database (same object)" << std::endl; + + mod_storage_db = new ModStorageDatabaseFiles(test_dir); + mod_storage_provider = new FixedProvider(mod_storage_db); + + runTestsForCurrentDB(); + + delete mod_storage_db; + delete mod_storage_provider; + + // reset database + fs::RecursiveDelete(test_dir + DIR_DELIM + "mod_storage"); + + rawstream << "-------- Files database (new objects)" << std::endl; + + mod_storage_provider = new FilesProvider(test_dir); + + runTestsForCurrentDB(); + + delete mod_storage_provider; + + rawstream << "-------- SQLite3 database (same object)" << std::endl; + + mod_storage_db = new ModStorageDatabaseSQLite3(test_dir); + mod_storage_provider = new FixedProvider(mod_storage_db); + + runTestsForCurrentDB(); + + delete mod_storage_db; + delete mod_storage_provider; + + // reset database + fs::DeleteSingleFileOrEmptyDirectory(test_dir + DIR_DELIM + "mod_storage.sqlite"); + + rawstream << "-------- SQLite3 database (new objects)" << std::endl; + + mod_storage_provider = new SQLite3Provider(test_dir); + + runTestsForCurrentDB(); + + delete mod_storage_provider; + +#if USE_POSTGRESQL + const char *env_postgresql_connect_string = getenv("MINETEST_POSTGRESQL_CONNECT_STRING"); + if (env_postgresql_connect_string) { + std::string connect_string(env_postgresql_connect_string); + + rawstream << "-------- PostgreSQL database (same object)" << std::endl; + + clearPostgreSQLDatabase(connect_string); + mod_storage_db = new ModStorageDatabasePostgreSQL(connect_string); + mod_storage_provider = new FixedProvider(mod_storage_db); + + runTestsForCurrentDB(); + + delete mod_storage_db; + delete mod_storage_provider; + + rawstream << "-------- PostgreSQL database (new objects)" << std::endl; + + clearPostgreSQLDatabase(connect_string); + mod_storage_provider = new PostgreSQLProvider(connect_string); + + runTestsForCurrentDB(); + + delete mod_storage_provider; + } +#endif // USE_POSTGRESQL +} + +//////////////////////////////////////////////////////////////////////////////// + +void TestModStorageDatabase::runTestsForCurrentDB() +{ + TEST(testRecallFail); + TEST(testCreate); + TEST(testRecall); + TEST(testChange); + TEST(testRecallChanged); + TEST(testListMods); + TEST(testRemove); + TEST(testRecallFail); +} + +void TestModStorageDatabase::testRecallFail() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + StringMap recalled; + std::vector recalled_keys; + mod_storage_db->getModEntries("mod1", &recalled); + mod_storage_db->getModKeys("mod1", &recalled_keys); + UASSERT(recalled.empty()); + UASSERT(recalled_keys.empty()); + std::string key1_value; + UASSERT(!mod_storage_db->getModEntry("mod1", "key1", &key1_value)); + UASSERT(!mod_storage_db->hasModEntry("mod1", "key1")); +} + +void TestModStorageDatabase::testCreate() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + UASSERT(mod_storage_db->setModEntry("mod1", "key1", "value1")); +} + +void TestModStorageDatabase::testRecall() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + StringMap recalled; + std::vector recalled_keys; + mod_storage_db->getModEntries("mod1", &recalled); + mod_storage_db->getModKeys("mod1", &recalled_keys); + UASSERTCMP(std::size_t, ==, recalled.size(), 1); + UASSERTCMP(std::size_t, ==, recalled_keys.size(), 1); + UASSERTCMP(std::string, ==, recalled["key1"], "value1"); + UASSERTCMP(std::string, ==, recalled_keys[0], "key1"); + std::string key1_value; + UASSERT(mod_storage_db->getModEntry("mod1", "key1", &key1_value)); + UASSERTCMP(std::string, ==, key1_value, "value1"); + UASSERT(mod_storage_db->hasModEntry("mod1", "key1")); +} + +void TestModStorageDatabase::testChange() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + UASSERT(mod_storage_db->setModEntry("mod1", "key1", "value2")); +} + +void TestModStorageDatabase::testRecallChanged() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + StringMap recalled; + mod_storage_db->getModEntries("mod1", &recalled); + UASSERTCMP(std::size_t, ==, recalled.size(), 1); + UASSERTCMP(std::string, ==, recalled["key1"], "value2"); + std::string key1_value; + UASSERT(mod_storage_db->getModEntry("mod1", "key1", &key1_value)); + UASSERTCMP(std::string, ==, key1_value, "value2"); + UASSERT(mod_storage_db->hasModEntry("mod1", "key1")); +} + +void TestModStorageDatabase::testListMods() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + UASSERT(mod_storage_db->setModEntry("mod2", "key1", "value1")); + UASSERT(mod_storage_db->setModEntry("mod2", "key2", "value1")); + std::vector mod_list; + mod_storage_db->listMods(&mod_list); + UASSERTCMP(size_t, ==, mod_list.size(), 2); + UASSERT(std::find(mod_list.cbegin(), mod_list.cend(), "mod1") != mod_list.cend()); + UASSERT(std::find(mod_list.cbegin(), mod_list.cend(), "mod2") != mod_list.cend()); +} + +void TestModStorageDatabase::testRemove() +{ + ModStorageDatabase *mod_storage_db = mod_storage_provider->getModStorageDatabase(); + UASSERT(mod_storage_db->removeModEntry("mod1", "key1")); + UASSERT(!mod_storage_db->removeModEntries("mod1")); + UASSERT(mod_storage_db->removeModEntries("mod2")); +}