fix(test): anchor all test sandboxes on reclaimable pid-free names

Every hand-rolled test-sandbox helper keyed its directory on
std::process::id() under env::temp_dir(), so the pre-create wipe never
matched a prior run's path: one directory stranded per helper site per
test-binary invocation, >50k dirs / 15.5 GiB on the 16 GiB tmpfs by
2026-07-13.

The remedy extends commit 84e1075's knob-lab pattern to every site:
fixed, tag-keyed, PID-FREE names under the build-tree tmp anchor, each
site keeping its pre-create remove_dir_all — which now genuinely
reclaims the previous run. Integration/bench targets use
env!("CARGO_TARGET_TMPDIR"); src-internal unit-test helpers (cargo sets
that var only for integration/bench targets) derive the same anchor
from env!("CARGO_MANIFEST_DIR") + ../../target/tmp. Residue is bounded
to one directory per site, on disk instead of the tmpfs, per checkout.

One deliberate exception: project_new.rs's tmp() stays under
env::temp_dir() because two of its tests (new_outside_a_work_tree_*)
need a base genuinely detached from any git work tree, and target/
lives inside the checkout's work tree. Its name carries a per-checkout
hash discriminator instead, so concurrently running checkouts (which
share /tmp) cannot race on the fixed name while each run still
reclaims its predecessor.

tempfile-RAII was considered and rejected (issue #258 decision log):
it cannot cover the process-lifetime OnceLock scaffolds (statics never
drop), adds a dependency, and still strands kill-leftovers on the
tmpfs.

Verified: full workspace suite green (incl. the new RED regression
test temp_cwd_sandbox_does_not_leak_under_env_temp_dir), clippy clean,
sandboxes observed under target/tmp with stable names across runs.
Stale pre-fix PID-keyed dirs in /tmp are not swept by this change and
age out only by manual cleanup.

closes #258
This commit is contained in:
2026-07-13 20:15:31 +02:00
parent 05565ee8a2
commit 1ccce9ad32
18 changed files with 100 additions and 45 deletions
+9 -4
View File
@@ -909,8 +909,11 @@ mod tests {
}
fn temp_path(name: &str) -> PathBuf {
// unique per test + per process; no external tempfile dependency
std::env::temp_dir().join(format!("aura-registry-{}-{}.jsonl", std::process::id(), name))
// fixed, tag-keyed, pid-free name under the build-tree tmp anchor (#258):
// no external tempfile dependency, and every call site already wipes
// before use, so the fixed name genuinely reclaims the previous run.
std::path::Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../../target/tmp"))
.join(format!("aura-registry-{name}.jsonl"))
}
#[test]
@@ -1081,8 +1084,10 @@ mod tests {
fn temp_family_dir(name: &str) -> PathBuf {
// a unique per-test directory so the families.jsonl sibling never collides
// across tests sharing the temp dir; the registry binds to runs.jsonl inside.
let dir =
std::env::temp_dir().join(format!("aura-registry-fam-{}-{}", std::process::id(), name));
// Fixed, tag-keyed, pid-free name under the build-tree tmp anchor (#258): the
// pre-create wipe below then genuinely reclaims the previous run.
let dir = std::path::Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../../target/tmp"))
.join(format!("aura-registry-fam-{name}"));
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).expect("create temp family dir");
dir.join("runs.jsonl")
+4 -2
View File
@@ -288,8 +288,10 @@ mod tests {
use aura_core::{Scalar, ScalarKind, Timestamp};
fn temp_traces_root(name: &str) -> PathBuf {
let dir =
std::env::temp_dir().join(format!("aura-tracestore-{}-{}", std::process::id(), name));
// fixed, tag-keyed, pid-free name under the build-tree tmp anchor (#258): the
// pre-create wipe below then genuinely reclaims the previous run.
let dir = std::path::Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../../target/tmp"))
.join(format!("aura-tracestore-{name}"));
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).expect("create temp traces root");
dir
@@ -18,8 +18,8 @@ use aura_registry::{
};
fn temp_dir(name: &str) -> PathBuf {
let dir = std::env::temp_dir()
.join(format!("aura-registry-campaign-e2e-{}-{}", std::process::id(), name));
let dir = std::path::Path::new(env!("CARGO_TARGET_TMPDIR"))
.join(format!("aura-registry-campaign-e2e-{name}"));
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).expect("create temp dir");
dir.join("runs.jsonl")