Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/daemon/detach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
22 changes: 19 additions & 3 deletions src/daemon/detach_tests.rs
Original file line number Diff line number Diff line change
@@ -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<OsString> {
list.iter().map(OsString::from).collect()
Expand All @@ -10,9 +10,25 @@ fn args(list: &[&str]) -> Vec<OsString> {
/// 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]
Expand Down