minetest/src/unittest/test_modmetadatadatabase.cpp

254 lines
6.8 KiB
C++

/*
Minetest
Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
Copyright (C) 2021 TurkeyMcMac, Jude Melton-Houghton <jwmhjwmh@gmail.com>
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 "test.h"
#include <algorithm>
#include "database/database-files.h"
#include "database/database-sqlite3.h"
#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;
};
}
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:
// 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).
rawstream << "-------- Files database (same object)" << std::endl;
ModMetadataDatabase *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;
}
////////////////////////////////////////////////////////////////////////////////
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;
mod_meta_db->getModEntries("mod1", &recalled);
UASSERT(recalled.empty());
}
void TestModMetadataDatabase::testCreate()
{
ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase();
StringMap recalled;
UASSERT(mod_meta_db->setModEntry("mod1", "key1", "value1"));
}
void TestModMetadataDatabase::testRecall()
{
ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase();
StringMap recalled;
mod_meta_db->getModEntries("mod1", &recalled);
UASSERT(recalled.size() == 1);
UASSERT(recalled["key1"] == "value1");
}
void TestModMetadataDatabase::testChange()
{
ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase();
StringMap recalled;
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);
UASSERT(recalled.size() == 1);
UASSERT(recalled["key1"] == "value2");
}
void TestModMetadataDatabase::testListMods()
{
ModMetadataDatabase *mod_meta_db = mod_meta_provider->getModMetadataDatabase();
UASSERT(mod_meta_db->setModEntry("mod2", "key1", "value1"));
std::vector<std::string> mod_list;
mod_meta_db->listMods(&mod_list);
UASSERT(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"));
}