yams/tests/unit/storage/sqlite_retry_catch2_test.cpp
Trevon 4228a0c5e9
chore: housekeeping — rm dead code, consolidate MCP tools, add tests, clean docs (#50)
* implemented stubbed IGraphContextService methods

* feat: wire graph communication updates in ipc, mcp and cli

* fix: fix call graph recall and add profiling coverage to graph calls sites

* fix: fixes for work where we added agent navigation to graph tooling

* fix(corpus): clean FTS and KG orphans on document delete

* fix(repair): clean orphans, honor cancellation, surface stats

* fix(rm): order content removal before metadata/KG delete. keep manifest while content is still referenced

* fix(daemon): seed built-in content extractor for readiness

* chore(cli): remove dead stubs and unwired helpers

* feat(search): named-collection scoping + provable relevance gate

* fix(refactor): rm dead stubs, inline simd, add proto/metrics tests

* chore: rm dead interfaces/enums, consolidate guards, add tests

* refactor: rm dr vaporware, collapse download handlers, clean list flags

* docs: rm stale testing investigation logs

* fix: address Copilot review findings from PR #50

- relationship_ops: return existing id when INSERT OR IGNORE skips
- document_crud_ops: propagate FTS5 cleanup error (was silent skip)
- builtin_text_content_extractor: unsigned char cast for tolower, add cctype
- mcp_server download_jobs: validate job_id for status/cancel actions
- list_command tests: unsigned char cast for isspace, add cctype include
2026-06-16 19:37:24 -04:00

81 lines
3.2 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include <yams/storage/sqlite_retry.h>
#include <sqlite3.h>
#include <chrono>
#include <string_view>
TEST_CASE("SQLite retry policy classifies transient lock failures", "[storage][sqlite][retry]") {
using namespace yams::storage::sqlite_retry;
CHECK(isBusyOrLocked(SQLITE_BUSY));
CHECK(isBusyOrLocked(SQLITE_LOCKED));
CHECK_FALSE(isBusyOrLocked(SQLITE_CONSTRAINT));
CHECK_FALSE(isBusyOrLocked(SQLITE_OK));
CHECK(isBusyOrLockedMessage("database is locked"));
CHECK(isBusyOrLockedMessage("SQLITE_BUSY: writer busy"));
CHECK_FALSE(isBusyOrLockedMessage("constraint failed"));
}
TEST_CASE("SQLite retry policy only retries FOREIGN KEY constraint failures",
"[storage][sqlite][retry]") {
using namespace yams::storage::sqlite_retry;
CHECK(isTransientConstraintMessage("FOREIGN KEY constraint failed"));
CHECK(isTransientConstraintMessage(
"Failed to execute statement: FOREIGN KEY constraint failed [SQL: INSERT ...]"));
CHECK_FALSE(isTransientConstraintMessage("UNIQUE constraint failed: documents.sha256_hash"));
CHECK_FALSE(isTransientConstraintMessage("NOT NULL constraint failed: documents.id"));
CHECK_FALSE(isTransientConstraintMessage("CHECK constraint failed: positive_size"));
CHECK_FALSE(isTransientConstraintMessage("constraint failed"));
CHECK_FALSE(isTransientConstraintMessage("database is locked"));
}
TEST_CASE("SQLite retry policy bounds exponential retry attempts", "[storage][sqlite][retry]") {
using namespace yams::storage::sqlite_retry;
const BusyRetryPolicy policy{3, std::chrono::milliseconds{7}};
CHECK(canRetry(SQLITE_BUSY, 0, policy));
CHECK(canRetry(SQLITE_LOCKED, 1, policy));
CHECK_FALSE(canRetry(SQLITE_BUSY, 2, policy));
CHECK_FALSE(canRetry(SQLITE_CONSTRAINT, 0, policy));
#if YAMS_LIBSQL_BACKEND
CHECK((metadataStatementPolicy().maxRetries == 2));
CHECK((vectorWritePolicy().maxRetries == 3));
#else
CHECK((metadataStatementPolicy().maxRetries == 3));
CHECK((vectorWritePolicy().maxRetries == 5));
#endif
}
TEST_CASE("SQLite retry policy tunes document update metadata bursts", "[storage][sqlite][retry]") {
using namespace yams::storage::sqlite_retry;
const auto readPolicy = metadataRepositoryQueryRetryPolicy("read", "client_search");
CHECK((readPolicy.maxRetries == 3));
CHECK((readPolicy.baseDelayMs == 25));
CHECK((readPolicy.maxDelayMs == 500));
const auto defaultWritePolicy =
metadataRepositoryQueryRetryPolicy("write", "bench_set_metadata_batch");
CHECK((defaultWritePolicy.maxRetries == 5));
CHECK((defaultWritePolicy.baseDelayMs == 25));
CHECK((defaultWritePolicy.maxDelayMs == 500));
const auto documentUpdatePolicy =
metadataRepositoryQueryRetryPolicy("write", "app_document_update_metadata");
CHECK((documentUpdatePolicy.maxRetries == 7));
CHECK((documentUpdatePolicy.baseDelayMs == 10));
CHECK((documentUpdatePolicy.maxDelayMs == 200));
const auto downloadMetadataPolicy =
metadataRepositoryQueryRetryPolicy("write", "app_download_metadata_burst");
CHECK((downloadMetadataPolicy.maxRetries == 2));
CHECK((downloadMetadataPolicy.baseDelayMs == 5));
CHECK((downloadMetadataPolicy.maxDelayMs == 10));
}