facett-core/tests/gated_tests_actually_run.rs
//! **A feature-gated test file that nothing switches on is not a passing test —
//! it is no test.**
//!
//! A `tests/*.rs` whose crate-level `#![cfg(feature = "…")]` is unsatisfied
//! compiles to an empty binary that prints `0 tests, 0 benchmarks` and exits 0.
//! That output is byte-for-byte the shape of a clean run. Measured on this repo,
//! 2026-08-03:
//!
//! ```text
//! $ cargo test -p facett-map --test upload_replaces_geometry -- --list
//! 0 tests, 0 benchmarks <-- the whole file, silent
//!
//! $ cargo test -p facett-map -p facett-demo --test upload_replaces_geometry -- --list
//! a_re_bake_replaces_the_uploaded_geometry_instead_of_adding_to_it: test
//! a_re_bake_with_more_ways_also_lands_exactly_the_new_set: test
//! 2 tests, 0 benchmarks
//! ```
//!
//! No `--features` flag in either command. The difference is **feature
//! unification**: `facett-demo`'s default features reach `facett/map-wgpu` →
//! `facett-map/wgpu`, so selecting it turns the GPU lane on for the whole
//! resolve. That is also why `cargo test --workspace` — the command nornir's
//! release pipeline runs (`nornir/src/release/pipeline.rs:617`,
//! `cargo test --workspace --no-fail-fast -j 1`) — does run facett-map's GPU
//! guards today.
//!
//! It runs them **by accident**. Nothing in this repo declares that it must, and
//! grep finds no invocation anywhere that spells `--features wgpu` for
//! facett-map outside prose in `.nornir/*.md`. One edit to an unrelated crate's
//! default feature list and every GPU-lane guard in facett-map goes back to
//! `0 tests, 0 benchmarks` with nothing to notice it — including
//! `upload_replaces_geometry`, which guards the VRAM leak where a re-bake ADDED
//! geometry instead of replacing it (200 ways then 40 ways left six chunks where
//! an upload should leave one).
//!
//! This file is what notices.
//!
//! Proving it red took cutting **three** independent routes, which is worth
//! recording because it is better news than the premise:
//! 1. `facett-demo`'s `default = ["map-wgpu", …]`,
//! 2. `facett-demo`'s unconditional `facett = { features = ["map-wgpu", …] }`
//! (two sites — native and wasm),
//! 3. `facett-map3d/wgpu` → `facett-map/wgpu`, reached via `map3d-wgpu`.
//!
//! Cutting one or two leaves the lane running. Cutting all three drops
//! `facett-map` to `features: ["default"]` and this test names all twenty
//! silenced functions.
//!
//! Run: `cargo test -p facett-core --test gated_tests_actually_run`
use facett_core::law;
use std::path::{Path, PathBuf};
/// Lanes whose gated tests must be reachable from the **plain workspace test
/// run**, not merely declared somewhere.
///
/// Being on this list is a stronger claim than having an arm in
/// `.nornir/testmatrix-arms.json`. An arm is a declaration that some *separate*
/// command could run the lane; `nornir_testmatrix::verify_arm` only ever builds
/// it with `--no-run`. Membership here says the lane is compiled and **executed**
/// by `cargo test --workspace`, which is the one command that actually runs on
/// this repo unattended.
///
/// Only `facett-map/wgpu` is locked today, deliberately. The other GPU lanes
/// (facett-core, facett-graph3d, facett-helix, facett-map3d) are legitimately
/// arm-only: their crates' features are not reached by any member's defaults,
/// which is the design recorded in `.nornir/testmatrix-arms.json` — the CPU
/// painter is the default path so a headless/tank/wasm build still renders.
/// facett-map is different: `facett-demo` already pulls its lane in, korp
/// declares `facett-map = { features = ["wgpu"] }` unconditionally, and the
/// twenty test functions behind it are every GPU-lane guard the crate has.
const LANES_THE_WORKSPACE_RUN_MUST_COVER: &[(&str, &str)] = &[("facett-map", "wgpu")];
fn root() -> PathBuf {
law::workspace_root(Path::new(env!("CARGO_MANIFEST_DIR")))
}
/// `.nornir/testmatrix-arms.json` → the `(package, feature)` pairs it declares.
fn declared_arms(root: &Path) -> Vec<(String, String)> {
let path = root.join(".nornir/testmatrix-arms.json");
let Ok(text) = std::fs::read_to_string(&path) else { return Vec::new() };
let doc: serde_json::Value = match serde_json::from_str(&text) {
Ok(d) => d,
Err(e) => panic!("{} is not valid JSON: {e}", path.display()),
};
let mut out = Vec::new();
for arm in doc["arms"].as_array().into_iter().flatten() {
let Some(pkg) = arm["package"].as_str() else { continue };
for f in arm["features"].as_array().into_iter().flatten() {
if let Some(f) = f.as_str() {
out.push((pkg.to_string(), f.to_string()));
}
}
}
out
}
#[test]
fn every_feature_gated_test_file_is_reachable_somehow() {
let root = root();
let md = law::cargo_metadata(&root).expect("cargo metadata");
let arms = declared_arms(&root);
assert!(
!arms.is_empty(),
"{}/.nornir/testmatrix-arms.json declares no arms — either it moved or it was \
emptied, and this guard would then pass every gated file that has a workspace \
route while silently un-covering the arm-only ones.",
root.display(),
);
let mut gated_total = 0usize;
let mut whole_file_seen = 0usize;
let mut per_fn_seen = 0usize;
let mut any_cfgs: Vec<String> = Vec::new();
let mut orphans: Vec<String> = Vec::new();
for member in law::workspace_members(&root) {
let dir = root.join(&member);
// Crate name == directory name across this workspace; assert it rather
// than assume it, or a rename turns every check below into a no-op.
let manifest = dir.join("Cargo.toml");
let Ok(mtext) = std::fs::read_to_string(&manifest) else { continue };
let pkg = mtext
.lines()
.find_map(|l| l.trim().strip_prefix("name = "))
.map(|n| n.trim().trim_matches('"').to_string())
.unwrap_or_else(|| member.clone());
for (f, line) in law::any_feature_cfgs(&dir) {
any_cfgs.push(format!(
" {}: {line}",
f.strip_prefix(&root).unwrap_or(&f).display()
));
}
for gated in law::gated_test_files(&dir) {
gated_total += 1;
let in_workspace_run = law::workspace_features(&md, &pkg)
.map(|fs| fs.contains(&gated.feature))
.unwrap_or(false);
let has_arm = arms.iter().any(|(p, f)| *p == pkg && *f == gated.feature);
if gated.whole_file {
whole_file_seen += 1;
} else {
per_fn_seen += 1;
}
if !in_workspace_run && !has_arm {
let shape = if gated.whole_file {
format!(
"`#![cfg(feature = \"{}\")]` on the whole file, {} test fn(s) that \
print `0 tests, 0 benchmarks`",
gated.feature, gated.tests
)
} else {
format!(
"{} `#[test]` fn(s) carry a per-fn `#[cfg(feature = \"{}\")]` — the \
target still reports `ok` and they are not even counted as \
`filtered out`",
gated.tests, gated.feature
)
};
orphans.push(format!(
" {} — {}\n not enabled by any member's default \
features (so `cargo test --workspace` skips it) and no arm \
`{{ \"package\": \"{}\", \"features\": [\"{}\"] }}` in \
.nornir/testmatrix-arms.json",
gated.file.strip_prefix(&root).unwrap_or(&gated.file).display(),
shape,
pkg,
gated.feature,
));
}
}
}
// The scan must have FOUND gated files. facett is a fan of GPU-gated render
// crates; zero would mean the scanner stopped reading, not that the repo got
// clean.
assert!(
gated_total >= 10,
"only {gated_total} feature-gated test entr(ies) found across the workspace — the \
scan is not reading `tests/` any more. This repo had 20+ when the guard was \
written; a low number here is a broken scanner, not a clean repo.",
);
// Liveness for EACH shape separately. A scanner that quietly stopped seeing the
// per-fn shape would keep this test green on the strength of the crate-level one
// alone — which is exactly how the quiet shape went uncounted until 2026-08-22
// (a unit test in `law.rs` had pinned `#[cfg(...)]` on a fn as "not a gate").
// MEASURED that day: 53 whole-file entries, 9 per-fn entries (11 fns, in 5 crates)
// across the workspace.
assert!(
whole_file_seen >= 10,
"{whole_file_seen} crate-level `#![cfg(feature = ...)]` test file(s) found — this \
workspace has ~50; the crate-level arm of the scanner is dead."
);
assert!(
per_fn_seen >= 3,
"{per_fn_seen} file(s) with per-fn `#[cfg(feature = ...)]` `#[test]`s found — \
facett-map alone has 3 (cull_envelope, fill_extent_gate, paint_order_pixels), so \
the per-fn arm of the scanner is dead and the quiet shape is invisible again."
);
// `any(feature = ...)` is a shape `gated_test_files` deliberately does not model:
// the file is reachable through EITHER arm, and reporting it as "requires A" would
// send someone declaring an arm nobody needs. There are none today. If one is
// written, that is a decision, and it has to be a visible one.
assert!(
any_cfgs.is_empty(),
"a test `cfg` uses `any(feature = ...)`, which the gated-test scanner does not \
model — it would be silently treated as ungated. Teach \
`law::required_features_of_cfg` the alternative, or restate the cfg:\n{}",
any_cfgs.join("\n"),
);
assert!(
orphans.is_empty(),
"{} feature-gated test file(s) can NEVER run: no default-feature route to them \
and no declared arm. Their `0 tests, 0 benchmarks` is indistinguishable from a \
pass. Either add an arm to .nornir/testmatrix-arms.json, or give the feature a \
route from a member's defaults:\n{}",
orphans.len(),
orphans.join("\n"),
);
}
#[test]
fn the_gpu_lanes_that_must_run_unattended_still_do() {
let root = root();
let md = law::cargo_metadata(&root).expect("cargo metadata");
let mut lost: Vec<String> = Vec::new();
for (pkg, feature) in LANES_THE_WORKSPACE_RUN_MUST_COVER {
let resolved = law::workspace_features(&md, pkg)
.unwrap_or_else(|| panic!("`{pkg}` is not in this workspace's resolve at all"));
if resolved.iter().any(|f| f == feature) {
continue;
}
// Name the casualties. A count is what makes this legible: these are the
// fns that go from running to printing `0 tests, 0 benchmarks`.
let dir = root.join(pkg);
let silenced: Vec<_> = law::gated_test_files(&dir)
.into_iter()
.filter(|g| g.feature == *feature)
.collect();
let fns: usize = silenced.iter().map(|g| g.tests).sum();
let files = silenced
.iter()
.map(|g| {
format!(
" {} ({} fn)",
g.file.strip_prefix(&root).unwrap_or(&g.file).display(),
g.tests
)
})
.collect::<Vec<_>>()
.join("\n");
lost.push(format!(
" `{pkg}/{feature}` is NOT in the workspace-wide feature resolve, so \
`cargo test --workspace` — the command nornir's release pipeline runs \
(nornir/src/release/pipeline.rs:617) — no longer compiles it.\n \
{} test fn(s) in {} file(s) just went silent:\n{}\n \
resolved features for {pkg} were: {:?}",
fns,
silenced.len(),
files,
resolved,
));
}
assert!(
lost.is_empty(),
"a GPU lane that must run unattended stopped being reachable from the plain \
workspace test run. Nothing spells `--features wgpu` for these crates \
anywhere in this repo (measured 2026-08-03 — grep finds only prose in \
.nornir/*.md), so the ONLY thing that ran them was feature unification from \
another member's default features. Restore that route, or wire a runner that \
genuinely executes the lane:\n{}",
lost.join("\n"),
);
}