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

nordisk/holger

xtask/tests/appliance_pack.rs

//! `cargo xtask appliance-pack` — proven on APPLIED OUTPUT: the files it
//! writes, read back independently, never its exit code alone.

use std::path::PathBuf;
use std::process::Command;

fn workspace_root() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .unwrap()
        .to_path_buf()
}

#[test]
fn packs_a_binary_pins_it_and_the_entry_reads_back() {
    let root = workspace_root();
    let scratch = root.join("target/appliance-pack-test");
    let _ = std::fs::remove_dir_all(&scratch);
    std::fs::create_dir_all(&scratch).unwrap();

    // A distinctive fixture "binary" — content is what round-trips, not ELF-ness
    // (the packer only WARNS about dynamic linking; it packs any bytes).
    let fixture = scratch.join("fake-holger-mvp");
    let payload: Vec<u8> = (0..64 * 1024u32).flat_map(|i| i.to_le_bytes()).collect();
    std::fs::write(&fixture, &payload).unwrap();
    let out_dir = scratch.join("out");

    let run = Command::new(env!("CARGO"))
        .args([
            "run",
            "--quiet",
            "--manifest-path",
            "xtask/Cargo.toml",
            "--",
            "appliance-pack",
        ])
        .args(["--bin"])
        .arg(&fixture)
        .args(["--entry", "holger", "--out"])
        .arg(&out_dir)
        .args(["--level", "3"]) // fast for the test; the default is release-dense
        .current_dir(&root)
        .output()
        .expect("spawn appliance-pack");
    let all = format!(
        "--- stdout ---\n{}\n--- stderr ---\n{}",
        String::from_utf8_lossy(&run.stdout),
        String::from_utf8_lossy(&run.stderr)
    );
    assert!(run.status.success(), "appliance-pack must succeed:\n{all}");

    // The archive: reads back the entry byte-identically through the SAME shared
    // codec the boot chain uses.
    let archive = out_dir.join("holger-app.znippy");
    let got = znippy_common::get_file(&archive, "holger").expect("entry 'holger' in the archive");
    assert_eq!(got, payload, "the packed entry is the input, byte for byte");

    // The pin: blake3 of the ARCHIVE bytes — what the ESP carries and korp-start
    // re-checks. Computed here independently, not trusted from the verb's print.
    let pin = std::fs::read_to_string(out_dir.join("holger-app.blake3")).unwrap();
    let archive_bytes = std::fs::read(&archive).unwrap();
    assert_eq!(
        pin.trim(),
        blake3::hash(&archive_bytes).to_hex().to_string(),
        "the pin file pins the archive on disk"
    );

    // RED — a wrong entry name is a refusal from the codec, not a silent empty.
    assert!(
        znippy_common::get_file(&archive, "korp").is_err(),
        "an entry nobody packed must not read back"
    );

    let _ = std::fs::remove_dir_all(&scratch);
}