#![cfg(feature = "armour")]
use std::path::Path;
use std::process::Command;
use armdb::armour::Db;
use armdb::{Config, ConstTree, DbError};
use tempfile::tempdir;
const ROOT_ENV: &str = "ARMDB_TEST_LOCK_CHILD_ROOT";
const COLLECTION_ENV: &str = "ARMDB_TEST_LOCK_CHILD_COLLECTION";
fn run_child(test_name: &str, env_key: &str, dir: &Path) {
let exe = std::env::current_exe().expect("current_exe");
let out = Command::new(exe)
.args(["--exact", test_name, "--nocapture"])
.env(env_key, dir)
.output()
.expect("spawn child process");
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
out.status.success(),
"child did not observe the lock (status {:?})\n--- stdout ---\n{stdout}\n--- stderr ---\n{stderr}",
out.status.code(),
);
assert!(
stdout.contains("1 passed"),
"child ran no test — `{test_name}` no longer names a #[test] fn in this binary\
\n--- stdout ---\n{stdout}\n--- stderr ---\n{stderr}",
);
}
#[test]
fn root_lock_holds_across_processes() {
if let Ok(dir) = std::env::var(ROOT_ENV) {
let res = Db::open_test(&dir);
match res {
Ok(_) => panic!("child must not open a root locked by the parent"),
Err(e) => assert!(matches!(e, DbError::Locked { .. }), "got {e:?}"),
}
return;
}
let dir = tempdir().unwrap();
let _held = Db::open_test(dir.path()).expect("parent opens the root");
run_child("root_lock_holds_across_processes", ROOT_ENV, dir.path());
}
#[test]
fn collection_lock_holds_across_processes() {
if let Ok(dir) = std::env::var(COLLECTION_ENV) {
let res = ConstTree::<[u8; 8], 8>::open(&dir, Config::test());
match res {
Ok(_) => panic!("child must not open a collection locked by the parent"),
Err(e) => assert!(matches!(e, DbError::Locked { .. }), "got {e:?}"),
}
return;
}
let dir = tempdir().unwrap();
let _held = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test())
.expect("parent opens the collection");
run_child(
"collection_lock_holds_across_processes",
COLLECTION_ENV,
dir.path(),
);
}