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

nordisk/facett

xtask/tests/wasm_bundle_installs_the_lanes_it_selects.rs

//! **The OTHER half of the GPU path: a lane that is selected but never installed.**
//!
//! `wasm_bundle_has_gpu_features.rs` — this file's sibling and the row before it —
//! asserts that `facet-wrapped/Cargo.toml` turns the components' GPU features ON. That
//! is necessary and it is not sufficient, and the gap between the two cost a day.
//!
//! # What was measured, on oden's RTX 4090, 2026-09-06
//!
//! The bundle mounted `osm3d` inside an iframe carrying Streamlit 1.60.0's exact
//! `sandbox`/`allow` strings and reported, off the running page:
//!
//! ```text
//! facet_mounted:      "osm3d"        facet_error:  ""
//! facet_canvas_api:   "webgpu"       backend:      "wgpu-vello"
//! gpu_lane_selected:  true           lane_flag:    "cpu"      ← the defect
//! ```
//!
//! Not `pending` — so a frame really had painted, and it had painted on the CPU
//! painter. **Identically on the 4090 and on SwiftShader**, which is the signature of a
//! fault that is not a property of the adapter at all: a missing function call.
//!
//! Selecting a lane and installing its renderer are two acts and only the first was
//! being done. `with_gpu(true)` swaps the backend — that is what `gpu_lane_selected`
//! and `backend` report. `install_renderer` puts the renderer into the `RenderState`'s
//! `callback_resources`; **without it the paint callback no-ops**, so
//! `facett_map3d::gpu::renderer_installed()` is `false`,
//! `WgpuVelloBackend::paint` reports `used_gpu = false`, and `lane_flag` answers a
//! perfectly honest `cpu`. Before the fix, `facet-wrapped/` contained ZERO occurrences
//! of `install_renderer` in `src/` or `tests/`.
//!
//! Red → green on the same box, same harness, same Chrome flags, two byte-distinct
//! bundles differing by one commit:
//!
//! ```text
//!                       RED f6a408a5…    GREEN 65ba3f1a…
//! lane_flag                  cpu              gpu
//! used_gpu                   false            true
//! fps                        30.48            60.00
//! ```
//!
//! (`visible_triangles` was 8 in BOTH arms and is deliberately not quoted as evidence:
//! it comes from the software geometry oracle that runs on either lane, so it is an
//! identity value here in LAW 2's sense. `fps` is the independent applied signal.)
//!
//! # Why this test is a source-shape test, and what that costs
//!
//! Said plainly rather than glossed: `eframe`/`egui_wgpu` are
//! `[target.'cfg(target_arch = "wasm32")'.dependencies]` of `facet-wrapped`, so the
//! rlib a native `cargo test` links **has no `RenderState` type in it at all** and the
//! mount body cannot be executed on the host. That is also exactly why
//! `facet-wrapped/tests/gpu_lane_is_observable.rs` could pass forever with the install
//! missing: its three assertions (`gpu_lane_selected == true`, `backend !=
//! "cpu-painter"`, `lane_flag == "pending"` before any frame) are all true of a bundle
//! that never dispatches, because on a host with no `RenderState` there is no frame to
//! observe. It proves the lane is WIRED and is structurally incapable of proving
//! anything DISPATCHED.
//!
//! So the host-side guard available is: **the manifest edges (read from cargo's own
//! parse) and the install calls (read from the source) must agree.** It cannot prove a
//! frame reached the GPU — the browser measurement above is what does that, and it is
//! recorded here so the number has a home. It CAN fail, and it fails on exactly the
//! change that caused the defect: deleting an install, or adding a fourth GPU edge to
//! the manifest without an install beside it.

use std::process::Command;

fn root() -> std::path::PathBuf {
    std::path::Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().to_path_buf()
}

/// The GPU edges the bundle declares, and the install each one needs.
///
/// The two graph surfaces share one entry point on purpose: `facett-graph3d` and
/// `facett-graphview` both route their node/edge cloud through facett-core's ONE
/// `graphcloud::cloud` renderer, whose `cloud_renderer_installed()` is what unlocks
/// `Graph3D`'s instanced fast path. Not a coincidence to be tidied away — it is the
/// LAW 5 seam, and a future third graph surface needs no new install.
///
/// The fourth row (2026-09-18) is a different kind of install and the same kind of
/// defect. `facett-graphnav/gpu` selects the compute-shader force layout; what it
/// needs installed is not a renderer but a LOAN of the host's device, because a
/// browser cannot block to make its own. Select the feature without the loan and the
/// selector finds no device — every large graph silently converges on wasm32's one CPU
/// thread, which is the state row 13 of `facet-wrapped-wheel.md` recorded.
/// The map rows (2026-09-28): the 2-D map lane, which `osm2d` (`OsmView`) and
/// `map` (`MapView`) select. It used to be deliberately absent (facett-map on default
/// features); the owner ruled that a map painting on the CPU in a headful browser is a
/// defect, so the manifest now enables it and the install sits beside the others.
/// The graphpan and graphnav `wgpu` rows (2026-09-28) put those node/edge clouds on the
/// same shared `graphcloud::cloud` renderer as the graph surfaces above.
const LANES: [(&str, &str, &str); 12] = [
    ("facett-flow", "wgpu", "facett_flow::gpu::install_renderer"),
    ("facett-pipeline", "wgpu", "facett_flow::gpu::install_renderer"),
    ("facett-plandag", "wgpu", "facett_flow::gpu::install_renderer"),
    ("facett-brokkrview", "wgpu", "facett_flow::gpu::install_renderer"),
    ("facett-graphpan", "wgpu", "graphcloud::cloud::install_cloud_renderer"),
    ("facett-map3d", "wgpu", "facett_map3d::gpu::install_renderer"),
    ("facett-map", "wgpu", "facett_map::gpu::install_renderer"),
    ("facett-geomap", "map-wgpu", "facett_map::gpu::install_renderer"),
    ("facett-graph3d", "wgpu", "graphcloud::cloud::install_cloud_renderer"),
    ("facett-graphview", "gpu", "graphcloud::cloud::install_cloud_renderer"),
    ("facett-graphnav", "gpu", "gpu_layout::install_host_device"),
    ("facett-graphnav", "wgpu", "graphcloud::cloud::install_cloud_renderer"),
];

/// The mount source, flattened to one line with runs of whitespace collapsed.
///
/// NORMALISED, and that is not a nicety — it is the lesson the sibling test wrote down
/// in blood: it was GREEN on the very manifest it existed to catch, because the phrase
/// it searched for happened to be line-wrapped. A call written across two lines by
/// rustfmt is the same call.
fn mount_source_flat() -> String {
    let src = std::fs::read_to_string(root().join("facet-wrapped/src/wasm.rs"))
        .expect("facet-wrapped/src/wasm.rs is readable");
    src.split_whitespace().collect::<Vec<_>>().join(" ")
}

/// Everything inside `fn install_gpu_lanes(...) { ... }`, flattened. Empty string when
/// the function does not exist at all — which is the state this row found.
fn install_body_flat() -> String {
    let flat = mount_source_flat();
    let Some(start) = flat.find("fn install_gpu_lanes(") else {
        return String::new();
    };
    let after = &flat[start..];
    let Some(open) = after.find('{') else { return String::new() };
    let mut depth = 0usize;
    for (i, c) in after[open..].char_indices() {
        match c {
            '{' => depth += 1,
            '}' => {
                depth -= 1;
                if depth == 0 {
                    return after[open + 1..open + i].to_string();
                }
            }
            _ => {}
        }
    }
    String::new()
}

fn metadata() -> serde_json::Value {
    let out = Command::new("cargo")
        .current_dir(root())
        .args(["metadata", "--no-deps", "--format-version", "1"])
        .output()
        .expect("run cargo metadata");
    assert!(out.status.success(), "cargo metadata failed: {}", String::from_utf8_lossy(&out.stderr));
    serde_json::from_slice(&out.stdout).expect("cargo metadata emits JSON")
}

/// The GPU edges the manifest ACTUALLY declares right now, read from cargo's parse and
/// never from the TOML text. This is the half that makes the test track the manifest
/// instead of restating it: turn an edge off and this shrinks, and the pairing test
/// below stops requiring its install.
fn declared_gpu_edges() -> Vec<(&'static str, &'static str)> {
    let md = metadata();
    let deps = md["packages"]
        .as_array()
        .expect("packages")
        .iter()
        .find(|p| p["name"] == "facet-wrapped")
        .expect("facet-wrapped is a workspace member")["dependencies"]
        .as_array()
        .expect("dependencies")
        .clone();
    LANES
        .iter()
        .filter(|(name, feature, _)| {
            deps.iter().any(|d| {
                d["name"] == *name
                    && d["features"]
                        .as_array()
                        .is_some_and(|a| a.iter().any(|f| f.as_str() == Some(*feature)))
            })
        })
        .map(|(name, _, install)| (*name, *install))
        .collect()
}

#[test]
fn every_gpu_lane_the_manifest_enables_has_an_install_beside_it() {
    let body = install_body_flat();
    assert!(
        !body.is_empty(),
        "facet-wrapped has no `install_gpu_lanes` at all. That was the state on \
         2026-09-06 and it is what made a 4090 report `lane_flag: \"cpu\"` behind a \
         WebGPU canvas: the bundle selected three GPU lanes and installed none of them."
    );
    let mut missing = Vec::new();
    for (crate_name, install) in declared_gpu_edges() {
        if !body.contains(install) {
            missing.push(format!("{crate_name} → {install}"));
        }
    }
    assert!(
        missing.is_empty(),
        "these GPU lanes are SELECTED by the manifest and never INSTALLED: {missing:?}\n\
         The component will report `gpu_lane_selected: true` and `backend: \"wgpu-vello\"` \
         and paint every frame on the CPU painter, on any adapter, with no error."
    );
}

#[test]
fn the_install_is_actually_called_from_the_mount() {
    // A function nobody calls is the hollow guard's own shape, and it would satisfy the
    // test above completely. So: the mount's `wgpu_render_state` block must call it.
    let flat = mount_source_flat();
    assert!(
        flat.contains("install_gpu_lanes(rs)"),
        "`install_gpu_lanes` is defined but never called from the mount. The \
         `RenderState` is already in hand at the `cc.wgpu_render_state` block — before \
         this row the ONLY thing done with it was `record_adapter`, which names the \
         device and puts nothing on any lane."
    );
}

#[test]
fn no_lane_is_installed_that_the_bundle_does_not_select() {
    // The reverse lie, and it is worth a test of its own: installing a renderer for a
    // lane the manifest does not enable would register it with
    // `facett_core::render::lane` and let an About box report a GPU lane that no
    // component can reach. `facett-map`'s 2-D GPU lane was the live case until
    // 2026-09-28, when the manifest started enabling it (owner ruling: a map that paints
    // on the CPU in a headful browser is a defect); remove the feature and this refuses
    // the install again.
    let body = install_body_flat();
    let selected = declared_gpu_edges();
    for (crate_name, _, install) in LANES {
        // An install shared with a SELECTED lane (the one graph cloud) is required by it.
        if !selected.iter().any(|(_, i)| *i == install) {
            assert!(
                !body.contains(install),
                "{crate_name}'s renderer is installed but the manifest does not enable \
                 its GPU feature — that registers a lane nothing can dispatch to"
            );
        }
    }
    // The 2-D map lane is now SELECTED (the table's facett-map/facett-geomap rows), so
    // the loop above holds it: its install may appear only while the manifest enables it.
    assert!(
        selected.iter().any(|(n, _)| *n == "facett-map")
            || !body.contains("facett_map::gpu::install_renderer"),
        "facett-map's 2-D GPU lane is installed, but the manifest takes facett-map on \
         default features — that renderer is not in this binary"
    );
}

// ── The SIBLING entry point: facett-demo's gh-pages bundle ─────────────────────
//
// Found 2026-09-18, fixed 2026-09-19: `facett-demo/src/main.rs::wasm_start` selected
// `map-wgpu,map3d-wgpu` (the declared `DEMO_WASM_FEATURES` axis) and made NO install
// call at all — its comment still said "no wgpu RenderState on the glow web path" from
// before the WebGPU backend landed. The exact defect the tests above end for the
// wheel, alive one crate over. Same shape of guard: the axis the build-thing declares
// (one writer; the xtask reads it) against the body of `wasm_install_gpu_lanes`.

/// facett-demo feature → the install it needs inside `wasm_install_gpu_lanes`.
const DEMO_LANES: [(&str, &str); 6] = [
    ("map-wgpu", "facett::map::gpu::install_renderer"),
    ("map3d-wgpu", "facett::map3d::gpu::install_renderer"),
    ("gpu", "install_cloud_renderer"),
    // The 2-D GraphView draws through the SAME graphcloud renderer as `gpu`.
    ("graph-wgpu", "feature = \"graph-wgpu\"))] facett::core::render::gpu::graphcloud::cloud::install_cloud_renderer"),
    ("graph-layout-gpu", "facett_graphnav::install_layout_device"),
    // Falsett's resident curve/packet renderer (facett-flow), 2026-10-04.
    ("flow-wgpu", "facett::flow::gpu::install_renderer"),
];

fn demo_source_flat() -> String {
    let src = std::fs::read_to_string(root().join("facett-demo/src/main.rs"))
        .expect("facett-demo/src/main.rs is readable");
    src.split_whitespace().collect::<Vec<_>>().join(" ")
}

fn demo_install_body_flat() -> String {
    let flat = demo_source_flat();
    let Some(start) = flat.find("fn wasm_install_gpu_lanes(") else {
        return String::new();
    };
    let after = &flat[start..];
    let Some(open) = after.find('{') else { return String::new() };
    let mut depth = 0usize;
    for (i, c) in after[open..].char_indices() {
        match c {
            '{' => depth += 1,
            '}' => {
                depth -= 1;
                if depth == 0 {
                    return after[open + 1..open + i].to_string();
                }
            }
            _ => {}
        }
    }
    String::new()
}

#[test]
fn the_pages_demo_installs_every_gpu_lane_its_declared_wasm_axis_selects() {
    let body = demo_install_body_flat();
    assert!(
        !body.is_empty(),
        "facett-demo has no `wasm_install_gpu_lanes` — the state of `wasm_start` until \
         2026-09-19: GPU features selected, nothing installed, every map/graph pane on \
         the gh-pages demo painting on the CPU behind a WebGPU canvas."
    );
    let axis = facett_build_thing::DEMO_WASM_FEATURES;
    let mut missing = Vec::new();
    for (feature, install) in DEMO_LANES {
        let selected = axis.contains(&feature);
        let installed = body.contains(install);
        if selected && !installed {
            missing.push(format!("{feature} → {install}"));
        }
        assert!(
            selected || !installed,
            "`wasm_install_gpu_lanes` installs {install} but `{feature}` is not on the \
             declared wasm axis {axis:?} — a lane nothing can dispatch to"
        );
    }
    assert!(
        missing.is_empty(),
        "the `facett-demo-wasm` row selects these GPU lanes and `wasm_start` never installs \
         them: {missing:?}"
    );
    // Every lane on the axis must also be a KNOWN lane here, so a fifth feature cannot be
    // added to the axis without deciding what its install is.
    for f in axis {
        assert!(
            DEMO_LANES.iter().any(|(n, _)| *n == f),
            "`{f}` is on DEMO_WASM_FEATURES but this guard does not know what it installs — \
             add its row to DEMO_LANES"
        );
    }
}

#[test]
fn the_pages_demo_calls_its_install_from_the_mount() {
    let flat = demo_source_flat();
    let start = flat.find("pub fn wasm_start(").expect("wasm_start exists");
    assert!(
        flat[start..].contains("wasm_install_gpu_lanes(rs)"),
        "`wasm_install_gpu_lanes` exists but `wasm_start` never calls it from its \
         `cc.wgpu_render_state` block"
    );
}