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

nordisk/edda

crates/nornir-build-thing/tests/common/mod.rs

//! Shared fixture builder for the tests that need a **real** artifact.
//!
//! Both `receipt_end_to_end.rs` and `history_end_to_end.rs` need the same thing:
//! a small binary built by a real compiler and a real linker, carrying (or
//! deliberately not carrying) a receipt in `.nordisk.buildthing`. Two copies of
//! this would be two definitions of what "a real artifact" means here, and the
//! history tests exist precisely to check that the same bytes attest the same
//! way — so they must be the same bytes.

use std::path::{Path, PathBuf};
use std::process::Command;

/// Build a one-file binary whose source is `prelude` followed by a `main`.
///
/// The fixture has **no dependencies**, so it builds `--offline` with no
/// registry and these tests need no network.
///
/// `strip` picks whether the artifact keeps a symbol table, which is the axis the
/// receipt-proof assertions turn on.
///
/// # Panics
///
/// If cargo cannot be run, if the fixture does not build (the compiler's stderr
/// is included), or if no binary appears where cargo said it would.
// Used by `receipt_end_to_end.rs` and `history_end_to_end.rs`, not by
// `attestation_end_to_end.rs` — and a `mod common;` is compiled fresh into each
// test binary, so one of the three always reports it unused. The alternative is
// three copies of the fixture builder, which is the thing this file exists to
// prevent.
#[allow(dead_code)]
pub fn build_fixture(root: &Path, name: &str, prelude: &str, strip: bool) -> PathBuf {
    build_fixture_with_main(root, name, prelude, "", strip)
}

/// [`build_fixture`] with a body spliced into `main` before the `println!`.
///
/// The extra parameter exists for one reason: a symbol only reaches the symbol
/// table if something keeps it, and `--release` + `lto = true` is entitled to
/// delete a function nothing reaches. A test that wants to measure a *family* of
/// symbols in a real binary therefore has to make `main` touch them, and a
/// fixture whose `main` is fixed cannot.
///
/// Kept as one function with a delegating wrapper rather than two builders:
/// "what a real artifact is here" has to have exactly one definition, or the
/// tests that compare artifacts against each other are comparing two things.
///
/// # Panics
///
/// As [`build_fixture`].
pub fn build_fixture_with_main(
    root: &Path,
    name: &str,
    prelude: &str,
    main_body: &str,
    strip: bool,
) -> PathBuf {
    let dir = root.join(name);
    std::fs::create_dir_all(dir.join("src")).expect("fixture dirs");
    std::fs::write(
        dir.join("Cargo.toml"),
        format!(
            "[package]\nname = \"{name}\"\nversion = \"0.0.0\"\nedition = \"2021\"\n\
             [workspace]\n\
             [profile.release]\nopt-level = 3\nlto = true\nstrip = {strip}\n"
        ),
    )
    .expect("fixture manifest");
    std::fs::write(
        dir.join("src/main.rs"),
        format!("{prelude}\nfn main() {{ {main_body} println!(\"{name}\"); }}\n"),
    )
    .expect("fixture source");

    let target_dir = root.join("t");
    let out = Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()))
        .args(["build", "--release", "--offline"])
        .arg("--target-dir")
        .arg(&target_dir)
        .current_dir(&dir)
        .output()
        .expect("run cargo");
    assert!(
        out.status.success(),
        "fixture {name} did not build:\n{}",
        String::from_utf8_lossy(&out.stderr)
    );
    let bin = target_dir.join("release").join(name);
    assert!(bin.is_file(), "no fixture binary at {}", bin.display());
    bin
}