facett-core 0.1.4

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
Documentation
//! **The functional-status → nornir test-matrix bridge** (feature `testmatrix`).
//!
//! This is the single, discoverable seam every facett crate's tests + self-test
//! / headless-render paths use to feed the `nornir test` matrix one row per
//! **real, meaningful check**. It wraps [`nornir_testmatrix::functional_status`]
//! so a leaf crate's test only has to call `facett_core::testmatrix::emit(...)`
//! (or [`emit_render`]) — it never has to depend on `nornir-testmatrix`
//! directly; this crate owns that edge.
//!
//! ## Gated so release strips it
//! Everything here is `#[cfg(feature = "testmatrix")]`. A facett crate adds a
//! passthrough `testmatrix = ["facett-core/testmatrix"]` and wraps each call in
//! `#[cfg(feature = "testmatrix")]`. So a **release build** (feature OFF):
//! * has no `nornir-testmatrix` dependency edge (it is `dep:` optional),
//! * compiles out every emit call site, and
//! * even a stray call would hit a no-op (the upstream function is itself a
//!   no-op when its own `testmatrix` feature is off).
//!
//! With `--features testmatrix` each call appends one functional row to the JSON
//! sink at `$NORNIR_TESTMATRIX_OUT` (default `target/nornir-functional.json`),
//! which `nornir test` reads back into the matrix. A blank / zero-geometry
//! render becomes a **RED** functional row (`ok = false`); a real render is green.

/// Emit one functional-status row for a single real check.
///
/// * `component` — the unit under test (a facett component / view name).
/// * `check` — the specific assertion (e.g. `"renders_non_blank"`).
/// * `ok` — the **real** assertion result (`true` → pass, `false` → red row).
/// * `detail` — the **measured** value (a count, a ratio, a reason …).
///
/// No-op (and zero-cost) when the `testmatrix` feature is off.
#[cfg(feature = "testmatrix")]
pub fn emit(component: &str, check: &str, ok: bool, detail: &str) {
    nornir_testmatrix::functional_status(component, check, ok, detail);
}

/// No-op shape compiled when `testmatrix` is OFF — the release path.
#[cfg(not(feature = "testmatrix"))]
#[inline(always)]
pub fn emit(_component: &str, _check: &str, _ok: bool, _detail: &str) {}

/// Convenience for a **headless render** check: a render is OK only when it drew
/// real geometry AND the component reports non-zero domain geometry
/// (`geometry > 0`). A blank framebuffer (`vertices == 0`) or a zero-geometry
/// component (`geometry == 0`, e.g. a dead map with no ways/points) emits a RED
/// row so a dead view is visible in the matrix.
///
/// `geometry` is the component's own count of what it should be drawing — ways +
/// points for a map, nodes for a graph, rows for a table — read from its
/// `state_json`. `vertices` is the harness's tessellated-mesh proof that the GPU
/// path actually produced primitives.
#[cfg(feature = "testmatrix")]
pub fn emit_render(component: &str, vertices: usize, geometry: usize) {
    let ok = vertices > 0 && geometry > 0;
    emit(
        component,
        "headless_render",
        ok,
        &format!("vertices={vertices} geometry={geometry}"),
    );
}

/// No-op shape compiled when `testmatrix` is OFF — the release path.
#[cfg(not(feature = "testmatrix"))]
#[inline(always)]
pub fn emit_render(_component: &str, _vertices: usize, _geometry: usize) {}

/// Convenience for a **pixel non-blank** render proof (the map / geomap class):
/// OK only when the measured content ratio clears `min_ratio` AND `geometry > 0`.
/// A blank pane (ratio ≈ 0) or zero-geometry view emits a RED row.
#[cfg(feature = "testmatrix")]
pub fn emit_non_blank(component: &str, ratio: f64, min_ratio: f64, geometry: usize) {
    let ok = ratio >= min_ratio && geometry > 0;
    emit(
        component,
        "renders_non_blank",
        ok,
        &format!("content_ratio={ratio:.4} min={min_ratio} geometry={geometry}"),
    );
}

/// No-op shape compiled when `testmatrix` is OFF — the release path.
#[cfg(not(feature = "testmatrix"))]
#[inline(always)]
pub fn emit_non_blank(_component: &str, _ratio: f64, _min_ratio: f64, _geometry: usize) {}

#[cfg(all(test, feature = "testmatrix"))]
mod tests {
    use super::*;

    /// INJECT-AND-ASSERT: a real render report → a real functional row on the
    /// sink. We point the sink at a temp file, emit a green + a red render, and
    /// assert both landed with the right status (the matrix's RED/green contract).
    #[test]
    fn emit_render_writes_green_and_red_rows() {
        let dir = std::env::temp_dir().join(format!(
            "facett-tm-{}",
            std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_nanos()
        ));
        std::fs::create_dir_all(&dir).unwrap();
        let file = dir.join("functional.json");
        // SAFETY (edition 2024): this is the only test that touches these vars,
        // run single-threaded for the duration of the assertions; no other
        // thread reads the environment concurrently here.
        unsafe {
            std::env::set_var("NORNIR_TESTMATRIX_OUT", &file);
            std::env::set_var("NORNIR_TESTMATRIX_REPO", "facett");
            std::env::set_var("NORNIR_TESTMATRIX_RUN", "run-fc-test");
        }

        // A live view: drew 1234 verts over 9 geometry → green.
        emit_render("live_view", 1234, 9);
        // A dead map: 0 geometry even though something drew → RED.
        emit_render("dead_map", 50, 0);
        // A blank pane: ratio under floor → RED.
        emit_non_blank("blank_pane", 0.0007, 0.01, 40_000);
        // A real pane: ratio over floor + geometry → green.
        emit_non_blank("real_map", 0.028, 0.01, 40_000);

        let rows = nornir_testmatrix::JsonFileSink::new(&file)
            .read_all()
            .unwrap();
        assert_eq!(rows.len(), 4, "four checks → four functional rows");

        let live = rows.iter().find(|r| r.suite == "live_view").unwrap();
        assert_eq!(live.status, nornir_testmatrix::status::PASS);
        assert_eq!(live.aspect, nornir_testmatrix::ASPECT_FUNCTIONAL);

        let dead = rows.iter().find(|r| r.suite == "dead_map").unwrap();
        assert_eq!(dead.status, nornir_testmatrix::status::FAIL, "zero geometry = RED");

        let blank = rows.iter().find(|r| r.suite == "blank_pane").unwrap();
        assert_eq!(blank.status, nornir_testmatrix::status::FAIL, "blank pane = RED");

        let real = rows.iter().find(|r| r.suite == "real_map").unwrap();
        assert_eq!(real.status, nornir_testmatrix::status::PASS);

        unsafe {
            std::env::remove_var("NORNIR_TESTMATRIX_OUT");
            std::env::remove_var("NORNIR_TESTMATRIX_REPO");
            std::env::remove_var("NORNIR_TESTMATRIX_RUN");
        }
        let _ = std::fs::remove_dir_all(&dir);
    }
}