#![allow(clippy::expect_used, clippy::unwrap_used)]
use std::time::{SystemTime, UNIX_EPOCH};
use chio_kernel::ExecutionNonceStore;
use chio_store_sqlite::SqliteExecutionNonceStore;
fn unique_db_path(prefix: &str) -> std::path::PathBuf {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time before epoch")
.as_nanos();
std::env::temp_dir().join(format!("{prefix}-{nonce}.sqlite3"))
}
#[test]
fn fresh_nonce_is_reserved() {
let store = SqliteExecutionNonceStore::open_in_memory().unwrap();
assert!(store.reserve("nonce-a").unwrap());
}
#[test]
fn replayed_nonce_is_rejected_within_retention() {
let store = SqliteExecutionNonceStore::open_in_memory().unwrap();
let now = 1_000_000;
let expires_at = now + 60;
assert!(store.try_reserve("nonce-b", now, expires_at).unwrap());
assert!(!store.try_reserve("nonce-b", now + 1, expires_at).unwrap());
}
#[test]
fn expired_row_is_pruned_and_slot_becomes_free() {
let store = SqliteExecutionNonceStore::open_in_memory().unwrap();
assert!(store.try_reserve("nonce-c", 1_000, 1_010).unwrap());
assert!(store.try_reserve("nonce-c", 2_000, 2_060).unwrap());
}
#[test]
fn persists_consumed_marker_across_reopen() {
let path = unique_db_path("chio-exec-nonce-persist");
{
let store = SqliteExecutionNonceStore::open(&path).unwrap();
assert!(store
.try_reserve("persistent-id", 1_000, 10_000_000_000)
.unwrap());
}
let reopened = SqliteExecutionNonceStore::open(&path).unwrap();
assert!(!reopened
.try_reserve("persistent-id", 1_001, 10_000_000_000)
.unwrap());
let _ = std::fs::remove_file(path);
}
#[test]
fn distinct_ids_each_succeed() {
let store = SqliteExecutionNonceStore::open_in_memory().unwrap();
assert!(store.reserve("a").unwrap());
assert!(store.reserve("b").unwrap());
assert!(store.reserve("c").unwrap());
assert!(!store.reserve("a").unwrap());
assert!(!store.reserve("b").unwrap());
}
#[test]
fn trait_reserve_uses_wall_clock_now() {
let store = SqliteExecutionNonceStore::open_in_memory().unwrap();
assert!(
<SqliteExecutionNonceStore as ExecutionNonceStore>::reserve(&store, "trait-path").unwrap()
);
}