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

nordisk/holger

holger-cli/tests/b1_prepare_has_no_default_verdict.rs

//! B1, the producer half: `holger-cli bundle prepare` has no default verdict.
//!
//! Before the fix `--verdict` defaulted to "pass", so a candidate nobody reviewed
//! was recorded as passed. Now the operator must state the verdict, and a
//! candidate prepared without one is never written.

use std::process::Command;

const BIN: &str = env!("CARGO_BIN_EXE_holger-cli");

fn prepare(dir: &std::path::Path, verdict: Option<&str>) -> std::process::Output {
    let payload = dir.join("fw.bin");
    std::fs::write(&payload, b"firmware").unwrap();
    let mut cmd = Command::new(BIN);
    cmd.args(["bundle", "prepare"])
        .arg("--candidate")
        .arg(dir.join("cand"))
        .args(["--bundle-id", "b-1", "--sequence", "1"])
        .args([
            "--supplier",
            "ACME",
            "--product",
            "Drive",
            "--release-version",
            "1.0.0",
        ])
        .arg("--payload")
        .arg(&payload);
    if let Some(v) = verdict {
        cmd.args(["--verdict", v]);
    }
    cmd.output().unwrap()
}

#[test]
fn prepare_without_a_verdict_is_refused_and_writes_nothing() {
    let dir = tempfile_dir();
    let out = prepare(&dir, None);
    let err = String::from_utf8_lossy(&out.stderr);
    assert!(
        !out.status.success(),
        "prepare must not invent a verdict; it succeeded:\n{err}"
    );
    assert!(
        err.contains("--verdict"),
        "the refusal must name --verdict:\n{err}"
    );
    assert!(
        !dir.join("cand").exists(),
        "a refused prepare wrote a candidate"
    );
}

#[test]
fn prepare_with_a_stated_verdict_records_it() {
    let dir = tempfile_dir();
    let out = prepare(&dir, Some("block"));
    assert!(
        out.status.success(),
        "{}",
        String::from_utf8_lossy(&out.stderr)
    );
    let core = std::fs::read_to_string(dir.join("cand").join("core.json")).unwrap();
    assert!(
        core.contains("\"verdict\": \"block\"") || core.contains("\"verdict\":\"block\""),
        "{core}"
    );
}

/// A fresh directory under the target dir (no tempfile dev-dependency here).
fn tempfile_dir() -> std::path::PathBuf {
    use std::sync::atomic::{AtomicU32, Ordering};
    static N: AtomicU32 = AtomicU32::new(0);
    let d = std::env::temp_dir().join(format!(
        "holger-b1-{}-{}",
        std::process::id(),
        N.fetch_add(1, Ordering::SeqCst)
    ));
    let _ = std::fs::remove_dir_all(&d);
    std::fs::create_dir_all(&d).unwrap();
    d
}