mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-05 09:46:38 +00:00
test: parameterize RelationalDatabase_test for multiple backends
- Add backend parameter to all test methods - Parse backends from --unittest-arg (CSV format: sqlite,rwdb) - Skip dbHasSpace checks for SQLite (uses in-memory databases in standalone mode) - Remove unnecessary database path setup/cleanup - Rename getDB() to getInterface()
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/rdb/RelationalDatabase.h>
|
||||
#include <ripple/app/rdb/backend/SQLiteDatabase.h>
|
||||
#include <ripple/core/ConfigSections.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <chrono>
|
||||
#include <test/jtx.h>
|
||||
#include <test/jtx/envconfig.h>
|
||||
@@ -29,16 +30,42 @@ namespace test {
|
||||
|
||||
class RelationalDatabase_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testBasicInitialization()
|
||||
private:
|
||||
// Helper to get SQLiteDatabase* (works for both SQLite and RWDB since RWDB
|
||||
// inherits from SQLiteDatabase)
|
||||
static SQLiteDatabase*
|
||||
getInterface(Application& app)
|
||||
{
|
||||
testcase("Basic initialization and empty database");
|
||||
return dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
|
||||
}
|
||||
|
||||
static SQLiteDatabase*
|
||||
getInterface(RelationalDatabase& db)
|
||||
{
|
||||
return dynamic_cast<SQLiteDatabase*>(&db);
|
||||
}
|
||||
|
||||
static std::unique_ptr<Config>
|
||||
makeConfig(std::string const& backend)
|
||||
{
|
||||
auto config = test::jtx::envconfig();
|
||||
// Sqlite backend doesn't need a database_path as it will just use
|
||||
// in-memory databases when in standalone mode anyway.
|
||||
config->overwrite(SECTION_RELATIONAL_DB, "backend", backend);
|
||||
return config;
|
||||
}
|
||||
|
||||
public:
|
||||
RelationalDatabase_test() = default;
|
||||
|
||||
void
|
||||
testBasicInitialization(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Basic initialization and empty database - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
auto& db = env.app().getRelationalDatabase();
|
||||
|
||||
@@ -47,7 +74,7 @@ public:
|
||||
BEAST_EXPECT(db.getMaxLedgerSeq() == 2);
|
||||
BEAST_EXPECT(db.getNewestLedgerInfo()->seq == 2);
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
|
||||
if (sqliteDb)
|
||||
@@ -64,12 +91,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testLedgerSequenceOperations()
|
||||
testLedgerSequenceOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Ledger sequence operations");
|
||||
testcase("Ledger sequence operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -103,7 +131,7 @@ public:
|
||||
BEAST_EXPECT(*minSeq == 2);
|
||||
BEAST_EXPECT(*maxSeq == 5);
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
if (sqliteDb)
|
||||
{
|
||||
auto ledgerCount = sqliteDb->getLedgerCountMinMax();
|
||||
@@ -114,17 +142,17 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testLedgerInfoOperations()
|
||||
testLedgerInfoOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Ledger info retrieval operations");
|
||||
testcase("Ledger info retrieval operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
auto* db =
|
||||
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase());
|
||||
auto* db = getInterface(env.app());
|
||||
|
||||
Account alice("alice");
|
||||
env.fund(XRP(10000), alice);
|
||||
@@ -167,12 +195,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testHashOperations()
|
||||
testHashOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Hash retrieval operations");
|
||||
testcase("Hash retrieval operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -218,12 +247,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testTransactionOperations()
|
||||
testTransactionOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Transaction storage and retrieval");
|
||||
testcase("Transaction storage and retrieval - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -235,7 +265,7 @@ public:
|
||||
env.fund(XRP(10000), alice, bob);
|
||||
env.close();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
|
||||
if (!sqliteDb)
|
||||
@@ -290,12 +320,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testAccountTransactionOperations()
|
||||
testAccountTransactionOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Account transaction operations");
|
||||
testcase("Account transaction operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -308,7 +339,9 @@ public:
|
||||
env.fund(XRP(10000), alice, bob, carol);
|
||||
env.close();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
|
||||
if (!sqliteDb)
|
||||
return;
|
||||
|
||||
@@ -369,12 +402,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testAccountTransactionPaging()
|
||||
testAccountTransactionPaging(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Account transaction paging operations");
|
||||
testcase("Account transaction paging operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -386,7 +420,8 @@ public:
|
||||
env.fund(XRP(10000), alice, bob);
|
||||
env.close();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
if (!sqliteDb)
|
||||
return;
|
||||
|
||||
@@ -440,12 +475,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testDeletionOperations()
|
||||
testDeletionOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Deletion operations");
|
||||
testcase("Deletion operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
@@ -457,7 +493,8 @@ public:
|
||||
env.fund(XRP(10000), alice, bob);
|
||||
env.close();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
if (!sqliteDb)
|
||||
return;
|
||||
|
||||
@@ -505,33 +542,41 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testDatabaseSpaceOperations()
|
||||
testDatabaseSpaceOperations(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Database space and size operations");
|
||||
testcase("Database space and size operations - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
auto& db = env.app().getRelationalDatabase();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
if (!sqliteDb)
|
||||
return;
|
||||
|
||||
// Test space availability (should always be true for in-memory)
|
||||
BEAST_EXPECT(db.ledgerDbHasSpace(env.app().config()));
|
||||
BEAST_EXPECT(db.transactionDbHasSpace(env.app().config()));
|
||||
|
||||
// Test size queries
|
||||
auto allKB = sqliteDb->getKBUsedAll();
|
||||
auto ledgerKB = sqliteDb->getKBUsedLedger();
|
||||
auto txKB = sqliteDb->getKBUsedTransaction();
|
||||
|
||||
BEAST_EXPECT(allKB == 0);
|
||||
BEAST_EXPECT(ledgerKB == 0);
|
||||
BEAST_EXPECT(txKB == 0);
|
||||
if (backend == "rwdb")
|
||||
{
|
||||
// RWDB reports actual data memory
|
||||
// After closing genesis ledger, should have some data
|
||||
BEAST_EXPECT(allKB == 0);
|
||||
BEAST_EXPECT(ledgerKB == 0);
|
||||
BEAST_EXPECT(txKB == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Will not assert on sqlite usage except that it's non-zero
|
||||
BEAST_EXPECT(allKB > 0);
|
||||
BEAST_EXPECT(ledgerKB > 0);
|
||||
BEAST_EXPECT(txKB > 0);
|
||||
}
|
||||
|
||||
// Create some data and verify size increases
|
||||
Account alice("alice");
|
||||
@@ -542,9 +587,37 @@ public:
|
||||
auto newLedgerKB = sqliteDb->getKBUsedLedger();
|
||||
auto newTxKB = sqliteDb->getKBUsedTransaction();
|
||||
|
||||
BEAST_EXPECT(newAllKB == 2);
|
||||
BEAST_EXPECT(newLedgerKB == 0);
|
||||
BEAST_EXPECT(newTxKB == 1);
|
||||
if (backend == "rwdb")
|
||||
{
|
||||
// RWDB reports actual data memory
|
||||
// After adding data, should see increases
|
||||
BEAST_EXPECT(newAllKB == 2);
|
||||
BEAST_EXPECT(newLedgerKB == 0);
|
||||
BEAST_EXPECT(newTxKB == 1);
|
||||
// For RWDB: All = Ledger + Transaction + overhead
|
||||
// So All should be >= Ledger + Transaction
|
||||
BEAST_EXPECT(newAllKB >= newLedgerKB + newTxKB);
|
||||
}
|
||||
else
|
||||
{
|
||||
// SQLite: The values should stay roughly the same or increase
|
||||
// slightly since SQLite reports global memory usage
|
||||
BEAST_EXPECT(newAllKB >= allKB); // Should not decrease
|
||||
BEAST_EXPECT(newLedgerKB >= ledgerKB); // Should not decrease
|
||||
BEAST_EXPECT(newTxKB >= txKB); // Should not decrease
|
||||
}
|
||||
|
||||
// Test space availability
|
||||
// Note: SQLite in standalone mode uses in-memory databases,
|
||||
// so file-based space checks don't apply
|
||||
if (backend == "rwdb")
|
||||
{
|
||||
// RWDB uses actual files, so space checks are valid
|
||||
BEAST_EXPECT(db.ledgerDbHasSpace(env.app().config()));
|
||||
BEAST_EXPECT(db.transactionDbHasSpace(env.app().config()));
|
||||
}
|
||||
// Skip space checks for SQLite as it uses in-memory databases in
|
||||
// standalone mode
|
||||
|
||||
// Test database closure operations (should not throw)
|
||||
try
|
||||
@@ -559,18 +632,20 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
testTransactionMinLedgerSeq()
|
||||
testTransactionMinLedgerSeq(
|
||||
std::string const& backend,
|
||||
std::unique_ptr<Config> config)
|
||||
{
|
||||
testcase("Transaction minimum ledger sequence tracking");
|
||||
testcase("Transaction minimum ledger sequence tracking - " + backend);
|
||||
|
||||
using namespace test::jtx;
|
||||
auto config = envconfig();
|
||||
config->LEDGER_HISTORY = 1000;
|
||||
|
||||
Env env(*this, std::move(config));
|
||||
auto& db = env.app().getRelationalDatabase();
|
||||
|
||||
auto* sqliteDb = dynamic_cast<SQLiteDatabase*>(&db);
|
||||
auto* sqliteDb = getInterface(db);
|
||||
BEAST_EXPECT(sqliteDb != nullptr);
|
||||
if (!sqliteDb)
|
||||
return;
|
||||
|
||||
@@ -610,19 +685,56 @@ public:
|
||||
BEAST_EXPECT(newAcctTxMinSeq == acctTxMinSeq);
|
||||
}
|
||||
|
||||
std::vector<std::string> static getBackends(std::string const& unittest_arg)
|
||||
{
|
||||
// Valid backends
|
||||
static const std::set<std::string> validBackends = {"sqlite", "rwdb"};
|
||||
|
||||
std::set<std::string> backends; // Use set to avoid duplicates
|
||||
std::string argStr =
|
||||
unittest_arg.empty() ? "sqlite,rwdb" : unittest_arg;
|
||||
std::stringstream ss(argStr);
|
||||
std::string backend;
|
||||
|
||||
while (std::getline(ss, backend, ','))
|
||||
{
|
||||
if (!backend.empty())
|
||||
{
|
||||
// Validate backend
|
||||
if (validBackends.contains(backend))
|
||||
{
|
||||
backends.insert(backend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return as vector (sorted due to set)
|
||||
return {backends.begin(), backends.end()};
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testBasicInitialization();
|
||||
testLedgerSequenceOperations();
|
||||
testLedgerInfoOperations();
|
||||
testHashOperations();
|
||||
testTransactionOperations();
|
||||
testAccountTransactionOperations();
|
||||
testAccountTransactionPaging();
|
||||
testDeletionOperations();
|
||||
testDatabaseSpaceOperations();
|
||||
testTransactionMinLedgerSeq();
|
||||
auto backends = getBackends(arg());
|
||||
|
||||
if (backends.empty())
|
||||
{
|
||||
fail("no valid backend specified: '" + arg() + "'");
|
||||
}
|
||||
|
||||
for (auto const& backend : backends)
|
||||
{
|
||||
testBasicInitialization(backend, makeConfig(backend));
|
||||
testLedgerSequenceOperations(backend, makeConfig(backend));
|
||||
testLedgerInfoOperations(backend, makeConfig(backend));
|
||||
testHashOperations(backend, makeConfig(backend));
|
||||
testTransactionOperations(backend, makeConfig(backend));
|
||||
testAccountTransactionOperations(backend, makeConfig(backend));
|
||||
testAccountTransactionPaging(backend, makeConfig(backend));
|
||||
testDeletionOperations(backend, makeConfig(backend));
|
||||
testDatabaseSpaceOperations(backend, makeConfig(backend));
|
||||
testTransactionMinLedgerSeq(backend, makeConfig(backend));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user