diff --git a/src/daemon/detach.rs b/src/daemon/detach.rs index 9ef99f69..d47dc4a1 100644 --- a/src/daemon/detach.rs +++ b/src/daemon/detach.rs @@ -17,7 +17,18 @@ const ALREADY_DETACHED: &str = "NIGHTCROW_DETACHED"; /// Whether this process is the backgrounded copy. pub fn is_detached_child() -> bool { - std::env::var_os(ALREADY_DETACHED).is_some() + marker_says_detached(std::env::var_os(ALREADY_DETACHED).as_deref()) +} + +/// The rule the marker carries, split from reading it. +/// +/// Reading the environment inside the rule made the test answer for the +/// machine it ran on: a suite started from inside a nightcrow pane inherits +/// the marker from the daemon that spawned the pane, and the foreground case +/// then failed while saying nothing about the rule. Presence is what counts — +/// the child is spawned with `"1"`, but an empty value is still a marker. +fn marker_says_detached(marker: Option<&std::ffi::OsStr>) -> bool { + marker.is_some() } /// Re-exec this binary in its own session and return. diff --git a/src/daemon/detach_tests.rs b/src/daemon/detach_tests.rs index 3cd9be79..d157d178 100644 --- a/src/daemon/detach_tests.rs +++ b/src/daemon/detach_tests.rs @@ -1,5 +1,5 @@ -use super::{background_command, child_args, is_detached_child}; -use std::ffi::OsString; +use super::{background_command, child_args, marker_says_detached}; +use std::ffi::{OsStr, OsString}; fn args(list: &[&str]) -> Vec { list.iter().map(OsString::from).collect() @@ -10,9 +10,25 @@ fn args(list: &[&str]) -> Vec { /// hypothetical: it happened, and 46 tests failed while dozens of copies of the /// harness fought over the same machine. The spawn itself is covered by running /// the real thing, not from in here. +/// The marker is passed in rather than read from the environment: a suite run +/// from inside a nightcrow pane inherits it from the daemon that spawned the +/// pane, and asking the environment here would fail on the machine rather than +/// on the rule. #[test] fn a_process_with_no_marker_is_the_foreground_copy() { - assert!(!is_detached_child()); + assert!(!marker_says_detached(None)); +} + +#[test] +fn a_process_carrying_the_marker_is_the_background_copy() { + assert!(marker_says_detached(Some(OsStr::new("1")))); +} + +#[test] +fn the_marker_counts_by_being_set_rather_than_by_its_value() { + // The child is spawned with "1", but nothing downstream reads the value — + // so an empty one must not read as the foreground copy and detach again. + assert!(marker_says_detached(Some(OsStr::new("")))); } #[test]