dwarves-gui/tests/robot_mimir_answer_states.rs
//! **ROBOT-UI: the Lenses header says what each answer RESTS ON.**
//!
//! Since Mímir v2 a lens is computed on the request from nornir's code room, and
//! every `Mimir.*` answer carries `lens_meta.state`: `complete` / `partial` /
//! `empty_fact` when it computed, `empty_gap` when it is empty BECAUSE an input is
//! missing, `not_wired` when it waits for a producer, or a refusal
//! (`not_consumed`, `lake_unavailable`, …). The pane's header is those states,
//! rendered — and it is the first thing an operator reads, because a ranked list
//! from a lens that did not compute is worse than no list.
//!
//! Driven through the shipped thin pane (`LensPane::thin`) against a mock
//! `Mimir.*` server serving canned bodies shaped like nornir's own envelopes, so
//! what is asserted is the state the pane actually publishes — not a formatter
//! called directly.
//!
//! **What a weaker test would miss.** Asserting only "the header is non-empty"
//! passes on a header that counts a `not_wired` lens as answered, on a scorecard
//! that grades its empty list as a `pass`, and on a status line that prints
//! `0 zombie feature(s)` for a lens that never ran. Each case below pins the
//! DISCRIMINATING substring or field: the count, the lens named beside its state,
//! the factor with no count.
use dwarves_gui::mimir_lens::LensPane;
use facett_core::Facet;
use nornir_robotui::egui_kittest::Harness;
use nornir_robotui::{Observable, RobotSession};
use nornir_warehouse_embed::testkit::{spawn_mock_mimir, MockMimir};
use serde_json::json;
struct LensApp(LensPane);
impl Observable for LensApp {
fn state_json(&self) -> serde_json::Value {
Facet::state_json(&self.0)
}
}
/// A lens that COMPUTED, as nornir's `room_feed::finish` shapes it: the dispatch
/// name as `kind`, a ranked `worst`, the feeds it read, and `lens_meta.state`.
/// `state` is `complete` / `partial` / `empty_fact` / `empty_gap`; the list is
/// empty for the two `empty_*` states.
fn answered(lens: &str, state: &str, missing: &[&str]) -> String {
let feeds: Vec<serde_json::Value> = missing
.iter()
.map(|t| json!({ "table": t, "rows": 0, "root": "", "missing": true }))
.collect();
let worst = if state.starts_with("empty") {
json!([])
} else {
json!([{ "file": "src/lib.rs" }])
};
json!({
"kind": lens,
"report_kind": lens,
"worst": worst,
"feeds": feeds,
"evidence_note": format!("{lens}: what this answer rests on"),
"lens_meta": {
"state": state,
"lens": lens,
"repo_scope": "",
"room_scope": "edda@41 · nornir@7",
"gaps": [],
"lower_bounds": [],
"ms": 3,
},
})
.to_string()
}
/// A lens that waits for a producer — nornir's `not_wired` envelope.
fn not_wired(lens: &str, producer: &str) -> String {
json!({
"kind": lens,
"worst": [],
"feeds": [],
"evidence_note": format!(
"{lens}: Mímir v2: producer not wired yet — a missing producer, not an absence of findings. Missing producer: {producer}."
),
"lens_meta": { "state": "not_wired", "lens": lens, "repo_scope": "", "missing_producer": producer },
})
.to_string()
}
/// A lens that refused by state — nornir's `refused` envelope.
fn refused(lens: &str, state: &str) -> String {
json!({
"kind": lens,
"worst": [],
"feeds": [],
"evidence_note": format!("{lens}: code room of `nordisk`: no repo has a consumer offset yet"),
"lens_meta": { "state": state, "lens": lens, "repo_scope": "" },
})
.to_string()
}
/// Every lens of the mock, from one body per lens name.
fn all(body: impl Fn(&str) -> String) -> MockMimir {
MockMimir {
generic_cost: body("generic_cost"),
zombie_features: body("zombie_features"),
change_risk: body("change_risk"),
weak_tests: body("weak_tests"),
bench_gaps: body("bench_gaps"),
similar_code: body("similar_code"),
semantic_clones: body("semantic_clones"),
villa: body("villa"),
churn: body("churn"),
anomaly: body("anomaly"),
world_impact: body("world_impact"),
binary_drift: body("binary_drift"),
data_reach: body("data_reach"),
trust: body("trust"),
name_collision: body("name_collision"),
symbol_identity: body("symbol_identity"),
undoc_api: body("undoc_api"),
reachable_vuln: body("reachable_vuln"),
// The SOURCE-door lenses, the twins rows and the re-implemented
// libraries: 22 rows in all (THIN_LENSES).
subclone: body("subclone"),
semantic_twins: body("semantic_twins"),
group_twins: body("group_twins"),
reimplements_shared: body("reimplements_shared"),
..Default::default()
}
}
/// Open the shipped thin pane on `mock`, let it read itself, and hand back its
/// published state.
fn state_of(mock: MockMimir) -> serde_json::Value {
let srv = spawn_mock_mimir(mock);
let pane = LensPane::thin(&srv.endpoint, "", "nordisk");
let harness = Harness::builder()
.with_size(nornir_robotui::egui::Vec2::new(1200.0, 900.0))
.build_ui_state(
|ui, app: &mut LensApp| Facet::ui(&mut app.0, ui),
LensApp(pane),
);
let mut robot = RobotSession::new(harness, "dwarves-gui");
// The pane reads itself on open; drive frames until the reading lands.
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(30);
loop {
robot.run(1);
if robot.state_at("/scanned") == Some(json!(true)) || std::time::Instant::now() > deadline {
break;
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
assert_eq!(
robot.state_at("/scanned"),
Some(json!(true)),
"the pane must have read itself within 30 s"
);
robot.state_at("").expect("the pane publishes its state")
}
fn header(state: &serde_json::Value) -> String {
state["status"]
.as_str()
.unwrap_or_else(|| {
panic!("the pane publishes no /status — the header is what this test reads ({state})")
})
.to_string()
}
fn factor<'a>(state: &'a serde_json::Value, lens: &str) -> &'a serde_json::Value {
state["quality"]["factors"]
.as_array()
.and_then(|f| f.iter().find(|x| x["lens"] == lens))
.unwrap_or_else(|| panic!("no `{lens}` factor on the scorecard: {}", state["quality"]))
}
/// Every lens computed with every input present: the header counts them all, names
/// no state that needs explaining, and says outright that no feed is missing.
#[test]
fn twelve_complete_answers_are_counted_and_nothing_is_flagged() {
let st = state_of(all(|l| answered(l, "complete", &[])));
let h = header(&st);
assert!(h.contains("lens 22/22 answered"), "names the count: {h}");
assert!(h.contains("22 complete"), "{h}");
assert!(
h.contains("feeds missing: none"),
"says so explicitly rather than staying silent: {h}"
);
for flag in [
"NOT WIRED",
"INPUT MISSING",
"REFUSED",
"NO STATE",
"not measured",
] {
assert!(
!h.contains(flag),
"a fully computed reading flags nothing (`{flag}`): {h}"
);
}
assert_eq!(
st["quality"]["unmeasured"],
json!(0),
"every factor was measured"
);
assert!(
st["quality"]["score"].is_number(),
"a fully measured card carries a score: {}",
st["quality"]
);
}
/// What a lake the SERVER consumed answers today: no binary stream, so
/// `generic_cost` and `binary_drift` are `empty_gap`; `similar_code` and
/// `semantic_clones` wait for item embeddings (`not_wired`); the rest computed.
/// The header names each of the four BY LENS beside its state — and the scorecard
/// does not grade the duplication factor from a lens that never ran.
#[test]
fn a_server_consumed_lake_names_the_unanswered_lenses_and_grades_none_of_them() {
let st = state_of(all(|l| match l {
"generic_cost" | "binary_drift" => answered(l, "empty_gap", &["symbol_sizes"]),
"similar_code" | "semantic_clones" => not_wired(l, "item embeddings from driver spans"),
"zombie_features" => answered(l, "empty_fact", &[]),
"change_risk" => answered(l, "partial", &["coverage_fn"]),
_ => answered(l, "complete", &[]),
}));
let h = header(&st);
assert!(
h.contains("lens 18/22 answered"),
"four lenses did not compute: {h}"
);
assert!(h.contains("16 complete"), "{h}");
assert!(h.contains("1 partial (lower bound)"), "{h}");
assert!(
h.contains("1 empty: nothing found"),
"an empty FACT is counted as an answer: {h}"
);
assert!(
h.contains("EMPTY, INPUT MISSING: generic_cost, binary_drift"),
"an empty GAP is named by lens, never folded into the answered count: {h}"
);
assert!(
h.contains("NOT WIRED: similar_code, semantic_clones"),
"{h}"
);
assert!(
h.contains("feeds missing: coverage_fn, symbol_sizes"),
"the missing feeds are named: {h}"
);
assert!(
h.contains("artifact(s) taxed: not measured [empty_gap]"),
"the headline count of a lens that did not compute is its state, not a 0: {h}"
);
assert!(
h.contains("0 zombie feature(s)"),
"an empty FACT is a measured zero and prints as one: {h}"
);
let dup = factor(&st, "similar_code");
assert_eq!(
dup["status"],
json!("not measured"),
"a not_wired lens is never a `pass`: {dup}"
);
assert!(dup["count"].is_null(), "and it has no count: {dup}");
assert_eq!(dup["state"], json!("not_wired"));
assert_eq!(
factor(&st, "zombie")["status"],
json!("pass"),
"an empty FACT does grade"
);
assert_eq!(
st["quality"]["overall"],
json!("unknown"),
"not every criterion was measured: not `clean`"
);
assert!(
st["quality"]["score"].is_null(),
"no score while a factor is unmeasured: {}",
st["quality"]
);
}
/// A workspace nothing was consumed of: every lens refuses `not_consumed`. Nothing is
/// counted as answered, the refusal is named with its state, and no headline zero is
/// printed.
#[test]
fn an_unconsumed_workspace_reads_as_twelve_refusals_not_as_twelve_empty_lists() {
let st = state_of(all(|l| refused(l, "not_consumed")));
let h = header(&st);
assert!(h.contains("lens 0/22 answered"), "{h}");
assert!(
h.contains("REFUSED: generic_cost [not_consumed]"),
"the refusal carries its state: {h}"
);
assert!(
h.contains("zombie feature(s): not measured [not_consumed]"),
"{h}"
);
assert!(
!h.contains("0 zombie feature(s)"),
"a refusal must not print as a measured zero: {h}"
);
assert_eq!(st["quality"]["overall"], json!("unknown"));
assert_eq!(st["quality"]["unmeasured"], json!(5));
assert!(
st["quality"]["heresies"].is_null(),
"no heresy count from a lens that refused"
);
}
/// An answer with NO `lens_meta` (a server that is not Mímir v2) says nothing about
/// itself. It is named as that and counted as not answered — its empty list is not a
/// verdict this client can vouch for.
#[test]
fn an_answer_without_a_state_is_named_and_never_counted_as_computed() {
let plain =
|l: &str| json!({ "kind": l, "worst": [], "feeds": [], "evidence_note": "ok" }).to_string();
let st = state_of(all(plain));
let h = header(&st);
assert!(h.contains("lens 0/22 answered"), "{h}");
assert!(
h.contains("NO STATE (not a Mímir v2 answer): generic_cost, zombie_features"),
"an unstamped answer is named for what it is: {h}"
);
assert_eq!(factor(&st, "villa")["status"], json!("not measured"));
}
/// A state word this client does not know is shown VERBATIM, not mapped onto a
/// known one — the old chain's `computed` is such a word now.
#[test]
fn an_unknown_state_word_is_shown_verbatim() {
let old = |l: &str| {
json!({ "kind": l, "worst": [], "feeds": [], "evidence_note": "computed", "lens_meta": { "state": "computed" } })
.to_string()
};
let h = header(&state_of(all(old)));
assert!(h.contains("lens 0/22 answered"), "{h}");
assert!(h.contains("generic_cost [`computed`]"), "{h}");
}