crates/nornir-bench/src/bin/nornir-bench-redprobe.rs
//! A two-arm bench binary that exists for exactly one reason: to be **watched
//! failing**.
//!
//! `nornir-bench`'s central claim after 2026-08-06 is that a bench run with a red
//! arm exits non-zero (see [`nornir_bench::api::verdict`]). That claim is about a
//! **process exit status**, and no in-process unit test can assert one: a test that
//! calls `verdict` and checks the `Err` proves the value, not the status the shell
//! reads. The gap between those two is precisely where the old defect lived —
//! `"passed": false` was in the JSON the whole time, correctly, and the process
//! still exited 0.
//!
//! So: a real binary, run as a real subprocess, whose arms are steered by the
//! environment. `tests/failed_arm_exits_nonzero.rs` runs it both ways and asserts
//! the exit code and the stdout it left behind.
//!
//! ```text
//! cargo run -p nornir-bench --bin nornir-bench-redprobe ; echo $? # 0
//! NORNIR_BENCH_REDPROBE=red cargo run -p nornir-bench \
//! --bin nornir-bench-redprobe ; echo $? # 1
//! ```
//!
//! Both runs print the same shape of JSON envelope on stdout. Only the exit status
//! and the `passed` fields differ — which is the whole point: a red run must stay
//! **readable**, so nothing that parses the envelope loses its evidence when the
//! process starts failing honestly.
use anyhow::{bail, Result};
use nornir_bench::api::Bencher;
use nornir_bench::BenchResult;
/// Which arms this run should fail, from `NORNIR_BENCH_REDPROBE`:
/// unset/empty ⇒ none, `red` ⇒ the arm named `.red`, `all` ⇒ both.
fn mode() -> String {
std::env::var("NORNIR_BENCH_REDPROBE").unwrap_or_default()
}
struct Arm(&'static str);
impl Bencher for Arm {
fn id(&self) -> &'static str {
self.0
}
fn run(&self) -> Result<BenchResult> {
let m = mode();
let fail = m == "all" || (m == "red" && self.0.ends_with(".red"));
if fail {
bail!(
"redprobe: `{}` was told to fail by NORNIR_BENCH_REDPROBE={m}",
self.0
);
}
let mut metrics = serde_json::Map::new();
metrics.insert("probe".into(), serde_json::json!(1));
Ok(BenchResult::measured(self.0, metrics))
}
}
nornir_bench::register_bench!(Arm("redprobe.green"));
nornir_bench::register_bench!(Arm("redprobe.red"));
fn main() -> Result<()> {
// Keep the envelope attributable but off every real host row: this binary
// must never be mistaken for a measurement.
if std::env::var_os("NORNIR_MACHINE").is_none() {
// SAFETY: single-threaded, before any bench arm has started.
unsafe { std::env::set_var("NORNIR_MACHINE", "redprobe") };
}
nornir_bench::api::run_main_json()
}