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

nordisk/edda

crates/nornir-testmatrix/.nornir/testmatrix-functional-status.md

Functional-status mode (the testmatrix feature)

The law (crisp) — no consultant-green

A green can only come from the function proving itself — never a claim, never an outside assert.

  1. The function under test computes its real state and emits it from the inside: functional_status(component, check, ok, detail), where ok is the measured value (e.g. ways > 0 && lit_px > 0), not a hardcoded true.
  2. That status is written to the warehouse (test_results, aspect functional) — the only source of truth.
  3. The matrix reads it back. So GREEN ⟺ the function emitted ok=true. Nobody types "green"; nothing asserts it from outside; I cannot claim it.
  4. The emit is #[cfg(feature = "testmatrix")] — in a release build it does not exist (no-op stub, not compiled, ships nothing).

When to use it (order of preference) — the emitter is a FALLBACK, not the default. A test asserts on the function's return value / object status (the returned result + state()/state_json) as usual, as much as possible. Only when that is not enough or not possible — the result can't be observed from outside (a GPU render: "did it actually draw?" is in no return value; a side effect with no readable handle) — do you implant functional_status inside the function under test. Default: assert the return/object state. Fallback: in-function emit. (map-render-non-blank is the canonical fallback case.)

→ enables the autonomous loop: build → emit → read status → fix → repeat until GREEN, no human in the loop.


Problem. Some "does it work?" checks can't be eyeballed by a test that only asserts "didn't panic" — e.g. a map that compiles and runs but draws nothing (0 ways, blank framebuffer). The unit/build/clippy aspects say "green"; the render is dead. We need a component to store a pass/fail STATUS that the test matrix can SEE (persisted, queryable in the warehouse) so a broken render is a RED matrix row automatically, without anyone looking at a GUI.

Solution. nornir-testmatrix gains a functional-status mode:

The mode

component self-test (headless render / kittest)
   │  functional_status("facett-map", "basemap_rendered", ok, detail)
   ▼
process-global buffer            (feature ON only; OFF = no-op stub)
   │  Aspect::Functional runner → drain_functional_rows()
   ▼
TestResultRow { suite=component, test_name=check, aspect="functional",
                status=pass|fail, message=detail, metric=#red }
   │  outcome_to_rows → TestSink (nornir's Iceberg `test_results`)
   ▼
nornir test history / viz 🧪 Test pane → RED row for the dead map

Aspect::Functional is in both Aspect::ALL and Aspect::DEFAULT, has the stable label "functional", round-trips through parse_aspect (functional / func / self-test), and is surfaced as a viz column (ASPECT_ORDER in src/viz/test_matrix_grid.rs). Unlike every other aspect it does not shell cargo — the component emits its own status during its test.

The testmatrix feature (release-gating)

In crates/nornir-testmatrix/Cargo.toml:

[features]
default = []
testmatrix = []

Two API shapes (in src/functional.rs):

// feature ON — record into a process-global buffer:
#[cfg(feature = "testmatrix")]
pub fn functional_status(component: &str, check: &str, ok: bool, detail: &str) { /* record */ }

// feature OFF (release) — inlined empty stub, compiles to nothing:
#[cfg(not(feature = "testmatrix"))]
#[inline]
pub fn functional_status(_:&str,_:&str,_:bool,_:&str) {}

drain_functional_rows() is gated the same way (real drain vs. empty Vec).

Two call-site patterns (the consumer picks one per call)

  1. Cheap detail — just call it; the OFF stub strips the call in release:
nornir_testmatrix::functional_status("facett-map", "basemap_rendered", ok, "0 ways");
  1. Expensive detail — if building detail costs real work (formatting a scene dump, counting lit framebuffer pixels), wrap the WHOLE block so even the string-building is compiled out in release:
#[cfg(feature = "testmatrix")]
{
    let detail = format!("{} ways, {} px lit", scene.way_count(), fb.lit_pixels());
    nornir_testmatrix::functional_status("facett-map", "basemap_rendered", ok, &detail);
}

The nornir root crate has a passthrough feature testmatrix = ["nornir-testmatrix/testmatrix"] (off by default) so the matrix process compiles in the emit only when asked: build/run with --features testmatrix.

How a consumer adopts it (5 lines)

  1. Depend on nornir-testmatrix and add a passthrough testmatrix feature that enables nornir-testmatrix/testmatrix (so release strips emits).
  2. In your headless-render / self-test path, after rendering, compute the verdict (ok) and a short detail.
  3. Emit it — functional_status("my-component", "the_check", ok, &detail) — wrapping the call in #[cfg(feature = "testmatrix")] if detail is expensive.
  4. Build/run that self-test with --features testmatrix.
  5. Run nornir test (it drains the buffer into Aspect::Functional rows) and watch the matrix go RED when ok=false, GREEN when ok=true.

Tests (inject-assert, proving both directions)

In src/functional.rs and src/aspect.rs (#[cfg]-split by feature):

Emit/drain tests share a process-global buffer, so they serialize on a test-only test_lock() and assert on uniquely-named checks.

Versioning

nornir-testmatrix bumped 0.1.5 → 0.2.0 (new public API + new aspect). Root nornir + nornir-robotui path-dep requirements bumped to 0.2.0. NOT published to crates.io — release is human-gated.