use facett_graphview::{
MetroBranch as FxBranch, MetroLine as FxLine, MetroMap as FxMap, MetroStation as FxStation, StationKind,
};
use crate::arch::metro::{build_metro_map as build_nornir_metro_map, MetroLine as NornirLine};
use crate::coverage::Boundary;
use crate::knowledge::symbols::{CallEdgeRow, SymbolRow};
use nornir_testmatrix::coverage::CoverageRow;
fn last_ident(s: &str) -> String {
s.rsplit(|c| c == ':' || c == '.').next().unwrap_or(s).to_lowercase()
}
fn lit_idents(coverage: &[CoverageRow]) -> std::collections::HashSet<String> {
coverage
.iter()
.filter(|r| r.verdict == "covered")
.map(|r| last_ident(&r.id))
.collect()
}
fn chain_kind(b: Boundary) -> StationKind {
match b {
Boundary::Emitter => StationKind::Emitter,
_ => StationKind::PassThrough,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Caller {
Ui,
Cli,
}
impl Caller {
fn kind(self) -> StationKind {
match self {
Caller::Ui => StationKind::UiClient,
Caller::Cli => StationKind::CliClient,
}
}
fn label(self) -> &'static str {
match self {
Caller::Ui => "viz",
Caller::Cli => "cli",
}
}
}
fn classify_caller(file: &str) -> Option<Caller> {
let f = file.replace('\\', "/").to_lowercase();
if f.contains("src/viz/") || f.contains("urdr-threads") {
Some(Caller::Ui)
} else if f.contains("src/bin/nornir.rs")
|| f.contains("src/bin/nornir-mcp.rs")
|| f.contains("bin/nornir.rs")
|| f.contains("bin/nornir-mcp.rs")
{
Some(Caller::Cli)
} else {
None
}
}
fn verb_stub_method(rpc: &str) -> String {
let verb = rpc.rsplit('.').next().unwrap_or(rpc);
let mut out = String::with_capacity(verb.len() + 4);
for (i, ch) in verb.chars().enumerate() {
if ch.is_ascii_uppercase() {
if i != 0 {
out.push('_');
}
out.push(ch.to_ascii_lowercase());
} else {
out.push(ch);
}
}
out
}
fn caller_arms_for_verb(
rpc: &str,
calls: &[CallEdgeRow],
lit: &std::collections::HashSet<String>,
) -> Vec<FxBranch> {
let stub = verb_stub_method(rpc);
let mut has_ui = false;
let mut has_cli = false;
for e in calls {
if last_ident(&e.callee_ident) != stub {
continue;
}
match classify_caller(&e.file) {
Some(Caller::Ui) => has_ui = true,
Some(Caller::Cli) => has_cli = true,
None => {}
}
}
let verb_lit = lit.contains(&stub) || lit.contains(&last_ident(rpc));
let mut arms = Vec::new();
if has_ui {
arms.push(FxBranch::new(
format!("caller::ui::{rpc}"),
Caller::Ui.label(),
Caller::Ui.kind(),
verb_lit,
));
}
if has_cli {
arms.push(FxBranch::new(
format!("caller::cli::{rpc}"),
Caller::Cli.label(),
Caller::Cli.kind(),
verb_lit,
));
}
arms
}
fn terminus_table(handler_seg: Option<&str>, rpc: &str, access: &[(String, String)]) -> (String, String, bool) {
if let Some(seg) = handler_seg {
let want = last_ident(seg);
if let Some((_, table)) = access.iter().find(|(fnseg, _)| last_ident(fnseg) == want) {
return (format!("warehouse::{table}"), table.clone(), true);
}
}
let svc = rpc.split('.').next().unwrap_or(rpc).to_lowercase();
let placeholder = format!("{svc}_results");
(format!("table?::{placeholder}"), placeholder, false)
}
fn line_to_fx(
nl: &NornirLine,
lit: &std::collections::HashSet<String>,
access: &[(String, String)],
calls: &[CallEdgeRow],
) -> FxLine {
let is_lit = |seg: &str| lit.contains(&last_ident(seg));
let mut stations: Vec<FxStation> = Vec::new();
let head = nl.stations.first();
let head_name = head.map(|s| s.fn_name.as_str()).unwrap_or(nl.ui_handler.as_str());
let head_id = head
.map(|s| s.symbol.clone())
.filter(|s| !s.is_empty())
.unwrap_or_else(|| head_name.to_string());
stations.push(FxStation::new(head_id, head_name, StationKind::Start, is_lit(head_name)));
let terminus_seg = nl.grpc_terminus.clone();
if nl.reached {
let interior_end = nl.stations.len().saturating_sub(1);
for st in nl.stations.iter().take(interior_end).skip(1) {
let id = if st.symbol.is_empty() { st.fn_name.clone() } else { st.symbol.clone() };
let kind = chain_kind(st.boundary);
stations.push(FxStation::new(id, &st.fn_name, kind, is_lit(&st.fn_name)));
}
} else {
stations.push(FxStation::new(
format!("unresolved::{}", nl.button_id),
"(unresolved)",
StationKind::PassThrough,
true,
));
}
let grpc_id = format!("grpc::{}", nl.rpc);
let grpc_lit = terminus_seg.as_deref().map(is_lit).unwrap_or(false)
|| is_lit(nl.rpc.rsplit('.').next().unwrap_or(&nl.rpc));
let arms = caller_arms_for_verb(&nl.rpc, calls, lit);
stations.push(FxStation::with_branches(grpc_id, nl.rpc.clone(), StationKind::Grpc, grpc_lit, arms));
let (term_id, term_label, term_resolved) = terminus_table(terminus_seg.as_deref(), &nl.rpc, access);
let term_lit = if term_resolved { is_lit(&term_label) || grpc_lit } else { grpc_lit };
stations.push(FxStation::new(term_id, term_label, StationKind::Terminus, term_lit));
FxLine::new(
format!("{}β{}", nl.button_id, nl.rpc),
format!("{} ({})", nl.button_id, nl.tab),
stations,
)
}
pub fn build_metro_map(
symbols: &[SymbolRow],
calls: &[CallEdgeRow],
coverage: &[CoverageRow],
access: &[(String, String)],
) -> FxMap {
let lit = lit_idents(coverage);
let nornir_lines = build_nornir_metro_map(symbols, calls);
let lines = nornir_lines.iter().map(|nl| line_to_fx(nl, &lit, access, calls)).collect();
FxMap::new(lines)
}
#[derive(Debug, Clone, Default)]
pub struct MetroFacts {
pub symbols: Vec<SymbolRow>,
pub calls: Vec<CallEdgeRow>,
pub coverage: Vec<CoverageRow>,
pub access: Vec<(String, String)>,
}
pub fn build_metro_maps_all(per_ws: &[(String, MetroFacts)]) -> Vec<(String, FxMap)> {
per_ws
.iter()
.map(|(ws, f)| (ws.clone(), build_metro_map(&f.symbols, &f.calls, &f.coverage, &f.access)))
.collect()
}
pub fn metro_coverage(map: &FxMap) -> (usize, usize) {
let mut green = 0usize;
let mut total = 0usize;
for line in &map.lines {
let unresolved = line.stations.iter().any(|s| s.id.starts_with("unresolved::"));
if unresolved {
continue;
}
total += 1;
if line.is_green() {
green += 1;
}
}
(green, total)
}
#[cfg(test)]
mod tests {
use super::*;
fn sym(module: &str, name: &str, kind: &str, file: &str, line: u32) -> SymbolRow {
SymbolRow {
crate_name: "nornir".into(),
module_path: module.into(),
item_kind: kind.into(),
item_name: name.into(),
visibility: "pub".into(),
file: file.into(),
line,
doc_lines: 0,
signature: None,
}
}
fn call(caller: &str, callee: &str) -> CallEdgeRow {
CallEdgeRow {
crate_name: "nornir".into(),
caller_path: caller.into(),
callee_ident: callee.into(),
call_kind: "call".into(),
file: "src/x.rs".into(),
line: 1,
}
}
fn cov(id: &str, verdict: &str) -> CoverageRow {
CoverageRow {
run_id: "r".into(),
workspace: "ws".into(),
surface_key: format!("function:{id}@fat"),
kind: "function".into(),
id: id.into(),
mode: "fat".into(),
verdict: verdict.into(),
reason: String::new(),
ts_micros: 1,
utfallsrum_covered: 0.0,
}
}
fn fixture() -> (Vec<SymbolRow>, Vec<CallEdgeRow>) {
let symbols = vec![
sym("nornir::viz::test_tab::TestTabState", "draw_run_ops", "fn", "src/viz/test_tab.rs", 207),
sym("nornir::viz::trace", "emit_in", "fn", "src/viz/trace.rs", 90),
sym("nornir::viz::remote", "run_test_matrix_rpc", "fn", "src/viz/remote.rs", 300),
sym("nornir_server", "impl OpsSvcTrait for OpsSvc", "impl", "src/bin/nornir-server.rs", 3243),
sym("nornir_server::OpsSvc", "run_test_matrix", "fn", "src/bin/nornir-server.rs", 3244),
];
let calls = vec![
call("nornir::viz::test_tab::TestTabState::draw_run_ops", "emit_in"),
call("nornir::viz::trace::emit_in", "run_test_matrix_rpc"),
call("nornir::viz::remote::run_test_matrix_rpc", "OpsSvc::run_test_matrix"),
];
(symbols, calls)
}
#[test]
fn map_has_a_line_per_button() {
let (symbols, calls) = fixture();
let map = build_metro_map(&symbols, &calls, &[], &[]);
assert_eq!(map.lines.len(), crate::arch::metro::button_registry().len());
}
#[test]
fn resolved_line_lights_up_to_green() {
let (symbols, calls) = fixture();
let coverage = vec![
cov("draw_run_ops", "covered"), cov("nornir::viz::trace::emit_in", "covered"),
cov("run_test_matrix", "covered"),
cov("test_matrix_runs", "covered"),
];
let access = vec![("OpsSvc::run_test_matrix".to_string(), "test_matrix_runs".to_string())];
let map = build_metro_map(&symbols, &calls, &coverage, &access);
let line = map
.lines
.iter()
.find(|l| l.id == "run_full_matrixβOps.RunTestMatrix")
.expect("the run_full_matrix line");
let kinds: Vec<StationKind> = line.stations.iter().map(|s| s.kind).collect();
assert_eq!(kinds.first(), Some(&StationKind::Start), "head is the button");
assert_eq!(kinds.last(), Some(&StationKind::Terminus), "tail is the warehouse table");
assert!(kinds.contains(&StationKind::Grpc), "the gRPC handler stop");
assert!(kinds.contains(&StationKind::Emitter), "an emitter station on the chain");
assert!(kinds.contains(&StationKind::PassThrough), "a ridden-through core fn");
let emitter = line.stations.iter().find(|s| s.kind == StationKind::Emitter).unwrap();
assert_eq!(emitter.label, "emit_in");
assert!(emitter.lit, "the covered emitter is lit");
let term = line.stations.last().unwrap();
assert_eq!(term.label, "test_matrix_runs", "terminus resolved from the access edge");
assert!(line.is_green(), "fully-covered resolved chain is green: {line:?}");
}
#[test]
fn unlit_emitter_makes_line_red() {
let (symbols, calls) = fixture();
let coverage = vec![cov("run_test_matrix", "covered"), cov("test_matrix_runs", "covered")];
let access = vec![("OpsSvc::run_test_matrix".to_string(), "test_matrix_runs".to_string())];
let map = build_metro_map(&symbols, &calls, &coverage, &access);
let line = map.lines.iter().find(|l| l.id == "run_full_matrixβOps.RunTestMatrix").unwrap();
assert!(!line.is_green(), "an unlit emitter keeps the line red");
let unlit_labels: Vec<&str> = line.unlit().iter().map(|s| s.label.as_str()).collect();
assert!(unlit_labels.contains(&"emit_in"), "emit_in is the unlit gating stop: {unlit_labels:?}");
}
#[test]
fn unresolved_chain_emits_skeleton() {
let (symbols, _) = fixture();
let map = build_metro_map(&symbols, &[], &[], &[]); let line = map.lines.iter().find(|l| l.id == "run_full_matrixβOps.RunTestMatrix").unwrap();
let kinds: Vec<StationKind> = line.stations.iter().map(|s| s.kind).collect();
assert_eq!(kinds.first(), Some(&StationKind::Start));
assert_eq!(kinds.last(), Some(&StationKind::Terminus));
assert!(kinds.contains(&StationKind::Grpc));
assert!(
line.stations.iter().any(|s| s.id.starts_with("unresolved::")),
"an honest unresolved marker, not a fabricated interior"
);
assert!(!line.is_green(), "an unproven skeleton is not green");
}
fn call_in(caller: &str, callee: &str, file: &str) -> CallEdgeRow {
CallEdgeRow {
crate_name: "nornir".into(),
caller_path: caller.into(),
callee_ident: callee.into(),
call_kind: "call".into(),
file: file.into(),
line: 1,
}
}
#[test]
fn verb_stub_method_snake_cases_the_verb() {
assert_eq!(verb_stub_method("Ops.RunTestMatrix"), "run_test_matrix");
assert_eq!(verb_stub_method("Health.Ping"), "ping");
assert_eq!(verb_stub_method("Workspaces.PopulateStatus"), "populate_status");
}
#[test]
fn classify_caller_splits_ui_from_cli() {
assert_eq!(classify_caller("src/viz/remote.rs"), Some(Caller::Ui));
assert_eq!(classify_caller("src/bin/nornir.rs"), Some(Caller::Cli));
assert_eq!(classify_caller("src/bin/nornir-mcp.rs"), Some(Caller::Cli));
assert_eq!(classify_caller("src/bin/nornir-server.rs"), None, "the server is not a client");
assert_eq!(classify_caller("src/lib.rs"), None);
}
#[test]
fn grpc_verb_forks_to_ui_and_cli_arms() {
let (symbols, mut calls) = fixture();
calls.push(call_in("nornir::viz::remote::run_test_matrix", "run_test_matrix", "src/viz/remote.rs"));
calls.push(call_in("nornir::run_test_matrix_remote", "run_test_matrix", "src/bin/nornir.rs"));
let coverage = vec![cov("run_test_matrix", "covered")];
let map = build_metro_map(&symbols, &calls, &coverage, &[]);
let line = map.lines.iter().find(|l| l.id == "run_full_matrixβOps.RunTestMatrix").unwrap();
let grpc = line.stations.iter().find(|s| s.kind == StationKind::Grpc).expect("a grpc stop");
assert_eq!(grpc.branches.len(), 2, "called by BOTH ui+cli β two arms: {:?}", grpc.branches);
let kinds: Vec<StationKind> = grpc.branches.iter().map(|b| b.kind).collect();
assert!(kinds.contains(&StationKind::UiClient), "a UI arm");
assert!(kinds.contains(&StationKind::CliClient), "a CLI arm");
let ui = grpc.branches.iter().find(|b| b.kind == StationKind::UiClient).unwrap();
let cli = grpc.branches.iter().find(|b| b.kind == StationKind::CliClient).unwrap();
assert_eq!(ui.marker(), Some("UI"));
assert_eq!(cli.marker(), Some("CLI"));
assert!(ui.lit && cli.lit, "covered verb lights both client arms");
assert_eq!(line.stations.first().unwrap().kind, StationKind::Start);
assert_eq!(line.stations.last().unwrap().kind, StationKind::Terminus);
}
#[test]
fn grpc_verb_with_only_cli_caller_renders_one_arm() {
let (symbols, mut calls) = fixture();
calls.push(call_in("nornir::run_test_matrix_remote", "run_test_matrix", "src/bin/nornir.rs"));
let map = build_metro_map(&symbols, &calls, &[], &[]);
let line = map.lines.iter().find(|l| l.id == "run_full_matrixβOps.RunTestMatrix").unwrap();
let grpc = line.stations.iter().find(|s| s.kind == StationKind::Grpc).unwrap();
assert_eq!(grpc.branches.len(), 1, "only the CLI calls it β one arm");
assert_eq!(grpc.branches[0].kind, StationKind::CliClient);
assert_eq!(grpc.branches[0].marker(), Some("CLI"));
assert!(!grpc.branches[0].lit, "no coverage β the CLI arm is present-but-unlit");
}
fn st(id: &str, kind: StationKind, lit: bool) -> FxStation {
FxStation::new(id, id, kind, lit)
}
#[test]
fn metro_coverage_counts_resolved_lines_excludes_unresolved() {
let resolved_green = FxLine::new(
"g",
"g",
vec![
st("start::g", StationKind::Start, true),
st("emit::g", StationKind::Emitter, true),
st("grpc::G", StationKind::Grpc, true),
st("warehouse::t", StationKind::Terminus, true),
],
);
let resolved_red = FxLine::new(
"r",
"r",
vec![
st("start::r", StationKind::Start, true),
st("emit::r", StationKind::Emitter, false), st("grpc::R", StationKind::Grpc, true),
st("warehouse::u", StationKind::Terminus, true),
],
);
let unresolved = FxLine::new(
"u",
"u",
vec![
st("start::u", StationKind::Start, true),
st("unresolved::btn", StationKind::PassThrough, true),
st("grpc::U", StationKind::Grpc, false),
st("table?::z", StationKind::Terminus, false),
],
);
let map = FxMap::new(vec![resolved_green, unresolved, resolved_red]);
let (green, total) = metro_coverage(&map);
assert_eq!(total, 2, "only the two RESOLVED lines are counted");
assert_eq!(green, 1, "one resolved line is fully lit");
assert_eq!(metro_coverage(&FxMap::new(vec![])), (0, 0));
}
#[test]
fn build_metro_maps_all_rolls_up_per_workspace() {
let (symbols, calls) = fixture();
let cov_a = vec![
cov("draw_run_ops", "covered"),
cov("nornir::viz::trace::emit_in", "covered"),
cov("run_test_matrix", "covered"),
cov("test_matrix_runs", "covered"),
];
let access = vec![("OpsSvc::run_test_matrix".to_string(), "test_matrix_runs".to_string())];
let per_ws = vec![
(
"a".to_string(),
MetroFacts {
symbols: symbols.clone(),
calls: calls.clone(),
coverage: cov_a,
access: access.clone(),
},
),
(
"b".to_string(),
MetroFacts { symbols, calls, coverage: vec![], access },
),
];
let maps = build_metro_maps_all(&per_ws);
assert_eq!(maps.iter().map(|(w, _)| w.as_str()).collect::<Vec<_>>(), vec!["a", "b"]);
let (ga, ta) = metro_coverage(&maps[0].1);
assert!(ta >= 1 && ga == ta, "ws a: every resolved line green ({ga}/{ta})");
let (gb, tb) = metro_coverage(&maps[1].1);
assert_eq!(tb, ta, "same resolved-line count in both workspaces");
assert!(gb < tb, "ws b: the uncovered resolved line is red ({gb}/{tb})");
}
#[test]
fn grpc_verb_with_no_client_caller_has_no_arms() {
let (symbols, calls) = fixture(); let map = build_metro_map(&symbols, &calls, &[], &[]);
let line = map.lines.iter().find(|l| l.id == "run_full_matrixβOps.RunTestMatrix").unwrap();
let grpc = line.stations.iter().find(|s| s.kind == StationKind::Grpc).unwrap();
assert!(grpc.branches.is_empty(), "no client caller β no arms: {:?}", grpc.branches);
}
}