diff --git a/crates/headroom-core/tests/ccr_backends.rs b/crates/headroom-core/tests/ccr_backends.rs index 5730b0cae..5530da157 100644 --- a/crates/headroom-core/tests/ccr_backends.rs +++ b/crates/headroom-core/tests/ccr_backends.rs @@ -241,6 +241,14 @@ fn sqlite_get_refreshes_idle_ttl() { #[test] fn sqlite_max_lifetime_caps_sliding_window() { + // Timing note: the backend stores unix-SECONDS (`as_secs()` truncates) + // and purges on `last_accessed + ttl <= now`, so apparent elapsed time + // is `floor(t0 + s) - floor(t0)` — it rounds UP by nearly a second + // depending on where t0 lands within its second. Every margin here is + // therefore kept a full second clear of the boundary in both + // directions; a sub-second margin makes this test phase-dependent + // (the previous 1.5s-against-a-2s-window "still alive" assertion + // failed ~70% of runs whenever `frac(t0) >= 0.5`). let dir = tempfile::tempdir().expect("tempdir"); let path = dir.path().join("ccr.sqlite"); // Idle 2s with a 3s ceiling: constant access must not outlive t+3s. @@ -248,14 +256,22 @@ fn sqlite_max_lifetime_caps_sliding_window() { SqliteCcrStore::open_with_ttls(&path, 2, 3).expect("open sqlite store with ceiling"); let hash = compute_key(b"capped sqlite"); store.put(&hash, "capped sqlite"); - std::thread::sleep(Duration::from_millis(1_500)); + // 0.5s: apparent elapsed is 0s or 1s — always under the 2s window. + std::thread::sleep(Duration::from_millis(500)); assert_eq!( store.get(&hash).as_deref(), Some("capped sqlite"), "entry inside idle window and ceiling must hit" ); - // Keep touching, but cross the 3s ceiling. - std::thread::sleep(Duration::from_millis(2_600)); + // Keep touching, but cross the 3s ceiling. The touches must stay INSIDE + // the idle window or the entry dies of idleness and the assertion below + // passes without ever exercising the ceiling — the thing under test. + // 0.7s gaps read as at most 1s apparent, comfortably under the 2s idle + // window, while the 4 of them carry total age past 3s. + for _ in 0..4 { + std::thread::sleep(Duration::from_millis(700)); + let _ = store.get(&hash); + } assert_eq!( store.get(&hash), None,