mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Add unit tests for MapDatabase implementations
This commit is contained in:
parent
215b000793
commit
cc352f3b66
4 changed files with 198 additions and 2 deletions
|
@ -30,8 +30,7 @@ void Database_Dummy::loadBlock(const v3s16 &pos, std::string *block)
|
|||
|
||||
bool Database_Dummy::deleteBlock(const v3s16 &pos)
|
||||
{
|
||||
m_database.erase(getBlockAsInteger(pos));
|
||||
return true;
|
||||
return m_database.erase(getBlockAsInteger(pos)) > 0;
|
||||
}
|
||||
|
||||
void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
||||
|
|
|
@ -316,6 +316,7 @@ void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
|
|||
bindPos(m_stmt_read, pos);
|
||||
|
||||
if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
|
||||
block->clear();
|
||||
sqlite3_reset(m_stmt_read);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ set (UNITTEST_SRCS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/test_lua.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_map.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapblock.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapdatabase.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapgen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_map_settings_manager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapnode.cpp
|
||||
|
|
195
src/unittest/test_mapdatabase.cpp
Normal file
195
src/unittest/test_mapdatabase.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
// Luanti
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2024 sfan5
|
||||
|
||||
#include "cmake_config.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include "database/database-dummy.h"
|
||||
#include "database/database-sqlite3.h"
|
||||
#if USE_LEVELDB
|
||||
#include "database/database-leveldb.h"
|
||||
#endif
|
||||
#if USE_POSTGRESQL
|
||||
#include "database/database-postgresql.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class MapDatabaseProvider
|
||||
{
|
||||
public:
|
||||
typedef std::function<MapDatabase*(void)> F;
|
||||
|
||||
MapDatabaseProvider(MapDatabase *db) : can_create(false), m_db(db) {
|
||||
sanity_check(m_db);
|
||||
}
|
||||
MapDatabaseProvider(const F &creator) : can_create(true), m_creator(creator) {
|
||||
sanity_check(m_creator);
|
||||
}
|
||||
|
||||
~MapDatabaseProvider() {
|
||||
if (m_db)
|
||||
m_db->endSave();
|
||||
if (can_create)
|
||||
delete m_db;
|
||||
}
|
||||
|
||||
MapDatabase *get() {
|
||||
if (m_db)
|
||||
m_db->endSave();
|
||||
if (can_create) {
|
||||
delete m_db;
|
||||
m_db = m_creator();
|
||||
}
|
||||
m_db->beginSave();
|
||||
return m_db;
|
||||
}
|
||||
|
||||
private:
|
||||
bool can_create;
|
||||
F m_creator;
|
||||
MapDatabase *m_db = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class TestMapDatabase : public TestBase
|
||||
{
|
||||
public:
|
||||
TestMapDatabase() { TestManager::registerTestModule(this); }
|
||||
const char *getName() { return "TestMapDatabase"; }
|
||||
|
||||
void runTests(IGameDef *gamedef);
|
||||
void runTestsForCurrentDB();
|
||||
|
||||
void testSave();
|
||||
void testLoad();
|
||||
void testList(int expect);
|
||||
void testRemove();
|
||||
|
||||
private:
|
||||
MapDatabaseProvider *provider = nullptr;
|
||||
|
||||
std::string test_data;
|
||||
};
|
||||
|
||||
static TestMapDatabase g_test_instance;
|
||||
|
||||
void TestMapDatabase::runTests(IGameDef *gamedef)
|
||||
{
|
||||
// fixed directory, for persistence
|
||||
const std::string test_dir = getTestTempDirectory();
|
||||
|
||||
for (int c = 255; c >= 0; c--)
|
||||
test_data.push_back(static_cast<char>(c));
|
||||
sanity_check(!test_data.empty());
|
||||
|
||||
rawstream << "-------- Dummy" << std::endl;
|
||||
|
||||
// We can't re-create this object since it would lose the data
|
||||
{
|
||||
auto dummy_db = std::make_unique<Database_Dummy>();
|
||||
provider = new MapDatabaseProvider(dummy_db.get());
|
||||
runTestsForCurrentDB();
|
||||
delete provider;
|
||||
}
|
||||
|
||||
rawstream << "-------- SQLite3" << std::endl;
|
||||
|
||||
provider = new MapDatabaseProvider([&] () {
|
||||
return new MapDatabaseSQLite3(test_dir);
|
||||
});
|
||||
runTestsForCurrentDB();
|
||||
delete provider;
|
||||
|
||||
#if USE_LEVELDB
|
||||
rawstream << "-------- LevelDB" << std::endl;
|
||||
|
||||
provider = new MapDatabaseProvider([&] () {
|
||||
return new Database_LevelDB(test_dir);
|
||||
});
|
||||
runTestsForCurrentDB();
|
||||
delete provider;
|
||||
#endif
|
||||
|
||||
#if USE_POSTGRESQL
|
||||
const char *connstr = getenv("MINETEST_POSTGRESQL_CONNECT_STRING");
|
||||
if (connstr) {
|
||||
rawstream << "-------- PostgreSQL" << std::endl;
|
||||
|
||||
provider = new MapDatabaseProvider([&] () {
|
||||
return new MapDatabasePostgreSQL(connstr);
|
||||
});
|
||||
runTestsForCurrentDB();
|
||||
delete provider;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TestMapDatabase::runTestsForCurrentDB()
|
||||
{
|
||||
// order-sensitive
|
||||
TEST(testSave);
|
||||
TEST(testLoad);
|
||||
TEST(testList, 1);
|
||||
TEST(testRemove);
|
||||
TEST(testList, 0);
|
||||
}
|
||||
|
||||
void TestMapDatabase::testSave()
|
||||
{
|
||||
auto *db = provider->get();
|
||||
std::string_view stuff{"wrong wrong wrong"};
|
||||
UASSERT(db->saveBlock({1, 2, 3}, stuff));
|
||||
// overwriting is valid too
|
||||
UASSERT(db->saveBlock({1, 2, 3}, test_data));
|
||||
}
|
||||
|
||||
void TestMapDatabase::testLoad()
|
||||
{
|
||||
auto *db = provider->get();
|
||||
std::string dest;
|
||||
|
||||
// successful load
|
||||
db->loadBlock({1, 2, 3}, &dest);
|
||||
UASSERT(!dest.empty());
|
||||
UASSERT(dest == test_data);
|
||||
|
||||
// failed load
|
||||
v3s16 pp[] = {{1, 2, 4}, {0, 0, 0}, {-1, -2, -3}};
|
||||
for (v3s16 p : pp) {
|
||||
dest = "not empty";
|
||||
db->loadBlock(p, &dest);
|
||||
UASSERT(dest.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void TestMapDatabase::testList(int expect)
|
||||
{
|
||||
auto *db = provider->get();
|
||||
std::vector<v3s16> dest;
|
||||
db->listAllLoadableBlocks(dest);
|
||||
UASSERTEQ(size_t, dest.size(), expect);
|
||||
if (expect == 1)
|
||||
UASSERT(dest.front() == v3s16(1, 2, 3));
|
||||
}
|
||||
|
||||
void TestMapDatabase::testRemove()
|
||||
{
|
||||
auto *db = provider->get();
|
||||
|
||||
// successful remove
|
||||
UASSERT(db->deleteBlock({1, 2, 3}));
|
||||
|
||||
// failed remove
|
||||
// FIXME: this isn't working consistently, maybe later
|
||||
//UASSERT(!db->deleteBlock({1, 2, 4}));
|
||||
}
|
Loading…
Add table
Reference in a new issue