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

nordisk/nornir

src/mimir_lens/room_feed/built_tests.rs

//! The binary lenses over REAL Build Thing builds: a small crate is built by
//! `nornir_build_thing::build_variant_with_info` (the one cargo-driving loop
//! every Build Thing door runs), filed through builder 2's job
//! (`code_room::products::land_build`: artifact node, BUILT_FROM,
//! provenance, the binary half), and the lenses answer from what it filed.

use std::path::Path;
use std::process::Command;

use nornir_build_thing::build_info::{BuildInfoKind, BuildInfoRow};
use nornir_build_thing::{BuildProvenance, BuildVariantSet, InMemBuildInfoSink, build_variant_with_info};
use serde_json::{Value, json};

use super::fixture::{self, SHOP, Without};
use crate::code_room::products::{self, COMMIT_PREFIX, DEP_CRATE, REPO_ROOT};
use crate::code_room::{CodeRoom, Reach};
use crate::warehouse::iceberg::IcebergWarehouse;

const RECIPE: &str = r#"
[[build.variant]]
name = "probe"
package = "PKG"
profile = "release"
"#;

/// The probe's `checksum` before and after the change between two builds.
const CHECKSUM_V1: &str = "data.iter().map(|b| *b as u64).sum()";
const CHECKSUM_V2: &str = "let mut h: u64 = 0xcbf2_9ce4_8422_2325;
    for (i, b) in data.iter().enumerate() {
        h ^= *b as u64;
        h = h.wrapping_mul(0x0100_0000_01b3);
        if i % 3 == 0 {
            h = h.rotate_left(7) ^ (i as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15);
        }
    }
    h ^ (h >> 33)";

/// A small real crate: a generic instantiated six times, a `checksum` the
/// second build changes, and `pay::dead` (the fixture shop's gated item).
fn write_crate(root: &Path, pkg: &str, checksum: &str) {
    std::fs::create_dir_all(root.join("src")).unwrap();
    std::fs::write(
        root.join("Cargo.toml"),
        format!("[package]\nname = \"{pkg}\"\nversion = \"0.1.0\"\nedition = \"2021\"\npublish = false\n\n[workspace]\n\n[profile.release]\ndebug = false\nstrip = false\n"),
    )
    .unwrap();
    let main = r#"use std::hint::black_box;

#[inline(never)]
pub fn widen<T: Copy + Into<u64>>(xs: &[T]) -> u64 {
    let mut acc = 0u64;
    for (i, x) in xs.iter().enumerate() {
        let v: u64 = (*x).into();
        acc = acc.rotate_left((i % 63) as u32) ^ v.wrapping_mul(0x9e37_79b9_7f4a_7c15);
        if v % 7 == 3 {
            acc = acc.wrapping_add(v.wrapping_pow(3));
        }
        if v % 5 == 1 {
            acc ^= acc >> 17;
        }
        acc = acc.wrapping_mul(0xff51_afd7_ed55_8ccd) ^ (acc >> 29);
    }
    acc
}

#[inline(never)]
pub fn checksum(data: &[u8]) -> u64 {
    CHECKSUM
}

pub mod pay {
    #[inline(never)]
    pub fn dead(n: u64) -> u64 {
        (0..n).map(|i| (i * i) ^ 0x5a).sum()
    }
}

fn main() {
    let a = black_box([1u8, 2, 3]);
    let b = black_box([1u16, 2]);
    let c = black_box([7u32, 8]);
    let d = black_box([9u64]);
    let e = black_box([true, false]);
    let f = black_box(['p', 'q']);
    println!(
        "{} {} {} {} {} {} {} {}",
        widen(&a), widen(&b), widen(&c), widen(&d), widen(&e), widen(&f), checksum(black_box(b"probe")), pay::dead(black_box(5))
    );
}
"#;
    std::fs::write(root.join("src/main.rs"), main.replace("CHECKSUM", checksum)).unwrap();
}

fn git(root: &Path, args: &[&str]) -> String {
    let out = Command::new("git")
        .args(["-c", "user.name=probe", "-c", "user.email=probe@example.invalid", "-c", "commit.gpgsign=false"])
        .args(args)
        .current_dir(root)
        .output()
        .expect("git");
    assert!(out.status.success(), "git {args:?}: {}", String::from_utf8_lossy(&out.stderr));
    String::from_utf8_lossy(&out.stdout).trim().to_string()
}

/// Commit the crate as it is now; the sha.
fn commit(root: &Path, msg: &str) -> String {
    if !root.join(".git").exists() {
        git(root, &["init", "-q"]);
    }
    git(root, &["add", "-A"]);
    git(root, &["commit", "-qm", msg]);
    git(root, &["rev-parse", "HEAD"])
}

/// A real Build Thing build of the crate at `root` (its dir name is the repo),
/// filed the way the server files one: the build's own `build_info` rows +
/// the forge's lineage rows (dwarves' `build_lineage`), landed by builder 2.
fn build_and_file(room: &CodeRoom, wh: &IcebergWarehouse, root: &Path, pkg: &str, sha: &str) -> (BuildProvenance, Value) {
    let set = BuildVariantSet::from_toml_str(&RECIPE.replace("PKG", pkg)).expect("the recipe");
    let sink = InMemBuildInfoSink::new();
    let out = build_variant_with_info(&set, "probe", root, &sink).expect("a real Build Thing build");
    assert!(out.success, "cargo built the probe");
    let record = out.attestation.record.clone();
    let mut rows = sink.rows();
    assert_eq!(products::landed_builds(&rows), vec![record.id.clone()], "the manifest says success");
    let repo = root.file_name().unwrap().to_string_lossy().into_owned();
    let row = |k: BuildInfoKind, n: &str, v: &str| BuildInfoRow::new(&record.id, 2, k).kv(n, v.to_string());
    rows.push(row(BuildInfoKind::Provenance, REPO_ROOT, &root.display().to_string()));
    rows.push(row(BuildInfoKind::Provenance, &format!("{COMMIT_PREFIX}{repo}"), sha));
    rows.push(row(BuildInfoKind::Dep, DEP_CRATE, &format!("{pkg}@0.1.0")));
    let landed = products::land_build(room, wh, &record, &rows).expect("builder 2 lands the build");
    (record, landed)
}

fn ask(room: &CodeRoom, wh: &IcebergWarehouse, lens: &str, p: Value) -> Value {
    crate::mimir_lens::answer(lens, &Reach::new(room, wh), &p)
}

fn note(v: &Value) -> &str {
    v["evidence_note"].as_str().unwrap_or("")
}

/// A real build files an artifact (Coderoom.Artifacts lists it, its bytes are
/// analysed under its sha256), and `generic_cost` answers from it: the
/// probe's `widen`, instantiated six times, is its named tax. Before any
/// build both binary lenses say so plainly; after ONE build `binary_drift`
/// says there is nothing to compare yet.
#[test]
fn a_real_build_thing_build_files_an_artifact_and_generic_cost_answers_from_it() {
    let _g = fixture::serial();
    let tmp = tempfile::tempdir().unwrap();
    let builds = tmp.path().join("builds");
    std::fs::create_dir_all(&builds).unwrap();
    let wh = IcebergWarehouse::open(&builds).unwrap();
    let room = CodeRoom::new("ws", &builds);
    let root = tmp.path().join("binlens-probe");
    write_crate(&root, "binlens-probe", CHECKSUM_V1);
    let sha = commit(&root, "v1");

    // nothing filed yet: said, never an empty list on its own
    for lens in ["generic_cost", "binary_drift"] {
        let v = ask(&room, &wh, lens, json!({}));
        assert_eq!(v["lens_meta"]["state"], "empty_gap", "{v}");
        assert!(note(&v).contains("no Build Thing run has filed an artifact for this workspace yet: ⚒ Build it"), "{}", note(&v));
    }

    let (record, landed) = build_and_file(&room, &wh, &root, "binlens-probe", &sha);
    assert_eq!(landed["artifacts"].as_array().map(Vec::len), Some(1), "{landed}");
    assert!(landed["binary_half"][0].get("error").is_none(), "analysed on this box: {landed}");
    let arts = products::answer(&room, &json!({ "crate": "binlens-probe" })).unwrap();
    assert_eq!(arts["count"], 1, "{arts}");
    let sha256 = &record.artifacts[0].sha256;
    assert!(crate::binscan::load_report(&wh, sha256).unwrap().is_some_and(|r| !r.symbols.is_empty()), "its symbols are filed under its sha256");

    let v = ask(&room, &wh, "generic_cost", json!({ "repo": "binlens-probe" }));
    assert_eq!(v["lens_meta"]["state"], "complete", "{v}");
    assert_eq!(v["source"], "build");
    let a = &v["worst_artifacts"][0];
    assert_eq!(a["repo"], "binlens-probe", "{v}");
    assert!(a["artifact"].as_str().unwrap().ends_with(&sha256[..16]), "the filed artifact, by its bytes: {v}");
    assert!(a["total_bytes"].as_u64().unwrap() > 0);
    let widen = a["top_named"].as_array().unwrap().iter().find(|g| g["symbol"].as_str().is_some_and(|s| s.ends_with("widen"))).unwrap_or_else(|| panic!("widen is a named generic: {v}"));
    assert_eq!(widen["instantiations"], 6, "{widen}");
    assert!(note(&v).contains("latest Build Thing artifact of each variant"), "{}", note(&v));
    // a repo nothing was built for is said by name
    let other = ask(&room, &wh, "generic_cost", json!({ "repo": "nobody" }));
    assert!(note(&other).contains("no Build Thing run has filed an artifact for `nobody` yet: ⚒ Build it"), "{}", note(&other));

    let d = ask(&room, &wh, "binary_drift", json!({}));
    assert_eq!(d["lens_meta"]["state"], "empty_gap", "{d}");
    assert!(note(&d).contains("filed once") && note(&d).contains("⚒ Build it again after a change"), "{}", note(&d));
    assert!(d["attestation"].as_str().unwrap().contains("UNKNOWN"), "{d}");
}

/// Two real builds of the same variant, the second after a commit that
/// changed `checksum`: `binary_drift` reports the change between the two
/// filings — first party, explained by the commit — and `generic_cost`
/// reads the newer artifact.
#[test]
fn a_second_build_with_a_changed_function_is_the_drift_binary_drift_reports() {
    let _g = fixture::serial();
    let tmp = tempfile::tempdir().unwrap();
    let builds = tmp.path().join("builds");
    std::fs::create_dir_all(&builds).unwrap();
    let wh = IcebergWarehouse::open(&builds).unwrap();
    let room = CodeRoom::new("ws", &builds);
    let root = tmp.path().join("binlens-probe");
    write_crate(&root, "binlens-probe", CHECKSUM_V1);
    let sha1 = commit(&root, "v1");
    let (first, _) = build_and_file(&room, &wh, &root, "binlens-probe", &sha1);
    write_crate(&root, "binlens-probe", CHECKSUM_V2);
    let sha2 = commit(&root, "checksum: fnv");
    let (second, _) = build_and_file(&room, &wh, &root, "binlens-probe", &sha2);
    assert_ne!(first.artifacts[0].sha256, second.artifacts[0].sha256, "other bytes");

    let d = ask(&room, &wh, "binary_drift", json!({ "repo": "binlens-probe" }));
    // the edge half (P4) is the one named gap
    assert_eq!(d["lens_meta"]["state"], "partial", "{d}");
    let step = &d["steps"][0];
    assert_eq!((step["from"]["sha256"].as_str(), step["to"]["sha256"].as_str()), (Some(first.artifacts[0].sha256.as_str()), Some(second.artifacts[0].sha256.as_str())), "{step}");
    assert!(step["provenance_changed"][0].as_str().unwrap().starts_with("commit binlens-probe"), "{step}");
    let checksum = d["findings"]
        .as_array()
        .unwrap()
        .iter()
        .find(|f| f["symbol"].as_str().is_some_and(|s| s.contains("checksum")))
        .unwrap_or_else(|| panic!("the changed function is reported: {d}"));
    assert!(["symbol-grew", "symbol-shrunk", "symbol-added", "symbol-removed"].contains(&checksum["kind"].as_str().unwrap()), "{checksum}");
    assert_eq!((checksum["first_party"].as_bool(), checksum["explained_by"].as_str(), checksum["severity"].as_str()), (Some(true), Some("source"), Some("medium")), "{checksum}");
    assert_eq!((checksum["from_commit"].as_str(), checksum["to_commit"].as_str()), (Some(&sha1[..10]), Some(&sha2[..10])));
    assert_eq!(d["attested"], true, "a source change explains it: {d}");
    // the first-party change ranks above the dependency churn
    assert_eq!(d["findings"][0]["first_party"], true, "{d}");

    let g = ask(&room, &wh, "generic_cost", json!({ "repo": "binlens-probe" }));
    assert!(g["worst_artifacts"][0]["artifact"].as_str().unwrap().ends_with(&second.artifacts[0].sha256[..16]), "the latest filed artifact: {g}");
}

/// `zombie_features`' bytes are the gated item's symbols in the latest Build
/// Thing artifact built from its repo: the fixture shop's `pay::dead` (gated
/// by `unused`), built for real and filed from shop's commit.
#[test]
fn zombie_bytes_are_the_gated_items_symbols_in_the_latest_filed_artifact() {
    let _g = fixture::serial();
    let ws = fixture::graph_only(Without::default());
    let tmp = tempfile::tempdir().unwrap();
    let root = tmp.path().join(SHOP);
    write_crate(&root, SHOP, CHECKSUM_V1);
    let sha = commit(&root, "shop");
    let before = ws.ask("zombie_features", json!({ "repo": SHOP }));
    let unused = |v: &Value| v["worst"].as_array().unwrap().iter().find(|f| f["feature"] == "shop/unused").cloned().unwrap_or_else(|| panic!("{v}"));
    assert_eq!(unused(&before)["bytes_in_binary"], Value::Null, "nothing filed yet: {before}");

    build_and_file(&ws.room, &ws.warehouse, &root, SHOP, &sha);
    let after = ws.ask("zombie_features", json!({ "repo": SHOP }));
    assert_eq!(after["lens_meta"]["state"], "complete", "{after}");
    assert!(unused(&after)["bytes_in_binary"].as_u64().unwrap() > 0, "pay::dead's bytes: {after}");
    assert!(note(&after).contains("latest Build Thing artifact built from its repo"), "{}", note(&after));
}