xtask/tests/build_variants.rs
//! **RED-when-broken: znippy-zoomies' declarative build matrix** —
//! `.nornir/build-variants.toml` DISCOVERS, parses and VALIDATES through
//! nornir-build-thing (`cargo xtask build`'s [`BuildVariantSet`]), and every atom it
//! declares is checked against the matrix Rickard approved on 2026-08-03:
//!
//! ```text
//! SUITE ATOM ROLE LINKAGE PACKAGE BIN
//! ORIGINAL osm-katana ⭐ tool not-applicable osm-katana osm-katana
//! ORIGINAL lbunzip2 tool not-applicable lbzip2 lbunzip2
//! ORIGINAL lgz tool not-applicable lgz lgz
//! ORIGINAL ljar tool not-applicable ljar ljar
//! ORIGINAL lzip tool not-applicable lzip-parallel lzip
//! ```
//!
//! ## The rule this file enforces
//!
//! **Carrying a `suites` tag is what makes an atom a Build Thing.** Before this pass
//! znippy-zoomies had no `.nornir/build-variants.toml` at all and no xtask, while
//! shipping five real CLI binaries — so every one of them was outside the system.
//! Now five atoms carry the tag and each must actually build through the declared
//! door.
//!
//! ## The four things measured here that a "does it parse" test would miss
//!
//! 1. **The bin roster is WALKED OUT of the manifests, never written down.** korp
//! renamed a bin in `Cargo.toml` and left its own test asserting a hardcoded argv
//! that could never succeed, green the whole time. Two of the five atoms here
//! have `atom ≠ package` (`lbunzip2` from `lbzip2`, `lzip` from `lzip-parallel`),
//! which is precisely where a hardcoded roster goes wrong.
//! 2. **`required-features` bins are SEEN.** `cargo build --all-targets` silently
//! skips a target whose required features are off and still exits 0 — so "the
//! workspace builds" is not evidence that anything in particular was built. This
//! file reads `required-features` out of the manifests and asserts no declared
//! atom carries one its own feature set does not satisfy, with ljar's three
//! `gen`-gated bench bins as the live proof the check can see them at all.
//! 3. **Every `[[bin]]` in the repo is accounted for** — either a matrix atom or a
//! named [`BENCH_HELPERS`] entry. An undeclared binary and a deliberately-unbuilt
//! one look identical on disk; this is what tells them apart, and it means a new
//! binary added tomorrow trips the guard until somebody decides which it is.
//! 4. **A `tool` never claims a service linkage**, and an OMITTED `linkage` is
//! asserted to read as `fat` — which is what makes stating `not-applicable`
//! worth doing rather than a style preference.
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
use nornir_build_thing::plugin::Role;
use nornir_build_thing::suite_cli;
use nornir_build_thing::variant::{ArtifactKind, BuildVariantSet, Profile, ServiceShape};
/// The repo root. This crate lives at `<root>/xtask`, so the root is its parent —
/// derived, never hardcoded, so a moved xtask fails loudly instead of reading nothing.
fn repo_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("xtask/ always has a parent")
.to_path_buf()
}
fn set() -> BuildVariantSet {
BuildVariantSet::discover(&repo_root())
.expect("discover .nornir/build-variants.toml")
.expect("znippy-zoomies declares a .nornir/build-variants.toml")
}
/// **The matrix, as data** — `(atom, role, linkage, package, bin)`, the ONLY rows a
/// znippy-zoomies declaration may contain. Written out as the matrix's own rows so
/// [`matrix_problems`] compares the declaration against the MATRIX and not against
/// itself.
const MATRIX_ROWS: [(&str, Role, ServiceShape, &str, &str); 5] = [
("osm-katana", Role::Tool, ServiceShape::NotApplicable, "osm-katana", "osm-katana"),
("lbunzip2", Role::Tool, ServiceShape::NotApplicable, "lbzip2", "lbunzip2"),
("lgz", Role::Tool, ServiceShape::NotApplicable, "lgz", "lgz"),
("ljar", Role::Tool, ServiceShape::NotApplicable, "ljar", "ljar"),
("lzip", Role::Tool, ServiceShape::NotApplicable, "lzip-parallel", "lzip"),
];
/// **The `[[bin]]` targets that are DELIBERATELY not Build Things**, each with the
/// reason it is not.
///
/// This list is what turns "not in the matrix" from an absence into a decision. An
/// undeclared binary and a deliberately-unbuilt one look identical on disk, so
/// without naming these five, [`every_binary_in_the_repo_is_accounted_for`] would
/// either have to ignore unknown bins (blind) or fail on them (unusable).
const BENCH_HELPERS: [(&str, &str); 5] = [
("vtd_bench", "osm-katana: timing harness for the VTD-style index; prints numbers, nobody installs it"),
("planet_bench", "osm-katana: timing harness for the planet pass; same"),
(
"bench_inflate_cmp",
"ljar: head-to-head vs the third-party rivals; `required-features = [\"gen\"]`, and \
`gen` pulls zip + miniz_oxide — shipping it would put the rivals in a delivered artifact",
),
("bench_large", "ljar: large-archive timing; `required-features = [\"gen\"]`, same reason"),
("gen_large_zip", "ljar: fixture GENERATOR for the two above; `required-features = [\"gen\"]`"),
];
/// Every problem with a declaration measured against [`MATRIX_ROWS`]. A function over
/// an ARBITRARY set so the RED cases can drive it with declarations that must fail.
fn matrix_problems(set: &BuildVariantSet) -> Vec<String> {
let mut out = Vec::new();
for v in &set.variants {
let Some(row) = MATRIX_ROWS.iter().find(|(n, ..)| *n == v.name) else {
out.push(format!(
"atom '{}' (role {:?}, kind {:?}) is not a row of the build matrix — the rows \
are {}",
v.name,
v.role,
v.kind,
MATRIX_ROWS.iter().map(|(n, ..)| *n).collect::<Vec<_>>().join(", ")
));
continue;
};
let (name, role, linkage, package, bin) = row;
if v.role != Some(*role) {
out.push(format!("atom '{name}': role {:?} but the matrix says {role:?}", v.role));
}
if v.shape != *linkage {
out.push(format!(
"atom '{name}': linkage {:?} but the matrix says {linkage:?}",
v.shape
));
}
if v.package.as_deref() != Some(*package) {
out.push(format!(
"atom '{name}': package {:?} but the matrix says '{package}'",
v.package
));
}
if v.bin.as_deref() != Some(*bin) {
out.push(format!("atom '{name}': bin {:?} but the matrix says '{bin}'", v.bin));
}
if !v.features.is_empty() {
out.push(format!(
"atom '{name}': features {:?}, but every row of this matrix is the LEAN default \
build — the matrix has no feature column",
v.features
));
}
}
out
}
/// One `[[bin]]` target as the manifests declare it: which package it belongs to and
/// what `required-features` it carries.
#[derive(Debug, Clone)]
struct BinTarget {
package: String,
required_features: Vec<String>,
}
/// **Walk every `Cargo.toml` in the repo and collect its `[[bin]]` targets**, with
/// the `required-features` [`BuildVariantSet::cargo_bin_targets`] does not return.
///
/// Not a twin of that method: it answers "which bin NAMES exist" (a membership
/// oracle, flattened), and this answers "which package owns each bin and what does
/// cargo require to build it" — the question `--all-targets` exiting 0 cannot.
/// Both are used below, and the names are cross-checked against each other.
///
/// Also collects the IMPLICIT bin cargo synthesises for a `[package]` with a
/// `src/main.rs` and no `[[bin]]` table, for the same reason the sibling method does:
/// miss it and the guard reds on a target that exists.
fn bin_targets(repo_root: &Path) -> BTreeMap<String, BinTarget> {
fn walk(dir: &Path, out: &mut BTreeMap<String, BinTarget>, depth: usize) {
if depth > 8 {
return;
}
let Ok(rd) = std::fs::read_dir(dir) else { return };
for e in rd.flatten() {
let p = e.path();
let name = e.file_name();
let name = name.to_string_lossy().to_string();
if p.is_dir() {
if matches!(name.as_str(), "target" | ".git" | "vendor" | "node_modules")
|| name.starts_with('.')
{
continue;
}
walk(&p, out, depth + 1);
} else if name == "Cargo.toml" {
let Ok(text) = std::fs::read_to_string(&p) else { continue };
let Ok(doc) = toml::from_str::<toml::Value>(&text) else { continue };
let pkg = doc
.get("package")
.and_then(|x| x.get("name"))
.and_then(|x| x.as_str())
.unwrap_or("<virtual>")
.to_string();
let mut explicit = 0usize;
if let Some(bins) = doc.get("bin").and_then(|b| b.as_array()) {
for b in bins {
let Some(n) = b.get("name").and_then(|n| n.as_str()) else { continue };
let rf = b
.get("required-features")
.and_then(|r| r.as_array())
.map(|a| {
a.iter().filter_map(|x| x.as_str().map(str::to_string)).collect()
})
.unwrap_or_default();
out.insert(
n.to_string(),
BinTarget { package: pkg.clone(), required_features: rf },
);
explicit += 1;
}
}
if explicit == 0
&& pkg != "<virtual>"
&& p.parent().map(|d| d.join("src").join("main.rs").is_file()).unwrap_or(false)
{
out.insert(
pkg.clone(),
BinTarget { package: pkg.clone(), required_features: Vec::new() },
);
}
}
}
}
let mut out = BTreeMap::new();
walk(repo_root, &mut out, 0);
out
}
/// ★ **EVERY DECLARED ATOM IS A MATRIX ROW.** Five atoms, all tool, all
/// not-applicable, and nothing else.
#[test]
fn every_declared_atom_is_a_matrix_row() {
let set = set();
assert_eq!(
set.names(),
vec!["osm-katana", "lbunzip2", "lgz", "ljar", "lzip"],
"znippy-zoomies declares exactly the five atoms of the approved matrix, in matrix order"
);
assert!(matrix_problems(&set).is_empty(), "{:?}", matrix_problems(&set));
// Non-vacuous: an empty declaration would satisfy `is_empty()` for the wrong reason.
assert_eq!(set.variants.len(), 5, "five atoms inspected, not zero");
// The container axis is EMPTY. `[[build.container]]` cannot carry a `suites` tag
// at all, so a declared container would be a cell outside the set.
assert!(
set.container_names().is_empty(),
"containers are not on the suite axis; declared: {:?}",
set.container_names()
);
// ── RED-WHEN-BROKEN (a): the LIBRARIES, which are not deliverables and must not
// be declarable as atoms. `gatling` (package `rotaryengine`), `linflate`,
// `znippy-zip-core` and the root crate itself are linked by skade and znippy with
// their own feature selection; `cargo build -p rotaryengine` is not a shipment.
let libs = BuildVariantSet::from_toml_str(
r#"
[build]
base_suite = "ORIGINAL"
[[build.variant]]
name = "osm-katana"
role = "tool"
default = true
suites = ["ORIGINAL"]
package = "osm-katana"
bin = "osm-katana"
kind = "exe"
linkage = "not-applicable"
profile = "release"
[[build.variant]]
name = "gatling"
role = "library"
suites = ["ORIGINAL"]
package = "rotaryengine"
kind = "lib"
linkage = "not-applicable"
profile = "release"
[[build.variant]]
name = "linflate"
role = "library"
suites = ["ORIGINAL"]
package = "linflate"
kind = "lib"
linkage = "not-applicable"
profile = "release"
[[build.variant]]
name = "znippy-zip-core"
role = "library"
suites = ["ORIGINAL"]
package = "znippy-zip-core"
kind = "lib"
linkage = "not-applicable"
profile = "release"
"#,
)
.expect("parse a library-bearing declaration");
let problems = matrix_problems(&libs);
assert_eq!(problems.len(), 3, "all three libraries reported: {problems:?}");
for lib in ["gatling", "linflate", "znippy-zip-core"] {
assert!(
problems.iter().any(|p| p.contains(&format!("atom '{lib}'"))
&& p.contains("not a row of the build matrix")),
"'{lib}' must be reported off-matrix: {problems:?}"
);
}
// ── RED-WHEN-BROKEN (b): a MATRIX-NAMED atom that LIES about its own row. The
// `lzip` row is the sharp one — atom `lzip`, package `lzip-parallel`, bin `lzip`
// — and a declaration that assumes atom == package == bin gets TWO of the three
// wrong while still passing a name-membership check.
let lying = BuildVariantSet::from_toml_str(
r#"
[build]
base_suite = "ORIGINAL"
[[build.variant]]
name = "lzip"
role = "client"
default = true
suites = ["ORIGINAL"]
package = "lzip"
bin = "lzip-parallel"
kind = "exe"
linkage = "thin"
features = ["gen"]
profile = "release"
"#,
)
.expect("parse");
let problems = matrix_problems(&lying);
assert_eq!(problems.len(), 5, "role + linkage + package + bin + features: {problems:?}");
assert!(problems[0].contains("role Some(Client) but the matrix says Tool"), "{}", problems[0]);
assert!(
problems[1].contains("linkage ThinStandalone but the matrix says NotApplicable"),
"{}",
problems[1]
);
assert!(problems[2].contains("package Some(\"lzip\")"), "{}", problems[2]);
assert!(problems[3].contains("bin Some(\"lzip-parallel\")"), "{}", problems[3]);
assert!(problems[4].contains("features [\"gen\"]"), "{}", problems[4]);
}
/// The declaration validates, names one normal case, and MATERIALIZES the exact cargo
/// argv the xtask hands cargo for each of the five.
#[test]
fn build_variants_discover_and_validate() {
let set = set();
set.validate_all().expect("znippy-zoomies' declared build variants validate");
assert!(set.check_defaults().is_empty(), "{:?}", set.check_defaults());
assert_eq!(
set.default_for_role(Some(Role::Tool)).map(|v| v.name.as_str()),
Some("osm-katana"),
"the ⭐ atom is the converter — the one anybody runs on purpose"
);
for v in &set.variants {
assert_eq!(v.kind, ArtifactKind::Exe, "atom '{}': a plain executable", v.name);
assert_eq!(v.profile, Profile::Release, "atom '{}'", v.name);
assert!(v.no_default_features, "atom '{}': the closure is stated, not inherited", v.name);
assert!(
v.embeds.is_empty() && v.reaches.is_empty(),
"atom '{}': a decompressor has no sibling edges at all",
v.name
);
}
// ★ The materialized argv for the two atoms whose names disagree with their
// package or bin. These are the exact strings that would have been wrong had the
// roster been hardcoded from the atom names.
assert_eq!(
set.get("lbunzip2").expect("lbunzip2").cargo_args(),
vec!["build", "-p", "lbzip2", "--bin", "lbunzip2", "--no-default-features", "--profile", "release"],
"atom lbunzip2 builds package lbzip2"
);
assert_eq!(
set.get("lzip").expect("lzip").command_line(),
"cargo build -p lzip-parallel --bin lzip --no-default-features --profile release",
"atom lzip builds package lzip-parallel"
);
// …and every atom's command line is DISTINCT, which is what says five atoms are
// five builds rather than one build named five times.
let lines: BTreeSet<String> = set.variants.iter().map(|v| v.command_line()).collect();
assert_eq!(lines.len(), 5, "five distinct cargo invocations: {lines:?}");
}
/// ★ **Every declared atom is the LEAN default build, measured from the manifests.**
///
/// `no_default_features = true` on all five is a statement of fact today — none of
/// the five packages declares a non-empty Cargo `default` — and this is what checks
/// that rather than assuming it. If somebody gives `ljar` a `default = ["zlib-ng"]`
/// tomorrow, the declaration silently starts building something different from what
/// the manifest says, and this goes red instead.
#[test]
fn every_atom_is_the_lean_default_build() {
let set = set();
let tables = BuildVariantSet::cargo_feature_tables(&repo_root()).expect("walk the manifests");
// Non-vacuous: the walk must have found real feature tables.
assert!(
tables.get("ljar").map(|t| !t.features.is_empty()).unwrap_or(false),
"the manifest walk found no [features] for ljar — the oracle is empty: {:?}",
tables.keys().collect::<Vec<_>>()
);
for v in &set.variants {
let pkg = v.package.as_deref().expect("every atom names a package");
let t = tables
.get(pkg)
.unwrap_or_else(|| panic!("atom '{}' names package '{pkg}', which has no manifest", v.name));
assert!(
v.features.is_empty(),
"atom '{}' enables {:?}, but this matrix has no feature column — if a feature is \
genuinely wanted, add it to the matrix and to `[build] offers` rather than here",
v.name,
v.features
);
assert!(
t.default.is_empty(),
"package '{pkg}' now declares default features {:?} — atom '{}' says \
`no_default_features = true`, so the shipped binary would LOSE them. Decide which, \
and say so in the matrix",
t.default,
v.name
);
}
// ljar's `gen` is the one that must never be on: it pulls zip + miniz_oxide, the
// third-party rivals this repo exists to beat.
assert!(
tables.get("ljar").expect("ljar").features.contains_key("gen"),
"the `gen` feature must exist for the assertion below to mean anything"
);
assert!(
!set.get("ljar").expect("ljar").features.contains(&"gen".to_string()),
"the shipped ljar must not carry `gen`"
);
}
/// ★ **A `tool` never claims a service linkage.**
///
/// `role = "tool"` means there is no server anywhere in the picture — these are
/// decompressors you run, that exit. So `fat` / `thin` / `mixed` is not a lesser
/// answer, it is a FALSE one: each is a positive claim about a relationship to a
/// daemon that does not exist.
///
/// And the failure is silent by default: `ServiceShape::default()` is `FatService`,
/// so an OMITTED `linkage` reads as "self-contained, shut every other server down and
/// it still runs" — a claim nobody wrote, indistinguishable from a forgotten field.
#[test]
fn a_tool_atom_never_claims_a_service_linkage() {
let set = set();
let tools: Vec<&str> = set
.variants
.iter()
.filter(|v| v.role == Some(Role::Tool))
.map(|v| v.name.as_str())
.collect();
assert_eq!(tools.len(), 5, "all five atoms are tools: {tools:?}");
for v in &set.variants {
assert_eq!(v.role, Some(Role::Tool), "atom '{}' is not a tool", v.name);
assert_eq!(
v.shape,
ServiceShape::NotApplicable,
"atom '{}' is a tool but claims linkage {:?} — a tool has no server to be fat or \
thin against; say `linkage = \"not-applicable\"`",
v.name,
v.shape
);
}
// RED-WHEN-BROKEN (a): an OMITTED linkage parses to `fat`. This is the whole
// argument for stating the field, asserted rather than believed.
let silent = BuildVariantSet::from_toml_str(
"[build]\nbase_suite = \"ORIGINAL\"\n\
[[build.variant]]\nname = \"lgz\"\nrole = \"tool\"\ndefault = true\n\
suites = [\"ORIGINAL\"]\npackage = \"lgz\"\nbin = \"lgz\"\nkind = \"exe\"\n\
profile = \"release\"\n",
)
.expect("parse");
assert_eq!(
silent.variants[0].shape,
ServiceShape::FatService,
"an omitted linkage MUST read as fat — if that ever changes, the argument for stating \
the field goes away and this test should be rewritten, not deleted"
);
assert_ne!(
silent.variants[0].shape,
ServiceShape::NotApplicable,
"'undeclared' and 'not-applicable' must not be the same value, or the field says nothing"
);
// RED-WHEN-BROKEN (b): a tool naming a linkage out loud.
let claiming = BuildVariantSet::from_toml_str(
"[build]\nbase_suite = \"ORIGINAL\"\n\
[[build.variant]]\nname = \"lgz\"\nrole = \"tool\"\ndefault = true\n\
suites = [\"ORIGINAL\"]\npackage = \"lgz\"\nbin = \"lgz\"\nkind = \"exe\"\n\
linkage = \"mixed\"\nprofile = \"release\"\n",
)
.expect("parse");
let bad: Vec<&str> = claiming
.variants
.iter()
.filter(|v| v.role == Some(Role::Tool) && v.shape != ServiceShape::NotApplicable)
.map(|v| v.name.as_str())
.collect();
assert_eq!(bad, vec!["lgz"], "a tool claiming 'mixed' must be reported");
}
/// ★ **Every declared `bin` must be a `[[bin]]` cargo can actually build**, and the
/// oracle is WALKED OUT of the manifests.
///
/// Non-vacuity here is load-bearing in a way it is not in the sibling repos: two of
/// the five atoms (`lbunzip2`, `lzip`) were `src/bin/*.rs` AUTO-DISCOVERED targets
/// until 2026-08-03, which `cargo_bin_targets` cannot see — it parses `[[bin]] name`
/// and the implicit `src/main.rs` bin. They would have looked like phantoms to this
/// guard while building perfectly. The fix was to declare them in their manifests
/// (not to weaken the check), and these two names are asserted present below so the
/// fix cannot silently be reverted.
#[test]
fn every_declared_bin_is_a_real_cargo_target() {
let set = set();
let real = BuildVariantSet::cargo_bin_targets(&repo_root()).expect("walk the manifests");
// Non-vacuous, and specifically about the two that were invisible before.
for must in ["osm-katana", "lbunzip2", "lgz", "ljar", "lzip"] {
assert!(
real.contains(&must.to_string()),
"the manifest walk did not find '{must}' — if it went back to being an \
auto-discovered src/bin/*.rs target, declare its [[bin]]. Found: {real:?}"
);
}
assert!(set.check_bins_declared(&real).is_empty(), "{:?}", set.check_bins_declared(&real));
// RED-WHEN-BROKEN, twice. (a) an oracle missing the declared bins…
let wrong = set.check_bins_declared(&["osm-katana"]);
assert_eq!(wrong.len(), 4, "the other four report: {wrong:?}");
assert!(wrong[0].contains("no `[[bin]]` target exists"), "{}", wrong[0]);
// …(b) and an EMPTY oracle must be reported rather than passing vacuously, which
// is what a silently-failing manifest walk would look like.
let empty: [&str; 0] = [];
let vacuous = set.check_bins_declared(&empty);
assert_eq!(vacuous.len(), 1, "{vacuous:?}");
assert!(vacuous[0].contains("VACUOUSLY"), "{}", vacuous[0]);
}
/// ★ **Every `[[bin]]` in the repo is either a matrix atom or a named bench helper.**
///
/// The half of the roster question the sibling check cannot answer: `check_bins_
/// declared` walks declaration → manifest, and this walks manifest → declaration. A
/// binary that exists and is in neither list is not "fine because nobody declared
/// it" — it is undecided, and an undeclared bin looks exactly like a
/// deliberately-unbuilt one on disk.
#[test]
fn every_binary_in_the_repo_is_accounted_for() {
let set = set();
let bins = bin_targets(&repo_root());
// Non-vacuous: the two walks must agree on the roster. They are independent
// parsers of the same manifests, so a disagreement means one of them is broken —
// which is the failure mode that would make either check pass over nothing.
let from_lib: BTreeSet<String> = BuildVariantSet::cargo_bin_targets(&repo_root())
.expect("walk")
.into_iter()
.collect();
let mine: BTreeSet<String> = bins.keys().cloned().collect();
assert_eq!(mine, from_lib, "the two independent manifest walks disagree on the bin roster");
assert!(mine.len() >= 10, "the walk found only {} bins: {mine:?}", mine.len());
let declared: BTreeSet<&str> = set.variants.iter().filter_map(|v| v.bin.as_deref()).collect();
let helpers: BTreeSet<&str> = BENCH_HELPERS.iter().map(|(n, _)| *n).collect();
// `xtask` itself is a bin (this crate), and it is not part of the repo's own
// workspace — but the walk sees it, so it is named here rather than filtered
// silently.
let tooling: BTreeSet<&str> = BTreeSet::from(["xtask"]);
let unaccounted: Vec<&String> = bins
.keys()
.filter(|b| {
!declared.contains(b.as_str())
&& !helpers.contains(b.as_str())
&& !tooling.contains(b.as_str())
})
.collect();
assert!(
unaccounted.is_empty(),
"binaries that are neither a matrix atom nor a named bench helper: {unaccounted:?} — \
decide which each is. A bin nobody decided about ships or does not ship by accident."
);
// Every named helper must actually EXIST, or the list is stale fiction that makes
// the check above weaker for free.
for (h, why) in BENCH_HELPERS {
assert!(
bins.contains_key(h),
"BENCH_HELPERS names '{h}' ({why}) but no such [[bin]] exists — remove the entry \
rather than leaving a hole in the accounting"
);
}
// …and no helper may also be a declared atom, which would make it both.
for (h, _) in BENCH_HELPERS {
assert!(!declared.contains(h), "'{h}' is both a bench helper and a matrix atom");
}
}
/// ★ **`required-features` must not silently un-build a declared atom.**
///
/// `cargo build --all-targets` SKIPS a target whose required features are off and
/// still exits 0, so a green workspace build is not evidence that any particular
/// binary was produced. modgunn hit the same shape from the other side: its only
/// `[[bin]]` requires `warehouse`, so a lean atom naming it could never build.
///
/// This asserts no declared atom names a bin whose `required-features` its own
/// feature set does not satisfy — and it is NOT vacuous, because this repo really
/// does have three `required-features` bins (ljar's `gen`-gated bench trio) that the
/// same walk finds and reports as unsatisfied under the atoms' empty feature sets.
#[test]
fn no_declared_atom_names_a_bin_it_cannot_build() {
let set = set();
let bins = bin_targets(&repo_root());
// Non-vacuous: the walk must be able to SEE a required-features bin at all. If
// this ever finds none, the check below passes over a world with no gates in it
// and proves nothing.
let gated: Vec<&String> =
bins.iter().filter(|(_, t)| !t.required_features.is_empty()).map(|(n, _)| n).collect();
assert_eq!(
gated.len(),
3,
"expected ljar's three gen-gated bench bins; found {gated:?}"
);
for g in ["bench_inflate_cmp", "bench_large", "gen_large_zip"] {
assert_eq!(
bins[g].required_features,
vec!["gen".to_string()],
"'{g}' must still be gated on `gen`"
);
assert_eq!(bins[g].package, "ljar");
}
// The real check: every declared atom satisfies its bin's gate (here, every gate
// is empty — which is a FACT about the five, not an assumption).
for v in &set.variants {
let bin = v.bin.as_deref().expect("every atom names a bin");
let t = bins
.get(bin)
.unwrap_or_else(|| panic!("atom '{}' names bin '{bin}', which no manifest declares", v.name));
assert_eq!(
t.package,
v.package.clone().unwrap_or_default(),
"atom '{}' says package {:?}, but bin '{bin}' is declared by '{}'",
v.name,
v.package,
t.package
);
let unmet: Vec<&String> =
t.required_features.iter().filter(|r| !v.features.contains(r)).collect();
assert!(
unmet.is_empty(),
"atom '{}' builds bin '{bin}', which requires {unmet:?} that the atom does not \
enable — `cargo build --bin {bin}` would ERROR, and `--all-targets` would SKIP it \
and still exit 0",
v.name
);
}
// RED-WHEN-BROKEN: the same rule applied to an atom that names one of the gated
// bins without turning `gen` on. This is the modgunn shape, and it must report.
let gate = &bins["bench_inflate_cmp"].required_features;
let no_features: Vec<String> = Vec::new();
let unmet: Vec<&String> = gate.iter().filter(|r| !no_features.contains(r)).collect();
assert_eq!(unmet, vec!["gen"], "an atom with no features cannot build a gen-gated bin");
}
/// ★ **No two atoms write the same file** ([`BuildVariantSet::check_bins`]).
///
/// Clean here, and — unlike modgunn, where exactly one atom declared a bin so nothing
/// COULD collide — this repo has five atoms all declaring bins, so the empty result
/// is earned rather than structural. The RED case still drives the method on a
/// deliberate collision, because "five distinct names today" is not a guarantee about
/// the sixth.
#[test]
fn no_two_atoms_emit_the_same_binary() {
let set = set();
let with_bins = set.variants.iter().filter(|v| v.bin.is_some()).count();
assert_eq!(with_bins, 5, "five atoms declare a bin, so a collision is possible in principle");
assert!(set.check_bins().is_empty(), "{:?}", set.check_bins());
// RED-WHEN-BROKEN: two atoms on one artifact path. This is the korp/nornir/dwarves
// defect — two build points, one file, and nothing on disk saying which you have.
let colliding = BuildVariantSet::from_toml_str(
r#"
[build]
base_suite = "ORIGINAL"
[[build.variant]]
name = "lgz"
role = "tool"
default = true
suites = ["ORIGINAL"]
package = "lgz"
bin = "lgz"
kind = "exe"
linkage = "not-applicable"
profile = "release"
[[build.variant]]
name = "lgz-timing"
role = "tool"
suites = ["ORIGINAL"]
package = "lgz"
bin = "lgz"
kind = "exe"
linkage = "not-applicable"
features = ["timing"]
profile = "release"
"#,
)
.expect("parse the colliding pair");
let problems = colliding.check_bins();
assert_eq!(problems.len(), 1, "one collision, one message: {problems:?}");
assert!(problems[0].contains("SAME artifact"), "{}", problems[0]);
assert!(problems[0].contains("lgz, lgz-timing"), "it names both: {}", problems[0]);
}
/// ★ **The suite tag** — `suites = ["ORIGINAL"]` on every atom, `base_suite` in
/// `[build]`, and `ORIGINAL` is the only name here.
///
/// `check_suites()` returning empty is CORRECT below two deliveries, not a pass, and
/// `declares_suites()` is what tells "checked and fine" from "there was nothing to
/// check". That distinction is the entire history of this repo: until 2026-08-03
/// there was **no declaration file at all**, so the honest RED case is discovery
/// finding nothing — asserted below against a directory that has no
/// `.nornir/build-variants.toml`.
#[test]
fn every_atom_is_tagged_into_the_one_delivery() {
let set = set();
assert!(set.check_suites().is_empty(), "{:?}", set.check_suites());
assert!(
set.declares_suites(),
"check_suites() is empty EITHER because the tags are fine OR because there are none — \
this is what tells the two apart"
);
assert_eq!(set.suites(), vec!["ORIGINAL"], "one delivery, named — and only one");
assert_eq!(set.base_suite.as_deref(), Some("ORIGINAL"));
for v in &set.variants {
assert_eq!(
v.suites,
vec!["ORIGINAL".to_string()],
"atom '{}' is untagged, so `--suite ORIGINAL` would not build it — and under 'the \
tag is what makes it a Build Thing' it would not be one at all",
v.name
);
}
// RED-WHEN-BROKEN (a): the state this repo was in until 2026-08-03 — NO
// declaration file. Discovery must return `None` rather than an empty set, so a
// caller cannot mistake "declares nothing" for "declares nothing wrong".
let nowhere = repo_root().join("xtask");
assert!(
BuildVariantSet::discover(&nowhere).expect("discover must not error").is_none(),
"a directory with no .nornir/build-variants.toml must discover to None"
);
// RED-WHEN-BROKEN (b): atoms with no tag at all — `check_suites` stays empty and
// `declares_suites` is what goes red.
let untagged = BuildVariantSet::from_toml_str(
"[build]\n\
[[build.variant]]\nname = \"lgz\"\nrole = \"tool\"\ndefault = true\n\
package = \"lgz\"\nbin = \"lgz\"\nkind = \"exe\"\nlinkage = \"not-applicable\"\n",
)
.expect("parse");
assert!(untagged.check_suites().is_empty(), "check_suites cannot see an untagged file");
assert!(!untagged.declares_suites(), "an untagged declaration must NOT claim a delivery");
// …and a BLANK tag is a delivery with no name, indistinguishable from none.
let blank = BuildVariantSet::from_toml_str(
"[build]\nbase_suite = \"ORIGINAL\"\n\
[[build.variant]]\nname = \"lgz\"\nsuites = [\"\"]\ndefault = true\n",
)
.expect("parse");
let problems = blank.check_suites();
assert_eq!(problems.len(), 1, "{problems:?}");
assert!(problems[0].contains("BLANK suite name"), "{}", problems[0]);
}
/// ★ **`--suite` must SELECT**, and a library must not resolve as an atom.
#[test]
fn the_one_build_verb_resolves_this_repos_delivery() {
let set = set();
let args = suite_cli::parse(&["--suite", "ORIGINAL"]).expect("parse");
let (suite, atoms) = suite_cli::resolve(&set, &args).expect("ORIGINAL resolves");
assert_eq!(suite, "ORIGINAL");
assert_eq!(
atoms.iter().map(|v| v.name.as_str()).collect::<Vec<_>>(),
vec!["osm-katana", "lbunzip2", "lgz", "ljar", "lzip"],
"exactly the declared atoms, in declaration order"
);
let one = suite_cli::parse(&["--suite", "ORIGINAL", "--atom", "lbunzip2"]).expect("parse");
let (_, just_one) = suite_cli::resolve(&set, &one).expect("lbunzip2 resolves");
assert_eq!(just_one.len(), 1);
assert_eq!(
just_one[0].command_line(),
"cargo build -p lbzip2 --bin lbunzip2 --no-default-features --profile release"
);
// RED-WHEN-BROKEN: an unknown delivery is a hard error that lists the real one.
for unknown in ["NOPE", "MVP"] {
let bad = suite_cli::parse(&["--suite", unknown]).expect("parse");
let err = suite_cli::resolve(&set, &bad).expect_err("an unknown suite must not shrug");
let msg = err.to_string();
assert!(msg.contains("no such delivery"), "{msg}");
assert!(msg.contains("ORIGINAL"), "it must name the declared delivery: {msg}");
}
// …and the libraries + the bench helpers must fail HERE rather than resolve to
// something that builds nothing.
for ghost in [
"gatling",
"rotaryengine",
"linflate",
"znippy-zip-core",
"znippy-zoomies",
"zstd-sys-rs",
"vtd_bench",
"planet_bench",
"gen_large_zip",
"lzip-parallel",
] {
let g = suite_cli::parse(&["--suite", "ORIGINAL", "--atom", ghost]).expect("parse");
let err = suite_cli::resolve(&set, &g).expect_err("a non-atom must not resolve");
// Assert what the CALLER needs out of the refusal, not the noun the shared
// crate happens to use for a row this week. This line read
// `contains("no such atom")` and was RED on main from the day build-thing
// renamed atom → variant in its own message: a passing test turned red by a
// rewording, which is what an assertion tied to prose is worth. What must
// hold is that the refusal NAMES the thing that does not exist and LISTS the
// ones that do, so the command can be fixed from the message alone.
let msg = err.to_string();
assert!(msg.contains(ghost), "the refusal must name what was asked for: {msg}");
for real in ["osm-katana", "lbunzip2", "lgz", "ljar", "lzip"] {
assert!(msg.contains(real), "{ghost}: the refusal must list `{real}`: {msg}");
}
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// THE FEATURE AXIS — the direction every check above is blind to
// ═══════════════════════════════════════════════════════════════════════════════
//
// Everything above walks ATOMS: is each declared row a real cargo target, does its
// argv come out right, does no bin escape the matrix. All five rows are
// `features = []`, and every one of those checks asserts that they stay that way.
//
// So the whole feature table of this repo sits outside every question asked here —
// and the shared gate written for exactly that question, `FeatureAxis::gate`, is
// blind on this repo too: it is a verdict on the `[build] offers` space, and this
// repo declares none (deliberately: five independent crates with disjoint feature
// tables cannot share one flat list). `unbuilt` and `unoffered` are then empty BY
// CONSTRUCTION, so it returned `Ok(())` while nine declared features were built by
// nothing. That is not a repo passing a check, it is a check with no input.
//
// `FeatureAxis::manifest_gate` is the same module's answer over the half that still
// has one — the `Cargo.toml` direction — and the two tests below hold it to being a
// real measurement rather than another green.
/// **THE GATE: every feature this repo declares is built by a variant, or has a
/// written reason in `[build.allow_unbuilt]` saying why nothing compiles it.**
///
/// Compiles nothing: a manifest read and two set differences, so unlike a matrix
/// build it is always on. A gate slow enough to skip gets skipped.
#[test]
fn every_declared_feature_is_built_or_written_down() {
let set = set();
let manifest = nornir_build_thing::feature_axis::manifest_features(&repo_root());
let axis = nornir_build_thing::FeatureAxis::with_manifest_features(
"znippy-zoomies",
&set,
Some(&manifest),
);
if let Err(rot) = axis.manifest_gate() {
panic!(
"znippy-zoomies' feature axis is rotting.\n\n{rot}\n\
Fix, in order of preference: (1) DELETE the feature, if it gates no \
`cfg` site and pulls no dependency — that is what happened to \
`vann-mmap` and `pmtiles` on 2026-08-22 and it is the right answer far \
more often than it looks; (2) declare a `[[build.variant]]` that enables \
it, if a delivered artifact should contain it; (3) write a line in \
`[build.allow_unbuilt]` saying in words why nothing compiles it. An \
empty reason is not a reason, and an excuse for a feature that is built \
now, or that no longer exists, fails here too."
);
}
}
/// **The gate is not vacuous**, in the three ways it could be.
///
/// (a) the manifest scan really saw this repo's feature tables — an empty oracle
/// would make (a) trivially green; (b) the excuse list is not doing the work alone —
/// take one line away and the gate names the feature it excused; (c) the check being
/// reused is the one that can see this repo at all: `gate()` is asserted GREEN here
/// while `manifest_gate()` on the same axis, minus the allowlist, is RED. If those
/// two ever agree, the wrong one is wired.
#[test]
fn the_feature_gate_can_report_red() {
let set = set();
let manifest = nornir_build_thing::feature_axis::manifest_features(&repo_root());
// (a) the oracle is real, and it is the repo's own table.
assert!(
manifest.len() >= 7,
"the manifest scan found only {} features — it is not seeing the member \
crates: {manifest:?}",
manifest.len()
);
for expect in ["timing", "zlib-ng", "gen", "search-index", "planet-fixture", "testmatrix"] {
assert!(manifest.contains(expect), "the scan missed `{expect}`: {manifest:?}");
}
// The two deleted flags must NOT come back without a reason being written.
for gone in ["vann-mmap", "pmtiles"] {
assert!(
!manifest.contains(gone),
"`{gone}` was deleted on 2026-08-22 because it gated zero cfg sites. If it \
is back, it must gate something and be built or excused — remove this line \
then, deliberately."
);
}
let axis = nornir_build_thing::FeatureAxis::with_manifest_features(
"znippy-zoomies",
&set,
Some(&manifest),
);
// (c) the blind spot this gate exists for, asserted rather than described:
// NOT ONE feature is built by a variant, and the offers gate is happy anyway.
assert!(axis.offers.is_empty(), "precondition: this repo declares no `offers`");
assert!(
axis.built.is_empty(),
"precondition: every atom is the lean default build, so no variant enables \
anything: {:?}",
axis.built
);
assert!(
axis.gate().is_ok(),
"THE BLIND SPOT, still there: the offers gate passes a repo that builds none \
of its {} features. That is why `manifest_gate` is the one wired above.",
manifest.len()
);
assert_eq!(
axis.manifest_unbuilt.len(),
manifest.len(),
"and the manifest direction sees all of them"
);
// (b) drop each excuse in turn: the gate must name exactly that feature.
let excused: Vec<String> = axis.allow_unbuilt.keys().cloned().collect();
assert!(!excused.is_empty(), "the allowlist is empty — (b) would be vacuous");
for feat in &excused {
let mut thinner = set.clone();
thinner.allow_unbuilt.remove(feat);
let a = nornir_build_thing::FeatureAxis::with_manifest_features(
"znippy-zoomies",
&thinner,
Some(&manifest),
);
let rot = a
.manifest_gate()
.expect_err("dropping an excuse must go RED");
assert_eq!(
rot.rotting,
vec![feat.clone()],
"dropping `{feat}` must name `{feat}` and nothing else"
);
}
// …and an excuse for a feature nobody declares is rot in the other direction.
let mut ghost = set.clone();
ghost
.allow_unbuilt
.insert("a-flag-that-was-deleted".into(), "left behind".into());
let rot = nornir_build_thing::FeatureAxis::with_manifest_features(
"znippy-zoomies",
&ghost,
Some(&manifest),
)
.manifest_gate()
.expect_err("an excuse for nothing must go RED");
assert_eq!(rot.unknown_allowlist, vec!["a-flag-that-was-deleted"]);
}