docs(plan): make tilde expansion injectable rather than env-mutating

The tilde test set HOME via unsafe std::env::set_var. That is sound under
nextest (process per test) but hazardous under cargo test, and the runner
is not something a unit test should depend on. expand_tilde now takes the
home directory as a parameter; parse_wait_for reads $HOME once and passes
it down.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGntTHCW3sEPy1VBRopNNp
This commit is contained in:
2026-08-07 15:28:49 +02:00
co-authored by Claude Opus 5
parent 73e17d51f3
commit c000a00f05
@@ -77,18 +77,24 @@ fn parses_a_path_condition_with_defaults() {
}
#[test]
fn expands_a_leading_tilde_in_a_path_condition() {
unsafe { std::env::set_var("HOME", "/home/someone") };
let text = "command \"/bin/x\"\nport 1\nwait-for { path \"~/.orbstack/run/docker.sock\" }";
let cfg = parse_server_config("foo", text, p()).unwrap();
fn expands_a_leading_tilde_against_the_given_home() {
let home = PathBuf::from("/home/someone");
assert_eq!(
cfg.wait_for.unwrap().condition,
WaitCondition::Path(PathBuf::from("/home/someone/.orbstack/run/docker.sock"))
expand_tilde("~/.orbstack/run/docker.sock", Some(&home)),
PathBuf::from("/home/someone/.orbstack/run/docker.sock")
);
}
#[test]
fn leaves_non_tilde_paths_and_unknown_home_alone() {
let home = PathBuf::from("/home/someone");
assert_eq!(expand_tilde("/var/run/d.sock", Some(&home)), PathBuf::from("/var/run/d.sock"));
assert_eq!(expand_tilde("~/a", None), PathBuf::from("~/a"));
assert_eq!(expand_tilde("~weird/a", Some(&home)), PathBuf::from("~weird/a"));
}
#[test]
fn parses_a_tcp_condition_with_overrides() {
let text = "command \"/bin/x\"\nport 1\nwait-for { tcp \"127.0.0.1:5432\"\ntimeout \"30s\"\ninterval \"250ms\" }";
@@ -246,13 +252,13 @@ and the field `wait_for,` in the returned `ServerConfig`.
Then add these functions:
```rust
fn expand_tilde(raw: &str) -> PathBuf {
fn expand_tilde(raw: &str, home: Option<&Path>) -> PathBuf {
let Some(rest) = raw.strip_prefix("~/") else {
return PathBuf::from(raw);
};
match std::env::var_os("HOME") {
Some(home) => PathBuf::from(home).join(rest),
match home {
Some(home) => home.join(rest),
None => PathBuf::from(raw),
}
}
@@ -272,6 +278,8 @@ fn parse_wait_for(doc: &KdlDocument, path: &Path) -> Result<Option<WaitForConfig
return Err(invalid("expected a block with exactly one condition".into()));
};
let home = std::env::var_os("HOME").map(PathBuf::from);
let mut conditions: Vec<WaitCondition> = Vec::new();
let mut command: Option<PathBuf> = None;
let mut args: Vec<String> = Vec::new();
@@ -283,7 +291,7 @@ fn parse_wait_for(doc: &KdlDocument, path: &Path) -> Result<Option<WaitForConfig
"path" => {
let raw = string_arg(child, "wait-for", path)?;
conditions.push(WaitCondition::Path(expand_tilde(&raw)));
conditions.push(WaitCondition::Path(expand_tilde(&raw, home.as_deref())));
}
"tcp" => {
let addr = string_arg(child, "wait-for", path)?;