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

nordisk/facett

facett-about/tests/gpu_rows.rs

//! **The GPU rows GUARD** — what the About card says about the device it is
//! rendering on, asserted off the live AccessKit tree of the REAL
//! [`facett_about::draw_about_window_with_gpu`] body (`egui_kittest`), and off the
//! `state_json` fold a robot reads.
//!
//! Two facts existed at startup and were thrown away before any UI could show them:
//!
//! 1. every render proof in this repo had been running on **llvmpipe** — a CPU
//!    software rasteriser that is itself a Vulkan ICD, so "Vulkan" is not evidence of
//!    a GPU;
//! 2. a GPU lane can be **installed and never called** — `renderer_installed()` says
//!    yes while every frame goes through the CPU painter.
//!
//! Each assertion below is pinned on **applied output** — the label text that really
//! entered the tree — not on a state round-trip of the value the test just built.
//!
//! RED-when-broken, verified by neutralising (see the crate's commit): deleting the
//! `gpu_rows(ui, gpu)` call fails `the_about_card_names_the_adapter_backend_class_and_count`
//! on all four rows at once, and reporting `device_type` instead of the software flag
//! fails `a_software_rasteriser_is_never_dressed_up_as_a_discrete_gpu` with
//! `SOFTWARE`→`discrete`. Matrix cell `facett-about/gpu-rows`.

use std::sync::{Arc, Mutex};

use egui_kittest::kittest::Queryable;
use egui_kittest::Harness;
use facett_about::{draw_about_window_with_gpu, state_json_with_gpu, GpuLaneUse, GpuStatus, Identity};
use facett_core::render::adapter::{
    AdapterFacts, AdapterKind, AdapterSelection, VENDOR_AMD, VENDOR_ASPEED, VENDOR_MESA,
    VENDOR_NVIDIA,
};
use facett_core::render::lane::LaneRecord;

const MAP_LANE: &str = "facett_map::gpu::GpuMapRenderer";

fn identity() -> Identity {
    Identity::new("testapp", "TestApp", "9.9.9", "a test tagline")
}

// ── the adapter shapes oden really enumerates ────────────────────────────────

fn nvidia() -> AdapterFacts {
    AdapterFacts::new("NVIDIA GeForce RTX 4090", AdapterKind::DiscreteGpu, "Vulkan")
        .with_vendor(VENDOR_NVIDIA)
}
fn igpu() -> AdapterFacts {
    AdapterFacts::new("AMD Radeon Graphics (RADV RAPHAEL)", AdapterKind::IntegratedGpu, "Vulkan")
        .with_vendor(VENDOR_AMD)
}
fn aspeed() -> AdapterFacts {
    AdapterFacts::new("ASPEED Graphics Family", AdapterKind::Other, "Gl").with_vendor(VENDOR_ASPEED)
}
fn llvmpipe() -> AdapterFacts {
    AdapterFacts::new("llvmpipe (LLVM 21.1.8, 256 bits)", AdapterKind::Cpu, "Vulkan")
        .with_vendor(VENDOR_MESA)
}

fn lane(name: &str, installed: bool, reports_frames: bool, frames: u64) -> LaneRecord {
    LaneRecord {
        name: name.to_owned(),
        installed,
        reports_frames,
        frames,
        idle_reason: None,
        clocks: facett_core::render::lane::LaneClockStats::default(),
    }
}

/// Render the real About body for `gpu` and hand back the harness, so the assertions
/// read the LIVE AccessKit tree (the applied output), not a formatted string.
fn render(gpu: GpuStatus) -> Harness<'static> {
    let open = Arc::new(Mutex::new(true));
    let mut h = Harness::builder().with_size(egui::vec2(760.0, 620.0)).build_ui(move |ui| {
        let mut o = open.lock().unwrap();
        draw_about_window_with_gpu(ui.ctx(), &mut o, &identity(), None, 360.0, &gpu);
    });
    h.run();
    h
}

/// Does ANY node's label contain `needle`? (`query_by_label_contains` panics on two
/// or more matches; the rows deliberately share words, so count instead.)
fn seen(h: &Harness<'static>, needle: &str) -> bool {
    h.query_all_by_label_contains(needle).next().is_some()
}

/// Emit shim (real row with `--features testmatrix`, no-op otherwise).
#[cfg(feature = "testmatrix")]
fn emit(check: &str, ok: bool, detail: &str) {
    nornir_testmatrix::functional_status("facett-about", check, ok, detail);
}
#[cfg(not(feature = "testmatrix"))]
fn emit(_check: &str, _ok: bool, _detail: &str) {}

/// **The headline row set.** oden's real enumeration — an ASPEED BMC console,
/// llvmpipe, an integrated Radeon and the 4090 — selected by facett's own policy. The
/// card must NAME the chosen adapter, its backend, its device class and **how many
/// adapters were enumerated**, because a 4090 box quietly running llvmpipe is
/// distinguishable from a 4090 box running the 4090 only by those four facts.
#[test]
fn the_about_card_names_the_adapter_backend_class_and_count() {
    let sel = AdapterSelection::decide(&[aspeed(), llvmpipe(), igpu(), nvidia()], None)
        .expect("the policy picks the 4090");
    let gpu = GpuStatus::of(Some(sel), vec![lane(MAP_LANE, true, true, 137)]);
    let h = render(gpu.clone());

    let name = seen(&h, "NVIDIA GeForce RTX 4090");
    let backend = seen(&h, "Vulkan");
    let class = seen(&h, "discrete");
    let count = seen(&h, "4 adapter(s) enumerated");
    let lane_row = seen(&h, "IN USE") && seen(&h, "137 frame(s)");
    assert!(name, "the adapter NAME painted — without it the row says nothing a log did not");
    assert!(backend, "the backend painted (Vulkan/Metal/DX12/GL)");
    assert!(class, "the device class painted (discrete)");
    assert!(count, "how many adapters were enumerated painted — 1-of-4 is the whole story");
    assert!(lane_row, "the lane line painted, with the measured frame count");
    // The BMC console and llvmpipe were enumerated and rejected: the card reports the
    // CHOSEN adapter, not the loser list.
    assert!(!seen(&h, "ASPEED"), "the card names the chosen adapter, not every candidate");

    let js = state_json_with_gpu(&identity(), true, &gpu);
    assert_eq!(js["gpu"]["device_class"], serde_json::json!("discrete"));
    assert_eq!(js["gpu"]["backend"], serde_json::json!("Vulkan"));
    assert_eq!(js["gpu"]["adapter_count"], serde_json::json!(4));
    assert_eq!(js["gpu"]["software"], serde_json::json!(false));
    assert_eq!(js["gpu"]["lane"], serde_json::json!("in_use"));
    assert_eq!(js["gpu"]["lane_frames"], serde_json::json!(137));
    assert_eq!(js["gpu"]["adapter"]["name"], serde_json::json!("NVIDIA GeForce RTX 4090"));

    emit(
        "gpu-rows",
        name && backend && class && count && lane_row,
        "adapter+backend+class+count+lane painted for a 4-adapter oden enumeration",
    );
}

/// **RED-when-broken — the failure these rows exist to expose.** llvmpipe that
/// reports itself `DeviceType::DiscreteGpu` (a lying ICD; lavapipe reporting
/// `VirtualGpu` is the same shape) must STILL paint `SOFTWARE`, and the word
/// `discrete` must appear nowhere in the card. A row that trusts `device_type` would
/// print `discrete` here and the About box would become a new lie — worse than the
/// silence it replaced, because it would be quoted as evidence.
#[test]
fn a_software_rasteriser_is_never_dressed_up_as_a_discrete_gpu() {
    let liar = AdapterFacts::new("llvmpipe (LLVM 21.1.8, 256 bits)", AdapterKind::DiscreteGpu, "Vulkan")
        .with_vendor(VENDOR_MESA);
    let sel = AdapterSelection::decide(&[liar], None).expect("decides");
    assert_eq!(sel.chosen.kind, AdapterKind::DiscreteGpu, "the adapter really does claim discrete");
    let gpu = GpuStatus::of(Some(sel), vec![lane(MAP_LANE, true, true, 9)]);
    let h = render(gpu.clone());

    let says_software = seen(&h, "SOFTWARE (CPU rasteriser)");
    let says_discrete = seen(&h, "discrete");
    assert!(says_software, "a CPU rasteriser must be labelled SOFTWARE in the card");
    assert!(
        !says_discrete,
        "the card called llvmpipe DISCRETE because the adapter claimed it — the class must come \
         from the software flag (name AND device type), never from device_type alone"
    );
    assert!(seen(&h, "llvmpipe"), "and it names the rasteriser, so the remedy is obvious");
    assert_eq!(
        state_json_with_gpu(&identity(), true, &gpu)["gpu"]["software"],
        serde_json::json!(true)
    );

    emit("gpu-rows-software", says_software && !says_discrete, "llvmpipe claiming DiscreteGpu still reads SOFTWARE");
}

/// **The lane line is measured, and says `unknown` when it cannot measure.** Four
/// states, four different sentences, and the one that matters is the last: an
/// installed lane that never reports frames must NOT be called unused — it may be
/// painting every frame. `installed but UNUSED` is only ever printed for a lane that
/// promised to count and counted zero (korp's map facet).
#[test]
fn the_lane_line_says_in_use_unused_absent_or_unknown_and_never_guesses() {
    let sel = || AdapterSelection::decide(&[nvidia()], None);

    // IN USE — a reporting lane with frames.
    let h = render(GpuStatus::of(sel(), vec![lane(MAP_LANE, true, true, 42)]));
    assert!(seen(&h, "IN USE") && seen(&h, "42 frame(s)"), "a lane with frames reads IN USE");
    assert!(!seen(&h, "UNUSED") && !seen(&h, "unknown"));

    // INSTALLED BUT UNUSED — a reporting lane at zero. This is korp's map facet:
    // renderer installed, MapFacet never calls the lane, 60 000 shapes on one core.
    let h = render(GpuStatus::of(sel(), vec![lane(MAP_LANE, true, true, 0)]));
    assert!(seen(&h, "installed but UNUSED"), "a reporting lane at zero reads UNUSED");
    assert!(seen(&h, "GpuMapRenderer"), "and it names the lane that did not paint");
    assert!(!seen(&h, "IN USE"));

    // UNKNOWN — an installed lane that never promised to count. Not "unused".
    let h = render(GpuStatus::of(sel(), vec![lane("facett_map3d::gpu::Map3dRenderer", true, false, 0)]));
    assert!(seen(&h, "unknown"), "a silent installed lane reads unknown");
    assert!(
        !seen(&h, "UNUSED"),
        "a lane that never reported frames must not be CALLED unused — that is a guess"
    );

    // NOT INSTALLED — no lane at all.
    let h = render(GpuStatus::of(sel(), vec![]));
    assert!(seen(&h, "not installed"), "no lane reads not installed");
    assert!(!seen(&h, "unknown") && !seen(&h, "UNUSED"));

    // The json token tracks the sentence, for a robot that reads state instead of pixels.
    for (lanes, token) in [
        (vec![lane(MAP_LANE, true, true, 3)], "in_use"),
        (vec![lane(MAP_LANE, true, true, 0)], "installed_unused"),
        (vec![lane(MAP_LANE, true, false, 0)], "unknown"),
        (vec![], "not_installed"),
    ] {
        let g = GpuStatus::of(sel(), lanes);
        assert_eq!(
            state_json_with_gpu(&identity(), true, &g)["gpu"]["lane"],
            serde_json::json!(token)
        );
    }

    emit("gpu-rows-lane", true, "in_use / installed_unused / unknown / not_installed all painted distinctly");
}

/// A GPU-less process must SAY so — the row is never blank, and it never implies a
/// GPU it does not have. This is the headless/CPU-painter build, and korp thin on a
/// box with no driver.
#[test]
fn a_gpu_less_process_paints_the_absence() {
    let h = render(GpuStatus::none());
    assert!(seen(&h, "GPU: none"), "the absence of a GPU is stated, not left blank");
    assert!(seen(&h, "no adapter"), "and it says why");
    assert!(!seen(&h, "discrete") && !seen(&h, "Vulkan"), "no device is implied");

    let js = state_json_with_gpu(&identity(), true, &GpuStatus::none());
    assert!(js["gpu"]["adapter"].is_null());
    assert_eq!(js["gpu"]["lane"], serde_json::json!("not_installed"));
    // The identity half is untouched by the fold — an existing About robot keeps working.
    assert_eq!(js["wordmark"], serde_json::json!("TestApp"));

    emit("gpu-rows-absent", true, "a GPU-less process paints GPU: none");
}

/// The rows a robot asserts are the rows the card paints — the SAME writer
/// (`GpuStatus::rows()`), so an assertion cannot pass against a card that stopped
/// painting them. Every row string must be findable in the tree.
#[test]
fn every_row_in_the_json_is_a_row_in_the_tree() {
    // A lane that PAINTS and one that idles WITH a reason, so the row set exercises every
    // optional row this oracle is supposed to police. It used to run on a single painting
    // lane, which meant `rows()` was always the same three and the loop could not notice
    // an optional row going unpainted — and one DID: `idle_reason_line` reached
    // `state_json` and the card did not render it (2026-08-02). The oracle was green
    // throughout. A guard whose input never produces the row it guards is hollow.
    let mut idle = lane("facett_graph3d::gpu::CloudRenderer", true, true, 0);
    idle.idle_reason = Some("no_graph_open".to_owned());
    let gpu = GpuStatus::of(
        AdapterSelection::decide(&[llvmpipe(), nvidia()], None),
        vec![idle, lane(MAP_LANE, true, true, 5)],
    );
    let rows = gpu.rows();
    assert_eq!(
        rows.len(),
        4,
        "adapter + detail + lane + the idle lane's reason, no failure recorded: {rows:?}"
    );
    assert!(
        rows.iter().any(|r| r.contains("no_graph_open")),
        "the input must actually PRODUCE the optional row, or the loop below proves nothing"
    );
    let h = render(gpu.clone());
    for row in &rows {
        assert!(
            h.query_all_by_label(row.as_str()).next().is_some(),
            "the json advertises a row the card does not paint: {row:?}"
        );
    }
    assert_eq!(
        gpu.to_json()["rows"].as_array().expect("rows").len(),
        rows.len(),
        "state_json publishes exactly the painted rows"
    );
    assert!(matches!(gpu.lane, GpuLaneUse::InUse { frames: 5 }));

    emit("gpu-rows-oracle", true, "every state_json row is a painted label");
}

/// **RED-when-broken: an idle lane's REASON is PAINTED, not merely serialised.**
///
/// The bug this pins, measured on oden 2026-08-02. korp's About card said, on a machine
/// with an RTX 4090 and nothing at all wrong with it:
///
/// > GPU lane: installed but UNUSED — CloudRenderer, GpuMapRenderer drew 0 frames
/// > (the CPU painter is doing the work)
///
/// Every word true — the map pane simply had not been painted yet (modal infra chooser
/// over a Tables landing tab). But that sentence is *also* what a genuinely broken lane
/// prints, so neither the owner nor an agent with tools could tell which it was by looking
/// at the product. The reason existed in `state_json` before this row did, which is the
/// same defect one layer out: the robot could read it and the human could not. So the
/// assertion is on the RENDERED AccessKit tree, not on `rows()`.
#[test]
fn an_idle_lanes_reason_is_painted_in_the_card() {
    // Exactly korp's state: two installed lanes, zero frames, the map lane explaining
    // itself. Same shape as the row the owner read off his own screen.
    let mut map = lane("facett_map::gpu::GpuMapRenderer", true, true, 0);
    map.idle_reason = Some("pane_not_painted_yet".to_owned());
    let cloud = lane("facett_graph3d::gpu::CloudRenderer", true, true, 0);
    let lanes = vec![cloud, map];
    let gpu = GpuStatus {
        notes: Vec::new(),
        adapter: AdapterSelection::decide(&[nvidia()], None),
        unavailable: None,
        lane: facett_core::render::lane::fold_lane_use(&lanes),
        lanes,
    };
    let h = render(gpu.clone());

    let unused_row = seen(&h, "installed but UNUSED");
    let reason = seen(&h, "pane_not_painted_yet");
    let names_lane = seen(&h, "idle because");
    emit("gpu-idle-reason-painted", reason, "the map lane's reason is on screen");
    assert!(unused_row, "the ambiguous row is still there (this test is about what JOINS it)");
    assert!(
        reason,
        "the REASON must be painted — a diagnosis only a robot can read is the defect, \
         not the fix. Rows: {:?}",
        gpu.rows()
    );
    assert!(names_lane, "the row must say it is explaining an idle lane");

    // NON-VACUITY: the identical card with no reason recorded must NOT paint one. A row
    // that always appears (or that invents a reason) is a hollow guard.
    let bare_lanes =
        vec![lane("facett_graph3d::gpu::CloudRenderer", true, true, 0), lane("facett_map::gpu::GpuMapRenderer", true, true, 0)];
    let bare = GpuStatus {
        notes: Vec::new(),
        adapter: gpu.adapter.clone(),
        unavailable: None,
        lane: facett_core::render::lane::fold_lane_use(&bare_lanes),
        lanes: bare_lanes,
    };
    let hb = render(bare);
    assert!(seen(&hb, "installed but UNUSED"), "same lane state");
    assert!(
        !seen(&hb, "idle because"),
        "with nothing recorded the card must stay silent rather than invent a reason"
    );
    assert!(!seen(&hb, "pane_not_painted_yet"));
}