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.
- The function under test computes its real state and emits it from the inside:
functional_status(component, check, ok, detail), whereokis the measured value (e.g.ways > 0 && lit_px > 0), not a hardcodedtrue. - That status is written to the warehouse (
test_results, aspectfunctional) — the only source of truth. - The matrix reads it back. So GREEN ⟺ the function emitted
ok=true. Nobody types "green"; nothing asserts it from outside; I cannot claim it. - 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:
functional_status(component, check, ok, detail)— a component's self-report (e.g.facett-map / basemap_rendered / ok=false / "0 ways, blank framebuffer").- A new
Aspect::Functional(label"functional") drains those reports intoTestResultRows on the existing warehousetest_resultspath, sonornir testand the viz 🧪 Test pane show a per-component functional row. - The whole emit path is gated behind the
testmatrixcargo feature so release builds (feature off) strip it to a no-op — zero release cost.
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
ok=false→status = "fail"→status::is_red(..) == true→ RED cell.ok=true→status = "pass"→ GREEN cell.- Nothing recorded (release, or feature off) → the aspect is a neutral
skip— never a false red/green, never a warehouse write.
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)
- Cheap detail — just call it; the OFF stub strips the call in release:
nornir_testmatrix::functional_status("facett-map", "basemap_rendered", ok, "0 ways");
- Expensive detail — if building
detailcosts 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)
- Depend on
nornir-testmatrixand add a passthroughtestmatrixfeature that enablesnornir-testmatrix/testmatrix(so release strips emits). - In your headless-render / self-test path, after rendering, compute the verdict (
ok) and a shortdetail. - Emit it —
functional_status("my-component", "the_check", ok, &detail)— wrapping the call in#[cfg(feature = "testmatrix")]ifdetailis expensive. - Build/run that self-test with
--features testmatrix. - Run
nornir test(it drains the buffer intoAspect::Functionalrows) and watch the matrix go RED whenok=false, GREEN whenok=true.
Tests (inject-assert, proving both directions)
In src/functional.rs and src/aspect.rs (#[cfg]-split by feature):
functional_row_maps_ok_false_to_red_fail/..._ok_true_to_green_pass— the row shape:ok→pass|fail,is_red/is_green, detail preserved.emit_red_then_drain_yields_red_row_and_clears(feature ON) — emitok=false→ drain yields a RED row, then the buffer is cleared.functional_aspect_drains_emitted_red_status_into_red_matrix_row(feature ON) — the FULL path: emit →run_aspect(Functional)→outcome_to_rows→ a REDTestResultRow(suite=component, aspect=functional) the matrix reads back.functional_aspect_green_when_all_checks_ok(feature ON) — GREEN direction.release_path_is_a_noop_drain_is_empty/functional_aspect_is_skip_noop_in_release(feature OFF) — the emit compiles to nothing andrun_aspect(Functional)is a neutralskip, zero write.
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.