diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h index c34597e60be..f467996dc56 100644 --- a/src/wallet/sqlite.h +++ b/src/wallet/sqlite.h @@ -75,6 +75,7 @@ private: void SetupSQLStatements(); bool ExecStatement(sqlite3_stmt* stmt, std::span blob); +protected: bool ReadKey(DataStream&& key, DataStream& value) override; bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override; bool EraseKey(DataStream&& key) override; diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp index 9c101d7ec02..c799721cfb4 100644 --- a/src/wallet/test/util.cpp +++ b/src/wallet/test/util.cpp @@ -108,9 +108,9 @@ std::unique_ptr DuplicateMockDatabase(WalletDatabase& database) std::unique_ptr batch_orig = database.MakeBatch(); std::unique_ptr cursor_orig = batch_orig->GetNewCursor(); - std::unique_ptr new_db = std::make_unique(); + std::unique_ptr new_db = CreateMockableWalletDatabase(); std::unique_ptr new_db_batch = new_db->MakeBatch(); - MockableBatch* batch_new = dynamic_cast(new_db_batch.get()); + MockableSQLiteBatch* batch_new = dynamic_cast(new_db_batch.get()); Assert(batch_new); while (true) { @@ -135,103 +135,13 @@ CTxDestination getNewDestination(CWallet& w, OutputType output_type) return *Assert(w.GetNewDestination(output_type, "")); } -MockableCursor::MockableCursor(const MockableData& records, bool pass, std::span prefix) -{ - m_pass = pass; - std::tie(m_cursor, m_cursor_end) = records.equal_range(BytePrefix{prefix}); -} - -DatabaseCursor::Status MockableCursor::Next(DataStream& key, DataStream& value) -{ - if (!m_pass) { - return Status::FAIL; - } - if (m_cursor == m_cursor_end) { - return Status::DONE; - } - key.clear(); - value.clear(); - const auto& [key_data, value_data] = *m_cursor; - key.write(key_data); - value.write(value_data); - m_cursor++; - return Status::MORE; -} - -bool MockableBatch::ReadKey(DataStream&& key, DataStream& value) -{ - if (!m_pass) { - return false; - } - SerializeData key_data{key.begin(), key.end()}; - const auto& it = m_records.find(key_data); - if (it == m_records.end()) { - return false; - } - value.clear(); - value.write(it->second); - return true; -} - -bool MockableBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite) -{ - if (!m_pass) { - return false; - } - SerializeData key_data{key.begin(), key.end()}; - SerializeData value_data{value.begin(), value.end()}; - auto [it, inserted] = m_records.emplace(key_data, value_data); - if (!inserted && overwrite) { // Overwrite if requested - it->second = value_data; - inserted = true; - } - return inserted; -} - -bool MockableBatch::EraseKey(DataStream&& key) -{ - if (!m_pass) { - return false; - } - SerializeData key_data{key.begin(), key.end()}; - m_records.erase(key_data); - return true; -} - -bool MockableBatch::HasKey(DataStream&& key) -{ - if (!m_pass) { - return false; - } - SerializeData key_data{key.begin(), key.end()}; - return m_records.contains(key_data); -} - -bool MockableBatch::ErasePrefix(std::span prefix) -{ - if (!m_pass) { - return false; - } - auto it = m_records.begin(); - while (it != m_records.end()) { - auto& key = it->first; - if (key.size() < prefix.size() || std::search(key.begin(), key.end(), prefix.begin(), prefix.end()) != key.begin()) { - it++; - continue; - } - it = m_records.erase(it); - } - return true; -} +MockableSQLiteDatabase::MockableSQLiteDatabase() + : SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), /*mock=*/true) +{} std::unique_ptr CreateMockableWalletDatabase() { - return std::make_unique(); -} - -MockableDatabase& GetMockableDatabase(CWallet& wallet) -{ - return dynamic_cast(wallet.GetDatabase()); + return std::make_unique(); } wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success) diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h index f812b0ccfaf..fbc5188fc14 100644 --- a/src/wallet/test/util.h +++ b/src/wallet/test/util.h @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -48,76 +49,31 @@ CTxDestination getNewDestination(CWallet& w, OutputType output_type); using MockableData = std::map>; -class MockableCursor: public DatabaseCursor + +class MockableSQLiteBatch : public SQLiteBatch { public: - MockableData::const_iterator m_cursor; - MockableData::const_iterator m_cursor_end; - bool m_pass; - - explicit MockableCursor(const MockableData& records, bool pass) : m_cursor(records.begin()), m_cursor_end(records.end()), m_pass(pass) {} - MockableCursor(const MockableData& records, bool pass, std::span prefix); - ~MockableCursor() = default; - - Status Next(DataStream& key, DataStream& value) override; -}; - -class MockableBatch : public DatabaseBatch -{ -private: - MockableData& m_records; - bool m_pass; - -public: - explicit MockableBatch(MockableData& records, bool pass) : m_records(records), m_pass(pass) {} - ~MockableBatch() = default; - - void Close() override {} - - bool ReadKey(DataStream&& key, DataStream& value) override; - bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite=true) override; - bool EraseKey(DataStream&& key) override; - bool HasKey(DataStream&& key) override; - bool ErasePrefix(std::span prefix) override; - - std::unique_ptr GetNewCursor() override - { - return std::make_unique(m_records, m_pass); - } - std::unique_ptr GetNewPrefixCursor(std::span prefix) override { - return std::make_unique(m_records, m_pass, prefix); - } - bool TxnBegin() override { return m_pass; } - bool TxnCommit() override { return m_pass; } - bool TxnAbort() override { return m_pass; } - bool HasActiveTxn() override { return false; } + using SQLiteBatch::SQLiteBatch; + using SQLiteBatch::WriteKey; }; /** A WalletDatabase whose contents and return values can be modified as needed for testing **/ -class MockableDatabase : public WalletDatabase +class MockableSQLiteDatabase : public SQLiteDatabase { public: - MockableData m_records; - bool m_pass{true}; + MockableSQLiteDatabase(); - MockableDatabase() : WalletDatabase() {} - ~MockableDatabase() = default; - - void Open() override {} - - bool Rewrite() override { return m_pass; } - bool Backup(const std::string& strDest) const override { return m_pass; } - void Close() override {} + bool Backup(const std::string& strDest) const override { return true; } std::string Filename() override { return "mockable"; } std::vector Files() override { return {}; } - std::string Format() override { return "mock"; } - std::unique_ptr MakeBatch() override { return std::make_unique(m_records, m_pass); } + std::string Format() override { return "sqlite-mock"; } + std::unique_ptr MakeBatch() override { return std::make_unique(*this); } }; std::unique_ptr CreateMockableWalletDatabase(); -MockableDatabase& GetMockableDatabase(CWallet& wallet); +MockableSQLiteDatabase& GetMockableDatabase(CWallet& wallet); DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, bool success); } // namespace wallet diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3724c3f2b3d..027f1d40432 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3521,7 +3521,7 @@ void CWallet::SetupLegacyScriptPubKeyMan() return; } - Assert(m_database->Format() == "bdb_ro" || m_database->Format() == "mock"); + Assert(m_database->Format() == "bdb_ro" || m_database->Format() == "sqlite-mock"); std::unique_ptr spk_manager = std::make_unique(*this); for (const auto& type : LEGACY_OUTPUT_TYPES) {