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

nordisk/znippy-zoomies

tests/required_features_law.rs

//! Guard test for the **required-features law**: a target nothing builds is a target
//! nothing checks.
//!
//! ## Why this is a law and not a style note
//!
//! `cargo check --workspace --all-targets` is the command everyone reaches for to answer
//! "is the tree clean". It does **not** mean all targets. A `[[bin]]` / `[[bench]]` /
//! `[[example]]` carrying `required-features` is skipped **silently** when those features
//! are off — no warning, no note, no non-zero exit. The target simply is not in the
//! build, and neither is anything wrong with it.
//!
//! MEASURED on this tree 2026-08-04: `ljar/src/bin/bench_inflate_cmp.rs:52` held
//!
//! ```text
//! error[E0282]: type annotations needed for `Vec<_>`
//! ```
//!
//! and `cargo check --workspace --all-targets` was **GREEN**, because the bin declares
//! `required-features = ["gen"]`. `--all-features` was green too, for a different and
//! worse reason: it turns `zlib-ng` on as well, and the `#[cfg(feature = "zlib-ng")]`
//! block is the only thing that ever pushes into that vector, so the inference succeeds
//! and the defect is invisible from that direction as well. Neither of the two commands
//! anyone actually runs could see it.
//!
//! This is the same defect class as the bench-target law next door
//! (`tests/bench_target_law.rs`): a target that no declared build point compiles.
//! There the target failed loudly and everybody learned to read past it; here it never
//! failed at all. This file IS the declared build point.
//!
//! ## The rule this test enforces
//!
//! Every target in the workspace that carries `required-features` must compile with
//! exactly those features enabled and nothing else. Checked by running `cargo check`,
//! and judged on its OUTPUT — compiler diagnostics — not on its exit code alone.
//!
//! ## The guard's own guard
//!
//! A test that shells out is the classic silent green: a malformed command fails, its
//! empty output looks exactly like a clean result, and the law passes for ever. So:
//!
//!   * [`the_scan_finds_the_required_features_targets`] asserts the manifest walk reaches
//!     real declarations and names one it must contain.
//!   * [`the_runner_can_report_red`] drives the same runner at a target that cannot
//!     build, and requires a failure with a diagnostic in it. A runner that always
//!     answered "clean" fails there.

#[path = "law_common/mod.rs"]
mod law_common;

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

/// One target that cargo will not build unless its features are asked for.
#[derive(Debug, Clone, PartialEq, Eq)]
struct Gated {
    /// The package the target belongs to (`-p`).
    package: String,
    /// `bin` / `bench` / `example` — the flag cargo takes.
    kind: String,
    /// The target's name.
    name: String,
    /// The features it declares it needs.
    features: Vec<String>,
}

/// The workspace root plus every member, as crate directories.
///
/// ONE reader, shared with the other two law guards — see [`law_common`]. The private
/// copy this replaces read `members = [...]` off a SINGLE line and narrowed to the root
/// crate, in silence, the moment that array wrapped.
fn crate_dirs() -> Vec<PathBuf> {
    law_common::crate_dirs()
}

/// Parse a `["a", "b"]` inline array.
fn array(val: &str) -> Vec<String> {
    let Some(a) = val.find('[') else {
        return Vec::new();
    };
    let Some(b) = val.rfind(']') else {
        return Vec::new();
    };
    val[a + 1..b]
        .split(',')
        .map(|s| s.trim().trim_matches('"').to_string())
        .filter(|s| !s.is_empty())
        .collect()
}

/// Every `required-features` target declared anywhere in the workspace.
fn gated_targets() -> Vec<Gated> {
    let mut out = Vec::new();
    for dir in crate_dirs() {
        let Ok(manifest) = std::fs::read_to_string(dir.join("Cargo.toml")) else {
            continue;
        };
        let mut package = String::new();
        let mut section = String::new();
        let mut cur: (Option<String>, Vec<String>) = (None, Vec::new());
        let mut flush = |section: &str,
                         cur: &mut (Option<String>, Vec<String>),
                         out: &mut Vec<Gated>,
                         package: &str| {
            let kind = match section {
                "[[bin]]" => "bin",
                "[[bench]]" => "bench",
                "[[example]]" => "example",
                "[[test]]" => "test",
                _ => return,
            };
            if let (Some(name), false) = (cur.0.take(), cur.1.is_empty()) {
                out.push(Gated {
                    package: package.to_string(),
                    kind: kind.to_string(),
                    name,
                    features: std::mem::take(&mut cur.1),
                });
            }
            *cur = (None, Vec::new());
        };
        for line in manifest.lines() {
            let t = line.trim();
            if t.starts_with('[') {
                flush(&section, &mut cur, &mut out, &package);
                section = t.to_string();
                continue;
            }
            let Some((key, val)) = t.split_once('=') else {
                continue;
            };
            let (key, val) = (key.trim(), val.trim());
            match (section.as_str(), key) {
                ("[package]", "name") => package = val.trim_matches('"').to_string(),
                (_, "name") => cur.0 = Some(val.trim_matches('"').to_string()),
                (_, "required-features") => cur.1 = array(val),
                _ => {}
            }
        }
        flush(&section, &mut cur, &mut out, &package);
    }
    out.sort_by(|a, b| (&a.package, &a.kind, &a.name).cmp(&(&b.package, &b.kind, &b.name)));
    out
}

/// A target directory of this law's own, so a `cargo check` run from inside a test
/// cannot contend with the outer build's lock on the one it is running out of.
fn scratch_target_dir() -> PathBuf {
    let base = std::env::var("CARGO_TARGET_DIR")
        .map(PathBuf::from)
        .unwrap_or_else(|_| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target"));
    base.join("required-features-law")
}

/// Run one `cargo check` and hand back `(success, combined output)`.
///
/// **The output, not the exit code.** A malformed argv fails in a way whose empty output
/// is shaped exactly like a clean result, and that is how a shell-out guard dies.
fn cargo_check(package: &str, features: &[String], targets: &[(String, String)]) -> (bool, String) {
    let mut cmd = Command::new(std::env::var("CARGO").unwrap_or_else(|_| String::from("cargo")));
    cmd.current_dir(env!("CARGO_MANIFEST_DIR"))
        .env("CARGO_TARGET_DIR", scratch_target_dir())
        // Inherited RUSTFLAGS would force a different fingerprint per caller and, worse,
        // could carry a `-D warnings` that turns this law into a style gate.
        .env_remove("RUSTFLAGS")
        .arg("check")
        .arg("-p")
        .arg(package);
    if !features.is_empty() {
        cmd.arg("--features").arg(features.join(","));
    }
    for (kind, name) in targets {
        cmd.arg(format!("--{kind}")).arg(name);
    }
    let out = cmd.output().expect("run cargo check");
    let text = format!(
        "{}{}",
        String::from_utf8_lossy(&out.stdout),
        String::from_utf8_lossy(&out.stderr)
    );
    (out.status.success(), text)
}

/// Every compiler diagnostic line in a cargo run's output.
fn errors(text: &str) -> Vec<&str> {
    text.lines()
        .map(str::trim_start)
        .filter(|l| l.starts_with("error[") || l.starts_with("error:"))
        .collect()
}

/// **The law.** A target cargo will not build by default must still build.
#[test]
fn every_required_features_target_builds() {
    let gated = gated_targets();
    // Group by (package, feature set): one cargo invocation compiles the dependency
    // graph once for all of them.
    let mut groups: Vec<(String, Vec<String>, Vec<(String, String)>)> = Vec::new();
    for g in &gated {
        match groups
            .iter_mut()
            .find(|(p, f, _)| *p == g.package && *f == g.features)
        {
            Some((_, _, ts)) => ts.push((g.kind.clone(), g.name.clone())),
            None => groups.push((
                g.package.clone(),
                g.features.clone(),
                vec![(g.kind.clone(), g.name.clone())],
            )),
        }
    }

    let mut offenders: Vec<String> = Vec::new();
    for (package, features, targets) in &groups {
        let (ok, text) = cargo_check(package, features, targets);
        let errs = errors(&text);
        if !ok || !errs.is_empty() {
            offenders.push(format!(
                "{package} --features {} ({}): {}",
                features.join(","),
                targets
                    .iter()
                    .map(|(k, n)| format!("--{k} {n}"))
                    .collect::<Vec<_>>()
                    .join(" "),
                if errs.is_empty() {
                    String::from("cargo failed with no diagnostic — the command itself is wrong")
                } else {
                    errs.join(" | ")
                },
            ));
        }
    }
    assert!(
        offenders.is_empty(),
        "{} of {} required-features group(s) do not build. `cargo check --workspace \
         --all-targets` skips these SILENTLY, so this test is the only thing that ever \
         compiles them:\n  {}",
        offenders.len(),
        groups.len(),
        offenders.join("\n  ")
    );
}

/// **Anti-hollow arm one: the sweep must actually reach declarations.**
///
/// A manifest walk that finds nothing makes the law above green for ever. Assert a floor
/// and name the target that carried the defect, so a discovery that stops seeing it
/// fails here rather than passing there.
#[test]
fn the_scan_finds_the_required_features_targets() {
    let gated = gated_targets();
    assert!(
        gated.len() >= 3,
        "found only {} required-features target(s) — the walk is misrooted and the law \
         would be vacuously green: {gated:?}",
        gated.len()
    );
    let found = gated
        .iter()
        .find(|g| g.package == "ljar" && g.name == "bench_inflate_cmp")
        .unwrap_or_else(|| panic!("discovery lost ljar's bench_inflate_cmp; it saw {gated:?}"));
    assert_eq!(found.kind, "bin");
    assert_eq!(
        found.features,
        vec![String::from("gen")],
        "the features must be read off the manifest, not assumed",
    );
}

/// **Anti-hollow arm two: the runner must be able to say no.**
///
/// Drives the identical machinery at a target that cannot exist. A runner that silently
/// reports clean — the way a shell-out guard usually dies — fails here.
#[test]
fn the_runner_can_report_red() {
    let (ok, text) = cargo_check(
        "ljar",
        &[String::from("gen")],
        &[(
            String::from("bin"),
            String::from("a_bin_that_does_not_exist"),
        )],
    );
    assert!(
        !ok,
        "cargo reported success for a bin that does not exist:\n{text}"
    );
    assert!(
        !errors(&text).is_empty(),
        "cargo failed but printed no diagnostic — this runner would read a broken \
         invocation as a clean tree:\n{text}"
    );
}