#[path = "common/harness.rs"]
mod harness;
use harness::TestHarness;
use macrame::graph::EdgeAssertion;
use macrame::metrics::CommandKind;
use macrame::{ConceptUpsert, Database};
const T0: &str = "2026-01-01T00:00:00.000000Z";
const OPEN: &str = "9999-12-31T23:59:59.999999Z";
const T1: &str = "2026-01-01T00:30:00.000000Z";
fn turns_for(snap: ¯ame::metrics::MetricsSnapshot, kind: CommandKind) -> u64 {
snap.kinds.iter().find(|k| k.kind == kind).unwrap().turns
}
#[tokio::test]
async fn every_write_method_is_attributed_to_its_own_command_kind() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
db.upsert_concept(ConceptUpsert::new("a", "A").valid_from(T0))
.await
.unwrap();
db.upsert_concept(ConceptUpsert::new("b", "B").valid_from(T0))
.await
.unwrap();
db.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(T0)
.valid_to(OPEN),
)
.await
.unwrap();
db.retire_edge("a", "b", "KNOWS", T0, "2026-06-01T00:00:00.000000Z")
.await
.unwrap();
db.rebuild_current().await.unwrap();
db.bulk_import(vec![EdgeAssertion::new("a", "b", "CITES")
.valid_from(T0)
.valid_to(OPEN)])
.await
.unwrap();
let snap = db.metrics();
assert_eq!(turns_for(&snap, CommandKind::UpsertConcept), 2);
assert_eq!(turns_for(&snap, CommandKind::AssertEdge), 1);
assert_eq!(turns_for(&snap, CommandKind::RetireEdge), 1);
assert_eq!(turns_for(&snap, CommandKind::RebuildCurrent), 1);
assert_eq!(turns_for(&snap, CommandKind::BulkImportChunk), 1);
assert_eq!(turns_for(&snap, CommandKind::Archive), 0);
let per_kind: u64 = snap.kinds.iter().map(|k| k.turns).sum();
assert_eq!(
per_kind, snap.turns,
"the loop counted {} turns but the kinds account for {per_kind}",
snap.turns
);
db.close().await.unwrap();
}
#[tokio::test]
async fn the_longest_hold_is_a_real_duration_and_names_its_command() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
db.upsert_concept(ConceptUpsert::new("a", "A").valid_from(T0))
.await
.unwrap();
let leaves: Vec<_> = (0..500).map(|i| format!("c{i}")).collect();
db.write_concepts(
leaves
.iter()
.map(|id| ConceptUpsert::new(id, id).valid_from(T0))
.collect(),
)
.await
.unwrap();
let edges: Vec<_> = leaves
.iter()
.map(|id| {
EdgeAssertion::new("a", id, "KNOWS")
.valid_from(T0)
.valid_to(OPEN)
})
.collect();
db.bulk_import(edges).await.unwrap();
db.rebuild_current().await.unwrap();
let snap = db.metrics();
let (kind, held) = snap.longest.expect("some turn took at least a microsecond");
assert!(
held > std::time::Duration::ZERO,
"the timer is not running: longest hold is {held:?}"
);
let rebuild = snap
.kinds
.iter()
.find(|k| k.kind == CommandKind::RebuildCurrent)
.unwrap();
assert!(
held >= rebuild.mean,
"the high-water mark ({held:?}) is below a mean it should dominate \
({:?}) — {kind} was recorded as the longest",
rebuild.mean
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_windowed_archive_takes_one_actor_turn_per_session() {
use std::time::Duration;
let harness = TestHarness::new();
let db = harness.db_with_fake_clock().await;
let ids: Vec<String> = (0..9).map(|i| format!("c{i:03}")).collect();
db.write_concepts(
ids.iter()
.map(|id| ConceptUpsert::new(id, "n").valid_from(T0))
.collect(),
)
.await
.unwrap();
for generation in 0..4 {
let batch: Vec<_> = (0..8)
.map(|k| {
EdgeAssertion::new(&ids[k], &ids[k + 1], "LINKS")
.valid_from(T0)
.valid_to(OPEN)
.weight(1.0 + generation as f64)
})
.collect();
db.bulk_import(batch).await.unwrap();
harness.advance(Duration::from_secs(3_600));
}
let cutoff = harness.clock.peek();
let reports = db
.archive_windowed(&cutoff, Duration::from_secs(3_600))
.await
.unwrap();
assert!(reports.len() > 1, "the fixture produced one window");
let snap = db.metrics();
assert_eq!(
turns_for(&snap, CommandKind::Archive),
reports.len() as u64,
"{} sessions were reported but the actor spent a different number of \
turns on them — the loop is inside the actor, and windowing buys \
nothing",
reports.len()
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_backlog_shows_up_in_the_queue_depth() {
let harness = TestHarness::new();
let db = std::sync::Arc::new(Database::open(&harness.db_path).await.unwrap());
db.upsert_concept(ConceptUpsert::new("a", "A").valid_from(T0))
.await
.unwrap();
db.upsert_concept(ConceptUpsert::new("b", "B").valid_from(T0))
.await
.unwrap();
let mut tasks = Vec::new();
for i in 0..64 {
let db = std::sync::Arc::clone(&db);
tasks.push(tokio::spawn(async move {
db.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(format!("2026-02-{:02}T00:00:00.000000Z", (i % 28) + 1))
.valid_to(format!("2026-03-{:02}T00:00:00.000000Z", (i % 28) + 1)),
)
.await
}));
}
for t in tasks {
let _ = t.await.unwrap();
}
let snap = db.metrics();
assert!(
snap.high_depth_max > 0,
"64 concurrent assertions produced no observed backlog at all — the \
depth is being sampled after the queue drains, not before the turn"
);
std::sync::Arc::into_inner(db)
.unwrap()
.close()
.await
.unwrap();
}
#[test]
fn the_budget_exemptions_and_their_documented_table_agree() {
let source = include_str!("../src/connection.rs");
let table: String = source
.lines()
.skip_while(|l| !l.contains("| Path | Bound | Why it cannot be chunked |"))
.take_while(|l| l.trim_start().starts_with("///") && l.contains('|'))
.collect::<Vec<_>>()
.join("\n");
assert!(
table.lines().count() > 3,
"CHUNK_BUDGET's exemption table has moved, been renamed, or lost its \
rows — {} line(s) matched",
table.lines().count()
);
for kind in CommandKind::ALL {
let named = table.contains(kind.as_str());
assert_eq!(
named,
kind.exempt_from_budget(),
"`{kind}` is {} by `exempt_from_budget` and {} in CHUNK_BUDGET's \
table. The two lists are the same fact written twice and must \
agree — see the exemption's rustdoc for which one is wrong.\n\
table:\n{table}",
if kind.exempt_from_budget() {
"exempt"
} else {
"not exempt"
},
if named { "present" } else { "absent" },
);
}
}
#[tokio::test]
async fn a_rehydrate_is_counted_as_rehydrate_and_not_as_archive() {
let harness = TestHarness::new();
let db = harness.db_with_fake_clock().await;
db.write_concepts(vec![ConceptUpsert::new("c000", "n")
.valid_from(T0)
.valid_to(T1)
.retired(true)])
.await
.unwrap();
harness.advance(std::time::Duration::from_secs(7_200));
let cutoff = harness.clock.peek();
db.archive(&cutoff).await.unwrap();
let before = turns_for(&db.metrics(), CommandKind::Archive);
assert!(before > 0, "the fixture did not archive anything");
db.rehydrate(&["c000"]).await.unwrap();
let snap = db.metrics();
assert_eq!(
turns_for(&snap, CommandKind::Rehydrate),
1,
"the rehydrate took an actor turn that was not attributed to Rehydrate"
);
assert_eq!(
turns_for(&snap, CommandKind::Archive),
before,
"the Archive counter moved on a rehydrate. That is the 0.9.0-0.12.8 \
behaviour W4.3 removed (D-152)."
);
db.close().await.unwrap();
}
#[tokio::test]
async fn the_starvation_counter_distinguishes_a_backlog_from_a_quiet_actor() {
use std::sync::Arc;
let harness = TestHarness::new();
let db = Arc::new(harness.db_with_fake_clock().await);
for i in 0..4 {
db.upsert_concept(ConceptUpsert::new(format!("q{i}"), "n").valid_from(T0))
.await
.unwrap();
}
let quiet = db.metrics();
assert_eq!(
quiet.low_starved_run_max, 0,
"an actor that never had low-priority work queued reported a starvation \
run of {}",
quiet.low_starved_run_max
);
let ids: Vec<String> = (0..40).map(|i| format!("c{i:03}")).collect();
db.write_concepts(
ids.iter()
.map(|id| ConceptUpsert::new(id, "n").valid_from(T0))
.collect(),
)
.await
.unwrap();
let bulk = {
let db = Arc::clone(&db);
let edges: Vec<_> = (0..39)
.map(|k| {
EdgeAssertion::new(&ids[k], &ids[k + 1], "LINKS")
.valid_from(T0)
.valid_to(OPEN)
})
.collect();
tokio::spawn(async move { db.bulk_import(edges).await })
};
let mut hot = Vec::new();
for i in 0..64 {
let db = Arc::clone(&db);
hot.push(tokio::spawn(async move {
db.upsert_concept(ConceptUpsert::new(format!("h{i:03}"), "n").valid_from(T0))
.await
}));
}
for t in hot {
t.await.unwrap().unwrap();
}
bulk.await.unwrap().unwrap();
let snap = db.metrics();
assert!(
snap.low_starved_turns > 0,
"64 concurrent high-priority writes raced a chunked bulk import and the \
actor never once took high-priority work with low-priority work queued. \
Either the biased select is not biased, or the counter is not wired to \
the arm that takes the choice."
);
assert!(
snap.low_starved_run_max > 0 && snap.low_starved_run_max <= snap.low_starved_turns,
"run_max {} is not a run of the {} starved turns — a run cannot exceed \
the total it is drawn from",
snap.low_starved_run_max,
snap.low_starved_turns
);
Arc::into_inner(db).unwrap().close().await.unwrap();
}
#[tokio::test]
async fn a_forced_low_turn_would_be_unbounded_by_contract() {
let harness = TestHarness::new();
let db = Database::open_with_cadence(&harness.db_path, None)
.await
.unwrap();
db.archive("2027-01-01T00:00:00.000000Z").await.unwrap();
assert_eq!(
turns_for(&db.metrics(), CommandKind::Archive),
1,
"`archive()` no longer takes an `Archive` turn, so this test is no \
longer about the low tier"
);
assert!(
CommandKind::Archive.exempt_from_budget(),
"every low-priority kind now states a bound, which is the one thing \
that would make a fairness floor boundable. W10.4 declined the floor \
because a forced low turn admits an arbitrary low command and one of \
them has no latency bound by contract (D-199). Re-read that decision \
rather than deleting this assertion."
);
db.close().await.unwrap();
}
#[tokio::test]
async fn analyze_and_optimize_are_counted_apart() {
let harness = TestHarness::new();
let db = Database::open_with_cadence(&harness.db_path, None)
.await
.unwrap();
db.upsert_concept(ConceptUpsert::new("a", "A").valid_from(T0))
.await
.unwrap();
db.analyze().await.unwrap();
let snap = db.metrics();
assert_eq!(
(
turns_for(&snap, CommandKind::Analyze),
turns_for(&snap, CommandKind::Optimize)
),
(1, 0),
"`analyze()` is not attributed to `Analyze` alone. Either the two kinds are still one, or `LowPriCommand::kind` reads `incremental` backwards (W10.5, D-197)"
);
db.optimize().await.unwrap();
let snap = db.metrics();
assert_eq!(
(
turns_for(&snap, CommandKind::Analyze),
turns_for(&snap, CommandKind::Optimize)
),
(1, 1),
"`optimize()` did not land on `Optimize`, or it moved `Analyze` as well. The point of the split is that `close()`'s automatic call is distinguishable from an explicit one (W10.5, D-197)"
);
db.close().await.unwrap();
let db = Database::open_with_cadence(&harness.db_path, None)
.await
.unwrap();
assert_eq!(
turns_for(&db.metrics(), CommandKind::Optimize),
0,
"a freshly opened handle has already run an optimize; `open()` is not supposed to touch statistics (D-149)"
);
db.close().await.unwrap();
}
#[test]
fn analyze_is_not_budget_exempt_and_that_is_deliberate() {
assert!(
!CommandKind::Analyze.exempt_from_budget(),
"`Analyze` was added to the budget exemptions. The exemption table has \
a `Bound` column and this kind cannot fill it in: the honest entry is \
\"the size of the table, damped 3–4x\", which is the absence of a \
bound rather than one. Every call being a violation is the intended \
reading, not the defect (D-166, D-197)."
);
assert!(
!CommandKind::Optimize.exempt_from_budget(),
"`Optimize` was added to the budget exemptions. It is under budget \
whenever it declines to re-analyse, which is nearly always — so its \
violations are not noise, they are the calls that actually did work \
(10.7 ms cold, 460 ms once the table had grown 25x). Exempting it \
deletes the one signal that distinguishes the two (D-197)."
);
assert!(
!CommandKind::ShadowRebuild.exempt_from_budget(),
"`ShadowRebuild` was exempted. It is the *fill* half — Begin and the \
Fill chunks — and those are meant to fit the budget, so their \
overage is workload-dependent and a violation discriminates. \
Exempting it deletes the only signal that a fill chunk regressed \
(D-082's goal, D-233's mechanism)."
);
assert!(
CommandKind::ShadowSwap.exempt_from_budget(),
"`ShadowSwap` lost its exemption. It exceeds by construction — three \
index builds under the write lock, 46.8 ms against a 3 ms budget \
(D-082), with no healthy state in which it fits — so counting it \
puts a permanent `N(rebuilds)` in `budget_violations()` on every \
database that has ever repaired its projection. That is exactly the \
failure `Rehydrate`'s exemption exists to prevent (W4.3, D-233)."
);
}
#[tokio::test]
async fn a_swap_is_counted_as_shadow_swap_and_not_as_shadow_rebuild() {
use macrame::integrity::{ShadowOutcome, ShadowStep};
let harness = TestHarness::new();
let db = harness.db_with_fake_clock().await;
db.upsert_concept(ConceptUpsert::new("a", "A").valid_from(T0))
.await
.unwrap();
db.upsert_concept(ConceptUpsert::new("b", "B").valid_from(T0))
.await
.unwrap();
db.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(T0)
.valid_to(OPEN),
)
.await
.unwrap();
let fills = |snap: &_| turns_for(snap, CommandKind::ShadowRebuild);
let swaps = |snap: &_| turns_for(snap, CommandKind::ShadowSwap);
let ShadowOutcome::Started { build_start, epoch } =
db.shadow_step(ShadowStep::Begin).await.unwrap()
else {
panic!("Begin returned the wrong outcome")
};
let snap = db.metrics();
assert_eq!(fills(&snap), 1, "Begin is a fill-half turn");
assert_eq!(swaps(&snap), 0, "Begin was counted as a swap");
db.shadow_step(ShadowStep::Fill { after: None })
.await
.unwrap();
let snap = db.metrics();
assert_eq!(
fills(&snap),
2,
"the Fill chunk did not land on ShadowRebuild"
);
assert_eq!(swaps(&snap), 0, "a Fill chunk was counted as a swap");
db.shadow_step(ShadowStep::Swap { build_start, epoch })
.await
.unwrap();
let snap = db.metrics();
assert_eq!(
swaps(&snap),
1,
"the swap took an actor turn that was not attributed to ShadowSwap"
);
assert_eq!(
fills(&snap),
2,
"the ShadowRebuild counter moved on a swap. That is the 0.6.0-0.14.15 \
behaviour D-233 removed: one kind over two hold distributions, whose \
`over_budget` then read `N(rebuilds) + regressions` and could not be \
decomposed."
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_swap_over_budget_is_not_a_violation() {
const KEYS: usize = 3_200;
const GENERATIONS: usize = 4;
let harness = TestHarness::new();
let db = harness.db_with_fake_clock().await;
db.write_concepts(
(0..KEYS)
.map(|i| ConceptUpsert::new(format!("n{i}"), "n").valid_from(T0))
.collect(),
)
.await
.unwrap();
for generation in 0..GENERATIONS {
db.bulk_import(
(0..KEYS)
.map(|i| {
EdgeAssertion::new(format!("n{i}"), format!("n{}", (i + 1) % KEYS), "KNOWS")
.valid_from(T0)
.valid_to(OPEN)
.weight(generation as f64 + 1.0)
})
.collect(),
)
.await
.unwrap();
}
db.rebuild_current_chunked().await.unwrap();
let snap = db.metrics();
let swap = snap
.kinds
.iter()
.find(|k| k.kind == CommandKind::ShadowSwap)
.unwrap();
assert_eq!(swap.turns, 1, "a rebuild is exactly one swap turn");
assert!(
swap.longest > macrame::CHUNK_BUDGET,
"the swap took {:?}, which is inside the {:?} budget, so this test \
asserts nothing about the exemption. Decide which reading applies \
before resizing: if the swap has acquired a smaller unit — upstream \
chunked the index build, or `ALTER INDEX ... RENAME` arrived — the \
exemption has lost its ground and should be removed, not resized \
around. Otherwise this is a faster machine and the fixture is the \
thing to grow. Measured in a debug build, fastest of three: 3.6 ms at \
400 x 4, 12.3 ms at 1,600 x 4, 25.4 ms at 3,200 x 4, against D-082's \
46.8 ms at 10,000 keys. 400 x 4 is what CI's windows runner did in \
2.572 ms (D-239).",
swap.longest,
macrame::CHUNK_BUDGET
);
assert_eq!(
swap.over_budget,
0,
"the swap exceeded the budget by {:?} and was counted as a violation. \
It exceeds on every rebuild — three index builds under the write lock \
— so counting it puts a permanent entry in `budget_violations()` on \
any database that has ever repaired its projection, which is what \
D-233 removed and what `Rehydrate`'s exemption exists to prevent.",
swap.longest.saturating_sub(macrame::CHUNK_BUDGET)
);
assert!(
!snap
.budget_violations()
.iter()
.any(|k| k.kind == CommandKind::ShadowSwap),
"`budget_violations()` named the swap"
);
db.close().await.unwrap();
}