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

nordisk/dwarves

dwarves-gui/tests/logo_asset_parity.rs

//! **The About logo really is inside this package — and really is the repo's logo.**
//!
//! `build.rs` transcodes `assets/dwarves.webp` into a PNG in `OUT_DIR`, and `src/about.rs`
//! `include_bytes!`es that PNG. Until 2026-08-24 the build script read
//! `../assets/dwarves.webp` — the dwarves repo's shared asset dir, one level ABOVE this
//! package root. That works in a checkout and cannot work from crates.io: `cargo package`
//! tarballs only files under the package root, so `../assets/` is not in the published
//! crate and the build script's (deliberately loud) `panic!` fired for every consumer:
//!
//! > `dwarves-gui build: could not decode ../assets/dwarves.webp as an image: …`
//!
//! The fix is a second copy of the 90 KB webp inside `dwarves-gui/assets/`. That copy is
//! what this file guards, in the two independent ways it can go wrong:
//!
//! 1. **It vanishes.** Then the published crate is unbuildable again — the exact defect
//!    the copy was made to fix, silently reintroduced.
//! 2. **It drifts.** The artist updates `assets/dwarves.webp` for the README and the UI
//!    keeps shipping last month's logo, with nothing anywhere saying so.
//!
//! On the SKIP: check (2) needs the repo-root copy, which by construction is absent from a
//! published tarball. So it is gated on a REPO MARKER (`../.nornir/build-variants.toml`,
//! the file the build receipt keys on) rather than on the asset's own absence. That
//! distinction is the difference between a guard that knows when it does not apply and a
//! guard that reports green because its input disappeared — this repo has been bitten by
//! the second kind (`8edaa23`: four CI guards green because a `#` was in front of them),
//! so the marker is checked FIRST and a marker with no asset beside it is a FAILURE.

use std::path::PathBuf;

fn crate_dir() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}

/// The copy `build.rs` actually reads — must be inside the package root.
fn packaged_logo() -> PathBuf {
    crate_dir().join("assets/dwarves.webp")
}

/// The repo-root copy `README.md` renders. Absent in a published tarball.
fn repo_logo() -> PathBuf {
    crate_dir().join("../assets/dwarves.webp")
}

/// The marker that says "we are in the nordisk checkout, not a registry tarball".
fn repo_marker() -> PathBuf {
    crate_dir().join("../.nornir/build-variants.toml")
}

/// THE PUBLISH CONTRACT: the logo is under the package root. This must hold everywhere —
/// checkout and published tarball alike — because `build.rs` panics without it.
#[test]
fn the_logo_is_inside_this_package_root() {
    let p = packaged_logo();
    assert!(
        p.is_file(),
        "{} is missing.\n`build.rs` reads `assets/dwarves.webp` relative to this \
         manifest and PANICS if it cannot decode it, so without this file the published \
         crate cannot build at all — and `cargo package` cannot reach outside the \
         package root to find the repo-root copy.",
        p.display()
    );

    let bytes = std::fs::read(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()));
    assert!(
        !bytes.is_empty(),
        "{} is EMPTY — an unreadable image is the same broken build as a missing one",
        p.display()
    );
    // RIFF/WEBP magic: "RIFF" ....  "WEBP". A truncated or wrong-format file would sail
    // past a size check and die in `image::open` at build time instead.
    assert!(
        bytes.len() > 12 && &bytes[0..4] == b"RIFF" && &bytes[8..12] == b"WEBP",
        "{} is not a WebP file (first 12 bytes: {:?}) — `build.rs` decodes it with an \
         `image` build whose only enabled codecs are webp + png",
        p.display(),
        &bytes[..bytes.len().min(12)]
    );

    eprintln!(
        "logo asset: {} present, {} bytes, WebP magic ok",
        p.display(),
        bytes.len()
    );
}

/// THE DRIFT CONTRACT: the packaged copy is the repo's logo, not a fork of it.
///
/// Gated on the repo marker, never on the asset's absence — see the module docs.
#[test]
fn the_packaged_logo_matches_the_repo_root_logo() {
    let marker = repo_marker();
    if !marker.is_file() {
        // No recipe ⇒ no checkout ⇒ there is no repo-root copy to compare against, and
        // that is a fact about WHERE we are, not a defect. `the_logo_is_inside_this_
        // package_root` above still runs and still carries the publish contract.
        eprintln!(
            "logo asset: no repo marker at {} — published-crate layout, drift check does \
             not apply here (the package-root check above still ran)",
            marker.display()
        );
        return;
    }

    // The marker IS there, so we are in the checkout and BOTH copies must be.
    let (packaged, repo) = (packaged_logo(), repo_logo());
    assert!(
        repo.is_file(),
        "the repo marker {} exists, so this is the nordisk checkout — but {} does not. \
         Either the shared asset was deleted (README.md renders it) or the layout moved; \
         a guard whose input silently vanished must go RED, not quietly pass.",
        marker.display(),
        repo.display()
    );
    assert!(packaged.is_file(), "{} is missing", packaged.display());

    let a = std::fs::read(&repo).unwrap_or_else(|e| panic!("read {}: {e}", repo.display()));
    let b = std::fs::read(&packaged).unwrap_or_else(|e| panic!("read {}: {e}", packaged.display()));

    assert!(
        !a.is_empty(),
        "{} is EMPTY — this guard would then compare nothing to nothing",
        repo.display()
    );

    assert!(
        a == b,
        "the packaged logo has DRIFTED from the repo's.\n  {} = {} bytes\n  {} = {} \
         bytes\nThey must be identical: the second copy exists ONLY so the file lands \
         inside the published tarball, so a difference means the shipped About box is \
         rendering a logo the repo no longer has. Re-copy the repo-root asset over the \
         packaged one.",
        repo.display(),
        a.len(),
        packaged.display(),
        b.len()
    );

    eprintln!(
        "logo asset: packaged copy is byte-identical to the repo asset ({} bytes)",
        a.len()
    );
}

/// `build.rs` must read the asset from INSIDE the package. A guard on the bytes is worth
/// nothing if the build script has quietly gone back to reaching over the package
/// boundary — that reintroduces the original defect while both copies sit there agreeing.
#[test]
fn the_build_script_reads_the_packaged_copy_not_the_repo_copy() {
    let bs = crate_dir().join("build.rs");
    let src = std::fs::read_to_string(&bs).unwrap_or_else(|e| panic!("read {}: {e}", bs.display()));

    // Only the CODE lines matter; the comments deliberately quote the old broken path to
    // record what went wrong, so a naive substring search over the whole file would find
    // `../assets/dwarves.webp` in the explanation and report a false red.
    let code: Vec<&str> = src
        .lines()
        .map(|l| l.split("//").next().unwrap_or(""))
        .filter(|l| !l.trim().is_empty())
        .collect();
    assert!(
        !code.is_empty(),
        "build.rs parsed to zero code lines — the filter is broken"
    );

    let offenders: Vec<&&str> = code
        .iter()
        .filter(|l| l.contains("../assets/dwarves.webp"))
        .collect();
    assert!(
        offenders.is_empty(),
        "build.rs reads the logo from OUTSIDE the package root again:\n  {}\n`cargo \
         package` will not carry `../assets/`, so the published crate goes back to \
         panicking in its build script. Read `assets/dwarves.webp` instead.",
        offenders
            .iter()
            .map(|l| l.trim())
            .collect::<Vec<_>>()
            .join("\n  ")
    );

    assert!(
        code.iter().any(|l| l.contains("\"assets/dwarves.webp\"")),
        "build.rs no longer names `assets/dwarves.webp` at all — this guard has lost its \
         subject and must not pass by finding nothing to object to"
    );

    eprintln!(
        "logo asset: build.rs reads the package-root copy ({} code lines scanned)",
        code.len()
    );
}