crates/nornir-funnel-embed/tests/facet_reaction_matrix.rs
//! **dwarves's FACETT REACTION MATRIX** — Phase-2 contract: for every
//! `(facett code × dwarves mount)` pair, dwarves MUST react, and the test asserts the
//! REACTION and the MOUNTED CODE — never a matched string.
//!
//! TABLE-DRIVEN from ONE data table (facett's shared
//! `facett_core::errcode::reaction_matrix()`, sliced to dwarves's mounts), so adding a
//! facett code — or a dwarves mount — adds rows automatically.
use facett_core::errcode::{self, FacetError, FacetRecorder, Reaction};
use nornir_funnel_embed::facet_react::{self, FUNNEL, MOUNTS};
fn raise(code: &str) -> FacetError {
let e = errcode::lookup(code).unwrap_or_else(|| panic!("{code} is registered"));
FacetError::new(e.component, e.n, e.code, e.message)
}
/// Drive ONE matrix row through the full check set; returns the assertion count.
fn check_row(mounted: &str, base: &'static str, mount: &str, expected: Reaction) -> usize {
// 1. resolvable
assert_eq!(
facet_react::reaction_of(mounted),
Some(expected),
"{mounted}: must resolve to its canonical reaction"
);
// 2. mount-independent — the reaction is a property of the CODE
assert_eq!(
errcode::reaction_for(base),
Some(expected),
"{base}: same reaction unmounted"
);
// 3. round-trip
assert_eq!(errcode::base_code(mounted), base);
assert_eq!(errcode::mount_of(mounted), Some(mount));
// 4. dwarves reacts with exactly the canonical reaction (hermetic recorder)
let mut rec = FacetRecorder::new();
let m = MOUNTS
.iter()
.find(|m| m.prefix() == mount)
.unwrap_or_else(|| panic!("{mount} is a declared dwarves mount"));
let err = raise(base);
assert_eq!(
facet_react::react(&mut rec, *m, &err),
expected,
"{mounted}: dwarves must take the canonical reaction"
);
// 5. the MOUNTED code was recorded
assert!(
rec.saw(mounted),
"{mounted}: the MOUNTED code must be recorded"
);
// 6. base code + human message survive
let e = &rec.entries()[0];
assert_eq!(
e.code, base,
"{mounted}: facett's frozen base code is untouched"
);
assert!(
!e.message.is_empty(),
"{mounted}: the visible message is still carried"
);
// 7. the pane's PUBLISHED data drives the reaction
let mut rec2 = FacetRecorder::new();
let state = serde_json::json!({ "error_code": base });
assert_eq!(
facet_react::react_to_state(&mut rec2, *m, &state),
Some(expected),
"{mounted}: reacting off state_json.error_code yields the same reaction"
);
8
}
fn run_kind(want: Reaction) -> (usize, usize) {
let (mut rows, mut asserts) = (0, 0);
for (mounted, base, mount, reaction) in facet_react::matrix() {
if reaction != want {
continue;
}
asserts += check_row(&mounted, base, mount, reaction);
rows += 1;
}
(rows, asserts)
}
#[test]
fn empty_state_codes_show_an_honest_empty_state() {
let (rows, asserts) = run_kind(Reaction::EmptyState);
assert!(rows > 0, "dwarves mounts a component that can be empty");
eprintln!("dwarves empty_state: {rows} rows, {asserts} assertions");
}
#[test]
fn diagnose_codes_are_recorded_as_faults() {
let (rows, asserts) = run_kind(Reaction::Diagnose);
eprintln!("dwarves diagnose: {rows} rows, {asserts} assertions");
}
#[test]
fn retry_codes_retry() {
let (rows, asserts) = run_kind(Reaction::Retry);
eprintln!("dwarves retry: {rows} rows, {asserts} assertions");
}
/// THE COVERAGE REPORT — every dwarves row, checked, counted, printed.
#[test]
fn matrix_coverage_report() {
let matrix = facet_react::matrix();
assert!(
!matrix.is_empty(),
"dwarves must implement a non-empty reaction matrix"
);
let mut asserts = 0;
let mut seen = std::collections::HashSet::new();
for (mounted, base, mount, reaction) in &matrix {
assert!(
seen.insert(mounted.clone()),
"duplicate matrix row {mounted}"
);
asserts += check_row(mounted, base, mount, *reaction);
}
eprintln!(
"\n══ dwarves FACETT REACTION MATRIX ══\n {} (code × mount) rows · {asserts} assertions\n",
matrix.len()
);
}
/// **THE ANTI-FICTION GUARD** (the dwarves lesson). Every mount dwarves DECLARES must
/// be real: its `site` file must exist and actually reference the facett component
/// whose codes it claims.
#[test]
fn every_declared_mount_is_actually_wired_in_its_declared_file() {
// CARGO_MANIFEST_DIR is <repo>/crates/nornir-funnel-embed; sites are repo-relative.
let repo = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.and_then(|p| p.parent())
.expect("the crate sits at <repo>/crates/nornir-funnel-embed");
for m in MOUNTS {
let path = repo.join(m.site);
assert!(
path.exists(),
"{}: declared site {} does not exist",
m.prefix(),
m.site
);
let src = std::fs::read_to_string(&path).expect("readable mount site");
let claimed: std::collections::HashSet<&str> = facet_react::matrix()
.iter()
.filter(|(_, _, mount, _)| *mount == m.prefix())
.map(|(_, base, _, _)| errcode::lookup(base).expect("registered").component)
.collect();
assert!(
!claimed.is_empty(),
"{}: declares no components",
m.prefix()
);
for comp in claimed {
let krate = format!("facett_{comp}");
assert!(
src.contains(&krate),
"{}: claims facet-{comp}-* codes but {} never references {krate} — \
a DECLARED mount must be a REAL mount, not fiction",
m.prefix(),
m.site
);
}
// …and a mount that never REACTS is still fiction. The declared site must
// carry a real consumer call into the reaction seam: a registration with no
// caller is not a wiring.
assert!(
src.contains("react_to_pane_state") || src.contains("facet_react::react"),
"{}: {} mounts the component but never calls the reaction seam — \
a declared row must be CONSUMER-WIRED, not merely declared",
m.prefix(),
m.site
);
}
}
/// **The wiring is on the LIVE path, not only in a test.** Loading an empty plan DAG
/// through the shipped `FunnelGraphPane::set_dag` makes the mount react, and the
/// mounted code + reaction ride out in the pane's published `report()`.
#[test]
fn the_live_funnel_pane_reacts_and_publishes_it() {
use funnel_core::plan_dag::PlanDag;
use nornir_funnel_embed::graph::FunnelGraphPane;
let mut pane = FunnelGraphPane::new();
pane.set_dag(&PlanDag {
nodes: Vec::new(),
edges: Vec::new(),
sel_plan: None,
});
assert!(
pane.facet_errors().saw("dwarves/funnel:facet-graphview-1"),
"the shipped load path reacted: {:?}",
pane.facet_errors().entries()
);
let rep = pane.report();
assert_eq!(rep["facet_errors"]["pairs"], facet_react::matrix().len());
assert_eq!(
rep["facet_errors"]["recorded"]["entries"][0]["reaction"],
errcode::Reaction::EmptyState.token()
);
}
/// No silent gaps: the registry's consumer column and dwarves's matrix must agree.
#[test]
fn the_registry_and_dwarvess_matrix_agree() {
let mounted: std::collections::HashSet<&str> = facet_react::matrix()
.into_iter()
.map(|(_, base, _, _)| base)
.collect();
for e in errcode::registry() {
assert_eq!(
e.consumer.contains("dwarves/"),
mounted.contains(e.code),
"{}: the registry consumer column and dwarves's implemented matrix disagree",
e.code
);
}
eprintln!(
" dwarves implements {} of {} facett codes",
mounted.len(),
errcode::registry().len()
);
}
/// dwarves publishes the Phase-2 surface as data.
#[test]
fn dwarves_publishes_the_reaction_matrix_as_state() {
let mut rec = FacetRecorder::new();
facet_react::react(&mut rec, FUNNEL, &raise("facet-graphview-1"));
let s = facet_react::state_json(&rec);
assert_eq!(s["scheme"], "dwarves/<surface>:facet-<component>-<n>");
assert_eq!(
s["pairs"].as_u64().unwrap() as usize,
facet_react::matrix().len()
);
assert_eq!(
s["recorded"]["entries"][0]["mounted_code"],
"dwarves/funnel:facet-graphview-1"
);
for r in s["matrix"].as_array().expect("rows") {
let mounted = r["mounted_code"].as_str().unwrap();
assert_eq!(
facet_react::reaction_of(mounted).map(|x| x.token()),
r["reaction"].as_str()
);
}
}
/// An unregistered facett code is DIAGNOSED, never ignored.
#[test]
fn an_unregistered_code_is_diagnosed_not_ignored() {
let mut rec = FacetRecorder::new();
let bogus = FacetError::new("nope", 99, "facet-nope-99", "invented");
assert_eq!(
facet_react::react(&mut rec, FUNNEL, &bogus),
Reaction::Diagnose
);
assert!(rec.saw("dwarves/funnel:facet-nope-99"));
}