Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/nornir-testmatrix/tests/arm_run.rs

//! **`run_arm` runs a declared arm and records the REAL per-test verdict.**
//!
//! `verify_arm` (the build-target check) proves an arm COMPILES and lists tests;
//! `run_arm` (the test-target run) is the last mile — it EXECUTES the arm's
//! feature set and reports PASS/FAIL. This test proves, RED before green (LAW 2),
//! that it reports each real outcome and never the `0 tests ... ok` silent green:
//!
//!  * a passing arm → GREEN, real passed count;
//!  * an arm whose file has a FAILING test → not green, `failed() >= 1` (the
//!    proof a broken test in the matrix is not swallowed);
//!  * a dark baseline (the gate's feature OFF) → 0 cases, and `green()` is FALSE
//!    because an arm that rescued nothing is not a pass;
//!  * an arm that does not compile (bogus feature) → `compiled_and_ran == false`
//!    and `green()` FALSE — a compile failure is caught, not read as empty-green.
//!
//! One test fn, run sequentially, so the process-global arm target-dir env is set
//! once with no cross-thread race, and the tiny fixture compiles once and is
//! reused across the four arms.

use std::path::PathBuf;

use nornir_testmatrix::{run_arm, status, MatrixArm};

fn fixture_dir() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests").join("fixtures").join("arm_run_probe")
}

#[test]
fn run_arm_records_pass_fail_dark_and_compile_failure() {
    let dir = fixture_dir();

    // Keep the per-arm build OUT of the source tree and off the tight md1 root:
    // a unique scratch target dir this run owns. `run_arm` reads it via
    // `arm_target_dir` (NORNIR_ARM_TARGET_DIR takes precedence).
    let target = std::env::temp_dir().join(format!(
        "nornir-testmatrix-arm-run-{}",
        nornir_testmatrix::new_run_id()
    ));
    // SAFETY: single-threaded — this is the only test fn in this binary.
    unsafe { std::env::set_var("NORNIR_ARM_TARGET_DIR", &target) };

    // ── RED baseline: the gated file is DARK under default, so an arm that does
    // not turn its feature on runs zero of its tests — and that is NOT green. ──
    let dark = MatrixArm::features::<[&str; 0], &str>([])
        .package("arm_run_probe")
        .test("good_gate");
    let dark = run_arm(&dir, &dark).expect("arm runs");
    assert!(
        dark.compiled_and_ran,
        "an empty-but-compiling arm still exits 0: {}",
        dark.run.cases.len()
    );
    assert_eq!(dark.ran(), 0, "good_gate is dark without --features good: {:?}", dark.run.cases);
    assert!(!dark.green(), "an arm that ran zero tests rescued nothing — not green");

    // ── GREEN: the arm turns the feature on → the two passing tests run. ──
    let good = MatrixArm::features(["good"]).package("arm_run_probe").test("good_gate");
    let good = run_arm(&dir, &good).expect("arm runs");
    assert!(good.compiled_and_ran, "the good arm compiles and runs");
    assert_eq!(good.ran(), 2, "good_gate has two tests: {:?}", good.run.cases);
    assert_eq!(good.passed(), 2, "both pass");
    assert_eq!(good.failed(), 0, "none fail");
    assert!(good.green(), "a two-passing-test arm is green");

    // ── RED, the load-bearing one: a FAILING test in the arm reports FAIL, it is
    // NOT swallowed as a silent green. ──
    let bad = MatrixArm::features(["bad"]).package("arm_run_probe").test("bad_gate");
    let bad = run_arm(&dir, &bad).expect("arm runs");
    assert_eq!(bad.ran(), 2, "bad_gate has two tests: {:?}", bad.run.cases);
    assert_eq!(bad.passed(), 1, "one passes");
    assert_eq!(bad.failed(), 1, "one fails — the matrix SEES it");
    assert!(!bad.green(), "an arm with a failing test is RED, not silent-green");
    assert!(
        bad.run.cases.iter().any(|c| c.status == status::FAIL && c.name.contains("bad_fails")),
        "the failing case is named in the rows: {:?}",
        bad.run.cases
    );

    // ── RED: an arm that does not compile (a feature that does not exist) is
    // caught as a compile failure, never read as an empty green. ──
    let broken = MatrixArm::features(["no_such_feature_zz"]).package("arm_run_probe");
    let broken = run_arm(&dir, &broken).expect("arm runs (cargo exits non-zero, no panic)");
    assert!(
        !broken.compiled_and_ran,
        "a bogus-feature arm does NOT compile — exit is non-zero"
    );
    assert!(!broken.green(), "a non-compiling arm is never green");

    // Cleanup: drop the scratch target dir (best-effort).
    let _ = std::fs::remove_dir_all(&target);
    unsafe { std::env::remove_var("NORNIR_ARM_TARGET_DIR") };
}