Huginn/crates/mind-body/tests/cli.rs
Meta Vens a50b25c08e mind-body: mind-control takes --root <dir>; the window probe runs in a tempdir
Soul s3: the window probe wrote a window-probe-<pid> instance under the real
/etc/gamecult/minds. A leading --root argv flag (argv, because sudo -E carries
the environment) replaces the default root; the probe points the real binary at
a tempdir, whose drop removes whatever a failed assert leaves. No test names
/etc/gamecult any more; the path-derivation test uses CONTROL_ROOT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:53:27 +02:00

136 lines
6.7 KiB
Rust

//! The `mind-control` command driven end to end through `mind_body::cli::run`
//! against a temporary root, and the binary once as a process for its exit
//! status. Nothing touches `/etc`.
use chrono::{TimeZone, Utc};
use mind_body::cli::{operator_name, run};
fn go(root: &std::path::Path, args: &[&str], set_by: &str, secs: i64) -> (anyhow::Result<()>, String) {
let args: Vec<String> = args.iter().map(|a| a.to_string()).collect();
let mut out = Vec::new();
let now = Utc.timestamp_opt(1_800_000_000 + secs, 0).unwrap();
let result = run(&args, root, set_by, now, &mut out);
(result, String::from_utf8(out).unwrap())
}
#[test]
fn show_reports_every_rung_from_an_absent_store_to_released() {
let root = tempfile::tempdir().unwrap();
let (r, out) = go(root.path(), &["--instance", "eureka", "show"], "op", 0);
r.unwrap();
assert!(out.contains("brake: absent") && out.contains("dial: absent") && out.contains("BrakeAbsent"), "{out}");
go(root.path(), &["--instance", "eureka", "brake", "release"], "alice", 1).0.unwrap();
let (_, out) = go(root.path(), &["--instance", "eureka", "show"], "op", 2);
assert!(out.contains("brake: released") && out.contains("set_by alice") && out.contains("DialAbsent"), "{out}");
go(root.path(), &["--instance", "eureka", "dial", "set", "--heat", "0.5", "--base-cooldown-s", "3600", "--base-run-usd", "5"], "bob", 3)
.0
.unwrap();
let (_, out) = go(root.path(), &["--instance", "eureka", "show"], "op", 4);
assert!(out.contains("heat 0.5") && out.contains("base_cooldown_s 3600") && out.contains("set_by bob"), "{out}");
assert!(out.contains("Released") && out.contains("7200s"), "{out}");
go(root.path(), &["--instance", "eureka", "brake", "hold"], "alice", 5).0.unwrap();
let (_, out) = go(root.path(), &["--instance", "eureka", "show"], "op", 6);
assert!(out.contains("brake: held") && out.contains("BrakeHeld"), "{out}");
}
#[test]
fn instances_do_not_share_a_store() {
let root = tempfile::tempdir().unwrap();
go(root.path(), &["--instance", "one", "brake", "release"], "op", 0).0.unwrap();
let (_, out) = go(root.path(), &["--instance", "two", "show"], "op", 1);
assert!(out.contains("brake: absent"), "{out}");
assert!(root.path().join("one").join("control.cc").exists());
}
#[test]
fn a_dial_set_outside_bounds_refuses_and_leaves_the_store_unchanged() {
let root = tempfile::tempdir().unwrap();
go(root.path(), &["--instance", "eureka", "brake", "release"], "op", 0).0.unwrap();
go(root.path(), &["--instance", "eureka", "dial", "set", "--heat", "1", "--base-cooldown-s", "60", "--base-run-usd", "1"], "op", 1)
.0
.unwrap();
let path = root.path().join("eureka").join("control.cc");
let before = std::fs::read(&path).unwrap();
for heat in ["2.0001", "0.0499", "0", "-1"] {
let (r, _) = go(root.path(), &["--instance", "eureka", "dial", "set", "--heat", heat, "--base-cooldown-s", "60", "--base-run-usd", "1"], "op", 9);
assert!(r.is_err(), "heat {heat} must be refused");
assert_eq!(std::fs::read(&path).unwrap(), before, "heat {heat} changed the store");
}
// A refusal on a store that does not exist yet must not create it.
let fresh = tempfile::tempdir().unwrap();
let (r, _) = go(fresh.path(), &["--instance", "eureka", "dial", "set", "--heat", "5", "--base-cooldown-s", "60", "--base-run-usd", "1"], "op", 0);
assert!(r.is_err());
assert!(!fresh.path().join("eureka").join("control.cc").exists());
}
#[test]
fn malformed_commands_are_refused_and_write_nothing() {
let root = tempfile::tempdir().unwrap();
let bad: &[&[&str]] = &[
&[],
&["show"],
&["--instance", "eureka"],
&["--instance", "eureka", "brake"],
&["--instance", "eureka", "brake", "toggle"],
&["--instance", "eureka", "dial", "set", "--heat", "1"],
&["--instance", "eureka", "dial", "set", "--heat", "1", "--heat", "1", "--base-cooldown-s", "60", "--base-run-usd", "1"],
&["--instance", "eureka", "dial", "set", "--heat", "x", "--base-cooldown-s", "60", "--base-run-usd", "1"],
&["--instance", "eureka", "dial", "set", "--heat", "1", "--base-cooldown-s", "1.5", "--base-run-usd", "1"],
&["--instance", "eureka", "dial", "set", "--heat", "1", "--base-cooldown-s", "60", "--base-run-usd", "1", "--extra", "1"],
&["--instance", "eureka", "dial", "set", "--heat"],
&["--instance", "../evil", "brake", "release"],
&["--instances", "eureka", "brake", "release"],
&["eureka", "eureka", "brake", "release"],
];
for args in bad {
assert!(go(root.path(), args, "op", 0).0.is_err(), "{args:?}");
}
assert_eq!(std::fs::read_dir(root.path()).unwrap().count(), 0, "a refused command wrote something");
}
#[test]
fn the_operator_is_sudo_user_then_user_then_unknown() {
let s = |v: &str| Some(v.to_string());
assert_eq!(operator_name(s("alice"), s("root")), "alice");
assert_eq!(operator_name(None, s("bob")), "bob");
assert_eq!(operator_name(s(""), s("bob")), "bob");
assert_eq!(operator_name(None, s("")), "unknown");
assert_eq!(operator_name(None, None), "unknown");
}
#[test]
fn the_binary_exits_nonzero_with_the_usage_when_refused() {
// A refusal before any path is derived, so this never reaches /etc.
let output = std::process::Command::new(env!("CARGO_BIN_EXE_mind-control")).output().unwrap();
assert_eq!(output.status.code(), Some(2));
assert!(String::from_utf8_lossy(&output.stderr).contains("usage: mind-control"));
assert!(output.stdout.is_empty());
}
#[test]
fn a_leading_root_flag_replaces_the_default_root() {
let default = tempfile::tempdir().unwrap();
let chosen = tempfile::tempdir().unwrap();
let chosen_arg = chosen.path().to_str().unwrap();
let (result, _) = go(default.path(), &["--root", chosen_arg, "--instance", "eureka", "brake", "release"], "op", 0);
result.unwrap();
assert!(chosen.path().join("eureka").join("control.cc").exists(), "the write went to the chosen root");
assert_eq!(std::fs::read_dir(default.path()).unwrap().count(), 0, "the default root was not touched");
// Without the flag the default applies.
go(default.path(), &["--instance", "eureka", "brake", "release"], "op", 1).0.unwrap();
assert!(default.path().join("eureka").join("control.cc").exists());
}
#[test]
fn a_root_flag_without_a_directory_or_an_instance_is_refused_and_writes_nothing() {
let default = tempfile::tempdir().unwrap();
for args in [&["--root"][..], &["--root", "/nonexistent-root-for-test"][..]] {
assert!(go(default.path(), args, "op", 0).0.is_err(), "{args:?}");
}
assert_eq!(std::fs::read_dir(default.path()).unwrap().count(), 0);
assert!(!std::path::Path::new("/nonexistent-root-for-test").exists());
}