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

nordisk/edda

crates/nornir-robotui/tests/watch_wgpu_is_an_alias.rs

//! **The `watch-wgpu` feature is an ALIAS, and this is the guard that keeps the
//! manifest and the prose from disagreeing about it again.**
//!
//! History: the `eframe` dependency line used to read `glow`, so `watch-wgpu` really
//! did pick a different renderer. LAW #4 moved the fleet to WebGPU and put `wgpu` on
//! that line UNCONDITIONALLY — which made `watch-wgpu` a feature that cannot change a
//! single byte of the build, while its own comment still described it as the
//! difference between a WebGPU window and an OpenGL one. Two writers of one fact: the
//! manifest was fixed and the sentences beside it were not.
//!
//! `watch-wgpu` is deliberately KEPT rather than deleted — korp
//! (`Cargo.toml`: `"nornir-robotui/watch-wgpu"`) and facett-demo
//! (`features = ["watch-wgpu"]`) both name it, and korp has a test that asserts this
//! manifest still declares it. Deleting it is a cross-repo change, not a leaf one. So
//! it stays, documented as the no-op alias it is, and these assertions make the alias
//! claim MECHANICAL: the moment the algebra stops matching the sentence, this refuses
//! by name instead of leaving a knife on the receipt that was never used.
//!
//! The whole oracle is the crate's own manifest, read at test time — not a rendered
//! doc string, so nothing that merely *echoes* the words can satisfy it.

use std::path::PathBuf;

fn manifest() -> toml::Value {
    let p = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
    let text = std::fs::read_to_string(&p).expect("read nornir-robotui/Cargo.toml");
    toml::from_str(&text).expect("nornir-robotui/Cargo.toml parses as TOML")
}

fn feature(m: &toml::Value, name: &str) -> Vec<String> {
    m.get("features")
        .and_then(|f| f.get(name))
        .unwrap_or_else(|| panic!("feature `{name}` is declared"))
        .as_array()
        .unwrap_or_else(|| panic!("feature `{name}` is a list"))
        .iter()
        .map(|v| v.as_str().expect("feature entry is a string").to_string())
        .collect()
}

/// `dependencies.eframe.features` — the list that decides which renderer eframe can
/// even build. This is the OTHER writer of the renderer fact.
fn eframe_features(m: &toml::Value) -> Vec<String> {
    m.get("dependencies")
        .and_then(|d| d.get("eframe"))
        .expect("the eframe dependency is declared")
        .get("features")
        .expect("the eframe dependency pins an explicit feature list")
        .as_array()
        .expect("eframe features is a list")
        .iter()
        .map(|v| v.as_str().expect("feature entry is a string").to_string())
        .collect()
}

/// The load-bearing one. `watch-wgpu`'s entire effect over `watch` is `eframe/wgpu`,
/// and `wgpu` is already on the `eframe` line unconditionally — therefore
/// `watch-wgpu` resolves to exactly the same dependency graph as `watch`, and every
/// sentence that calls it a renderer CHOICE is false.
///
/// If `wgpu` ever leaves the `eframe` line, this reds: the alias claim would have
/// become false again and the feature's documentation has to change WITH the
/// manifest, in the same commit, not eight days later.
#[test]
fn watch_wgpu_adds_nothing_that_watch_does_not_already_carry() {
    let m = manifest();
    let watch_wgpu = feature(&m, "watch-wgpu");
    let ef = eframe_features(&m);

    assert!(
        watch_wgpu.iter().any(|f| f == "watch"),
        "`watch-wgpu` must imply `watch` (it is an alias of it), got {watch_wgpu:?}"
    );

    // Everything it adds beyond `watch` itself.
    let extra: Vec<&String> = watch_wgpu.iter().filter(|f| *f != "watch").collect();
    assert_eq!(
        extra,
        vec!["eframe/wgpu"],
        "`watch-wgpu` is documented as a no-op alias of `watch`; its only extra entry \
         may be `eframe/wgpu`, which the eframe line already carries. It now adds \
         {extra:?} — either that entry is a REAL effect, in which case the feature is \
         no longer an alias and its Cargo.toml comment plus mode.rs/watch.rs docs must \
         say what it does, or it is dead weight."
    );

    assert!(
        ef.iter().any(|f| f == "wgpu"),
        "the `eframe` dependency must carry `wgpu` UNCONDITIONALLY (LAW #4: WebGPU \
         everywhere) — that is what makes `watch-wgpu` an alias. eframe features are \
         {ef:?}. If wgpu moved behind the feature, `watch-wgpu` is a real switch again \
         and every doc calling it a no-op alias is now wrong."
    );
}

/// LAW #4, made mechanical rather than left to prose: `glow` is not a feature of this
/// crate and not a feature this crate asks eframe for. `resolve_renderer` returns
/// `eframe::Renderer::Wgpu` unconditionally and `WatchRenderer` has one variant, so a
/// `glow` entry reappearing anywhere in the manifest would re-arm the exact defect
/// (`Renderer::default()` resolves to `Glow` whenever eframe's `glow` feature is on).
#[test]
fn no_glow_anywhere_in_this_crates_manifest() {
    let m = manifest();
    if let Some(features) = m.get("features").and_then(|f| f.as_table()) {
        for (name, entries) in features {
            assert!(
                !name.contains("glow"),
                "feature `{name}` names glow; LAW #4 — this fleet is WebGPU only"
            );
            let list = entries.as_array().cloned().unwrap_or_default();
            for e in list {
                let s = e.as_str().unwrap_or_default();
                assert!(
                    !s.contains("glow"),
                    "feature `{name}` enables `{s}`; LAW #4 — no glow/WebGL"
                );
            }
        }
    }
    assert!(
        !eframe_features(&m).iter().any(|f| f.contains("glow")),
        "the eframe dependency must never ask for `glow` — with it on, eframe's \
         `Renderer::default()` is `Glow`, so the live watch window paints on OpenGL \
         decided by one word in a manifest with nothing in the source saying so."
    );
    // `x11` is deliberately absent too (2026-08-07, Wayland-only) — same shape of
    // by-construction refusal, worth pinning here rather than trusting the comment.
    assert!(
        !eframe_features(&m).iter().any(|f| f == "x11"),
        "`x11` must stay off the eframe line: robot UI is Wayland-only, and NOT \
         compiling the X11 backend is the fix by construction, not a runtime check."
    );
}

/// The second way the stale alias bites: anything *gated on* `cfg(feature =
/// "watch-wgpu")` is gated on a condition indistinguishable from `watch`, so a
/// WebGPU-only path can be compiled out while the wgpu backend is nonetheless active
/// — with no compile error either way. While the feature is an alias, no such gate
/// may exist.
#[test]
fn nothing_is_cfg_gated_on_the_alias() {
    let src = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src");
    let mut offenders = Vec::new();
    walk(&src, &mut |path, text| {
        for (i, line) in text.lines().enumerate() {
            // Only real cfg gates — a doc comment mentioning the name is prose.
            let code = line.split("//").next().unwrap_or("");
            if code.contains("feature = \"watch-wgpu\"") {
                offenders.push(format!("{}:{}", path.display(), i + 1));
            }
        }
    });
    assert!(
        offenders.is_empty(),
        "`watch-wgpu` is an alias of `watch`, so a cfg gate on it compiles exactly \
         when `watch` does — the gate reads as a choice and is not one. Found: {offenders:?}"
    );
}

fn walk(dir: &std::path::Path, f: &mut impl FnMut(&std::path::Path, &str)) {
    let Ok(rd) = std::fs::read_dir(dir) else { return };
    for e in rd.flatten() {
        let p = e.path();
        if p.is_dir() {
            walk(&p, f);
        } else if p.extension().is_some_and(|x| x == "rs") {
            if let Ok(t) = std::fs::read_to_string(&p) {
                f(&p, &t);
            }
        }
    }
}