Expand description
§nornir-testmatrix
The portable core of nornir’s multi-aspect test matrix — extracted from
nornir (EPIC L) so any leaf repo (znippy, skade, lbzip2-rs …) can run the
same matrix with a tiny dep set: std + serde/serde_json + anyhow.
No iceberg, arrow, eframe, tantivy, or skade.
§What it does
- Runner (
runner) — wrap a repo’s native Rust test framework (cargo nextest run --message-format libtest-jsonif nextest is on PATH, else plaincargo test), parse each test’s pass/fail + duration, enforce a stall watchdog. Pure subprocess driving — no test registration. - Multi-aspect engine (
aspect) — beyond unit tests, run MANY aspects of a repo’s health (Aspect): build, doctest, clippy, fmt, audit, bench-smoke, coverage, feature-powerset, msrv, examples. Each shells the rightcargosubcommand, parses its result, and emitsTestResultRows carrying anaspecttag + a numericmetric(coverage %, warning count, advisory count …). A missing tool is a skip, never a hard fail. - Model (
model) — the pure row/summary types (TestResultRow,RunSummary,TestSelector, thestatustags) + the renderers (render_matrix,summarize_runs,rows_to_json). - Sinks (
sink) — theTestSinktrait + built-inJsonFileSinkandNullSinkso a leaf repo with no warehouse can still persist its matrix. nornir implementsTestSinkover its Iceberg warehouse. - Discovery (
discover) — the autonom (AUT2) anti-drift core: pure enumerators that build the testableSurfacefrom data (facett components, viz tabs × {thin,fat}, CLI subcommands, MCP tools, and the unreached-function set fromsymbol_facts − test-reachable(call_edges)), thencompute_gapdifferences it against coverage so the gate can enforceGap == ∅. No warehouse here — the caller feeds the rows. - Functional-status mode (
functional) — a component reports whether it actually works (functional_status(component, check, ok, detail)) from its own headless-render / self-test path. TheAspect::Functionalrunner drains those into rows so a broken render is a RED matrix row WITHOUT eyeballing a GUI. Gated behind thetestmatrixcargo feature: release builds (feature off) strip the emit to a no-op.
§How a leaf repo uses it
use nornir_testmatrix::{run_full_matrix, Aspect, JsonFileSink, TestSink};
use std::path::Path;
let aspects = [Aspect::Build, Aspect::Unit, Aspect::Doctest, Aspect::Clippy, Aspect::Fmt];
let rows = run_full_matrix(Path::new("."), &aspects);
let sink = JsonFileSink::new("target/nornir-testmatrix.json");
sink.append(&rows).unwrap();Re-exports§
pub use aspect::aspect_label;pub use aspect::parse_aspect;pub use aspect::parse_funnel_decompose;pub use aspect::run_aspect;pub use aspect::run_full_matrix;pub use aspect::Aspect;pub use aspect::AspectOutcome;pub use coverage::rows_for;pub use coverage::seed_allowlist;pub use coverage::stale_allowlist_entries;pub use coverage::AllowEntry;pub use coverage::Allowlist;pub use coverage::CoverageRow;pub use coverage::CoverageSummary;pub use coverage::GateReport;pub use coverage::Verdict;pub use discover::cli_commands;pub use discover::compute_gap;pub use discover::facett_components;pub use discover::mcp_tools;pub use discover::test_reachable;pub use discover::unreached_functions;pub use discover::viz_tabs;pub use discover::CallEdge;pub use discover::FacetRow;pub use discover::Gap;pub use discover::Mode;pub use discover::Surface;pub use discover::SurfaceKind;pub use discover::SurfaceNode;pub use discover::SymbolRow;pub use functional::drain_functional_rows;pub use functional::functional_row;pub use functional::functional_status;pub use model::listed_rows;pub use model::new_run_id;pub use model::parse_cargo_test_list;pub use model::parse_nextest_list;pub use model::render_matrix;pub use model::rows_to_json;pub use model::short_run;pub use model::status;pub use model::summarize_runs;pub use model::RunSummary;pub use model::TestResultRow;pub use model::TestSelector;pub use runner::detect_runner;pub use runner::list_tests;pub use runner::run_matrix;pub use runner::stall_secs;pub use runner::MatrixRun;pub use runner::Runner;pub use runner::TestCase;pub use runner::DEFAULT_STALL_SECS;pub use sink::JsonFileSink;pub use sink::NullSink;pub use sink::TestSink;
Modules§
- aspect
- The multi-aspect engine — test MANY aspects of a repo’s health, not just
its unit tests. Each
Aspectshells the rightcargosubcommand, parses its result into anAspectOutcome, and emitsTestResultRows carrying the aspect tag + a numericmetric(coverage %, warning count, advisory count …). - coverage
- autonom coverage gate — the PURE verdict model (AUT2 / n-005)
- discover
- autonom self-discovery — the anti-drift core of the completeness gate
- functional
- Functional-status mode — a component reports whether it actually works.
- model
- The pure test-matrix model: rows, summaries, selectors, status tags, and
the human/JSON renderers. Zero heavy deps —
stdonly (no chrono, no uuid): a tiny RFC3339 formatter + a getrandom-free UUIDv4 keep the crate lean. - runner
- Standardized test-matrix runner — wrap a repo’s native Rust test framework, parse per-test pass/fail + duration, and hand the rows back.
- sink
- Where a matrix run’s rows go. The
TestSinktrait is the durable seam:nornirimplements it over its Iceberg warehouse; a leaf repo with no warehouse uses the built-inJsonFileSink(append-only JSON history file) orNullSink(drop, for dry-runs / tests).