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

nordisk/facett

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"),
    );
}