aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/test/db_tests.cpp
diff options
context:
space:
mode:
authorfurszy <matiasfurszyfer@protonmail.com>2024-01-08 11:19:25 -0300
committerfurszy <matiasfurszyfer@protonmail.com>2024-01-30 17:27:36 -0300
commitb298242c8d495c36072415e1b95eaa7bf485a38a (patch)
tree97e2c2104962da68074620af87c7fb24792e9dc3 /src/wallet/test/db_tests.cpp
parentfc0e747192e98e779c5f31f2df808f62b3fdd071 (diff)
test: sqlite, add coverage for dangling to-be-reverted db txns
Diffstat (limited to 'src/wallet/test/db_tests.cpp')
-rw-r--r--src/wallet/test/db_tests.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index c6b2154efd..7e6219378f 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -228,6 +228,59 @@ BOOST_AUTO_TEST_CASE(db_availability_after_write_error)
}
}
+#ifdef USE_SQLITE
+
+// Test-only statement execution error
+constexpr int TEST_SQLITE_ERROR = -999;
+
+class DbExecBlocker : public SQliteExecHandler
+{
+private:
+ SQliteExecHandler m_base_exec;
+ std::set<std::string> m_blocked_statements;
+public:
+ DbExecBlocker(std::set<std::string> blocked_statements) : m_blocked_statements(blocked_statements) {}
+ int Exec(SQLiteDatabase& database, const std::string& statement) override {
+ if (m_blocked_statements.contains(statement)) return TEST_SQLITE_ERROR;
+ return m_base_exec.Exec(database, statement);
+ }
+};
+
+BOOST_AUTO_TEST_CASE(txn_close_failure_dangling_txn)
+{
+ // Verifies that there is no active dangling, to-be-reversed db txn
+ // after the batch object that initiated it is destroyed.
+ DatabaseOptions options;
+ DatabaseStatus status;
+ bilingual_str error;
+ std::unique_ptr<SQLiteDatabase> database = MakeSQLiteDatabase(m_path_root / "sqlite", options, status, error);
+
+ std::string key = "key";
+ std::string value = "value";
+
+ std::unique_ptr<SQLiteBatch> batch = std::make_unique<SQLiteBatch>(*database);
+ BOOST_CHECK(batch->TxnBegin());
+ BOOST_CHECK(batch->Write(key, value));
+ // Set a handler to prevent txn abortion during destruction.
+ // Mimicking a db statement execution failure.
+ batch->SetExecHandler(std::make_unique<DbExecBlocker>(std::set<std::string>{"ROLLBACK TRANSACTION"}));
+ // Destroy batch
+ batch.reset();
+
+ // Ensure there is no dangling, to-be-reversed db txn
+ BOOST_CHECK(!database->HasActiveTxn());
+
+ // And, just as a sanity check; verify that new batchs only write what they suppose to write
+ // and nothing else.
+ std::string key2 = "key2";
+ std::unique_ptr<SQLiteBatch> batch2 = std::make_unique<SQLiteBatch>(*database);
+ BOOST_CHECK(batch2->Write(key2, value));
+ // The first key must not exist
+ BOOST_CHECK(!batch2->Exists(key));
+}
+
+#endif // USE_SQLITE
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet