Skip to content

Commit b298242

Browse files
committed
test: sqlite, add coverage for dangling to-be-reverted db txns
1 parent fc0e747 commit b298242

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/wallet/test/db_tests.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,59 @@ BOOST_AUTO_TEST_CASE(db_availability_after_write_error)
228228
}
229229
}
230230

231+
#ifdef USE_SQLITE
232+
233+
// Test-only statement execution error
234+
constexpr int TEST_SQLITE_ERROR = -999;
235+
236+
class DbExecBlocker : public SQliteExecHandler
237+
{
238+
private:
239+
SQliteExecHandler m_base_exec;
240+
std::set<std::string> m_blocked_statements;
241+
public:
242+
DbExecBlocker(std::set<std::string> blocked_statements) : m_blocked_statements(blocked_statements) {}
243+
int Exec(SQLiteDatabase& database, const std::string& statement) override {
244+
if (m_blocked_statements.contains(statement)) return TEST_SQLITE_ERROR;
245+
return m_base_exec.Exec(database, statement);
246+
}
247+
};
248+
249+
BOOST_AUTO_TEST_CASE(txn_close_failure_dangling_txn)
250+
{
251+
// Verifies that there is no active dangling, to-be-reversed db txn
252+
// after the batch object that initiated it is destroyed.
253+
DatabaseOptions options;
254+
DatabaseStatus status;
255+
bilingual_str error;
256+
std::unique_ptr<SQLiteDatabase> database = MakeSQLiteDatabase(m_path_root / "sqlite", options, status, error);
257+
258+
std::string key = "key";
259+
std::string value = "value";
260+
261+
std::unique_ptr<SQLiteBatch> batch = std::make_unique<SQLiteBatch>(*database);
262+
BOOST_CHECK(batch->TxnBegin());
263+
BOOST_CHECK(batch->Write(key, value));
264+
// Set a handler to prevent txn abortion during destruction.
265+
// Mimicking a db statement execution failure.
266+
batch->SetExecHandler(std::make_unique<DbExecBlocker>(std::set<std::string>{"ROLLBACK TRANSACTION"}));
267+
// Destroy batch
268+
batch.reset();
269+
270+
// Ensure there is no dangling, to-be-reversed db txn
271+
BOOST_CHECK(!database->HasActiveTxn());
272+
273+
// And, just as a sanity check; verify that new batchs only write what they suppose to write
274+
// and nothing else.
275+
std::string key2 = "key2";
276+
std::unique_ptr<SQLiteBatch> batch2 = std::make_unique<SQLiteBatch>(*database);
277+
BOOST_CHECK(batch2->Write(key2, value));
278+
// The first key must not exist
279+
BOOST_CHECK(!batch2->Exists(key));
280+
}
281+
282+
#endif // USE_SQLITE
283+
231284

232285
BOOST_AUTO_TEST_SUITE_END()
233286
} // namespace wallet

0 commit comments

Comments
 (0)