---
name: spt-daemon-lib-test-home-helper
description: spt-daemon lib tests isolate SPT_HOME via crate::test_home::with_home / env_lock (process-mutex serialized); use it for any canonical-path (spt_home-derived) unit test.
metadata:
  type: project
---

`crates/spt-daemon/src/test_home.rs` (`#[cfg(test)] mod test_home;`) provides the SPT_HOME isolation for spt-daemon **lib** unit tests:
- `crate::test_home::with_home(|home: &Path| { ... })` — points SPT_HOME at a fresh tempdir, serialized on a process-global `ENV_LOCK` mutex against every other with_home test in the binary, restored after.
- `crate::test_home::env_lock()` — the raw guard for set-AND-unset env mutation.

**Why:** every spt-daemon fn that resolves the canonical config/perch path (`spt_store::perch::spt_home()` → `DaemonConfig::default_path()`, `adapters_dir()`, etc.) reads the single global SPT_HOME env var; parallel tests race it. This is the sanctioned serialization.

**How to apply:** any unit test exercising a canonical-path API (e.g. `DaemonConfig::upsert_startup_endpoint`, `DaemonConfig::load()`, autostart replay) must run inside `with_home`. Tests that take an EXPLICIT path (`load_from`/`save_to(&temp)`) don't need it. Adding a new field to `DaemonConfig` breaks any full-struct-literal test (e.g. `save_load_roundtrip`) with E0063 — update those literals (or use `..DaemonConfig::default()`); most sibling tests already use `..default()`.

**CAUTION (from operator memory):** never run the unfiltered `spt-daemon --lib` suite on this live host — seedmap/serveprobe/shellwake deadlock when live daemons share the Windows host. Run SCOPED filters only, e.g. `cargo test -p spt-daemon --lib config::` and `... autostart::`, each timeboxed. cargo test accepts only ONE positional filter — run separate invocations, not `config:: autostart::` together.
