crates/nornir-warehouse-embed/tests/bench_history.rs
//! **The `Bench.History` READ leg, proven on the wire.**
//!
//! The forge measures and the warehouse keeps the numbers; until now reading them
//! back was `nornir bench history-show`. The doc-book MASHUP renderer moving into
//! dwarves needs its own read-back leg (`fetch_bench_history`), and what has to be
//! true of it is a ROUND TRIP: the run that crossed the wire IN over `Bench.Submit`
//! comes back OUT over `Bench.History` carrying the same numbers, mapped back onto
//! the same `nornir_bench::BenchRun` the rest of the codebase holds.
//!
//! The zero-equals-zero identity trap (see dwarves' `dupes_thin_fat_parity`): an
//! assertion over two empty lists proves nothing, so the round-trip test asserts a
//! NON-empty history field-for-field — and the empty case is its own test, proving
//! "no runs yet" is an EMPTY VEC (a normal state the mashup renders), never an
//! error, while a dead or refusing server IS an error, never a silent empty.
use nornir_warehouse_embed::{
bench_run_from_pb, bench_run_to_pb, fetch_bench_history, pb, submit_bench_run, testkit,
};
fn measured_run() -> nornir_bench::BenchRun {
let mut metrics = serde_json::Map::new();
metrics.insert("paths_per_sec".into(), serde_json::json!(1234.5));
// The telemetry metric the `core_saturation` gate reads — per-arm, riding the
// free-form map, so it only comes back if the WHOLE map round-trips.
metrics.insert("telem_proc_cores_max".into(), serde_json::json!(0.56));
// A NON-numeric metric: `KVF.value` is a double, so it cannot cross. Present so
// the loss stays a measured property of the RPC, in the read leg too.
metrics.insert("note".into(), serde_json::json!("not a number"));
nornir_bench::BenchRun {
// The producer mints its own id; the round trip must bring the SAME one
// back, which is what makes a re-submit idempotent rather than a second row.
id: nornir_bench::BenchRun::new_id(),
machine_facts: None,
date: "2026-08-18".into(),
timestamp: Some("2026-08-18T09:00:00Z".into()),
version: "0.6.1".into(),
machine: "oden".into(),
cores: 32,
results: vec![nornir_bench::BenchResult::measured(
"gunnar.walk_1m",
metrics,
)],
tests: vec![
nornir_bench::TestOutcome {
name: "gunnar.smoke".into(),
passed: true,
duration_ms: Some(12.5),
message: None,
},
nornir_bench::TestOutcome {
name: "gunnar.red_case".into(),
passed: false,
duration_ms: None,
message: Some("assertion left != right".into()),
},
],
}
}
/// ★ Submit → History is a genuine round trip: the run the server received over
/// the wire comes back as a `nornir_bench::BenchRun`, field-for-field.
#[test]
fn a_submitted_run_reads_back_over_history_field_for_field() {
let (srv, _log) = testkit::spawn_mock_bench();
let sent = measured_run();
submit_bench_run(&srv.endpoint, "", "nordisk", "gunnar", &sent)
.expect("submit against the live mock Bench server");
let hist = fetch_bench_history(&srv.endpoint, "", "nordisk", "gunnar")
.expect("history against the live mock Bench server");
// NOT the identity trap: exactly one run, and it is the one that was sent.
assert_eq!(
hist.len(),
1,
"the submitted run came back, and nothing else"
);
let got = &hist[0];
assert_eq!(got.date, sent.date);
assert_eq!(
got.timestamp, sent.timestamp,
"RFC3339 timestamp survives as Some"
);
assert_eq!(got.version, sent.version, "the SUBJECT version stamp");
assert_eq!(
got.machine, sent.machine,
"the host that partitions the row"
);
assert_eq!(got.cores, sent.cores);
// The measured numbers — the payload the mashup actually renders.
assert_eq!(got.results.len(), 1);
let r = &got.results[0];
assert_eq!(r.name, "gunnar.walk_1m");
assert_eq!(
r.metrics.get("paths_per_sec"),
Some(&serde_json::json!(1234.5))
);
assert_eq!(
r.metrics.get("telem_proc_cores_max"),
Some(&serde_json::json!(0.56)),
"the free-form map round-trips whole"
);
// The documented loss, still documented on the read leg: KVF.value is a
// double, so the non-numeric metric never crossed.
assert_eq!(
r.metrics.get("note"),
None,
"non-numeric metrics do not cross the wire"
);
// Test outcomes, including the Option flattening coming back honest.
assert_eq!(got.tests.len(), 2);
assert_eq!(got.tests[0].name, "gunnar.smoke");
assert!(got.tests[0].passed);
assert_eq!(got.tests[0].duration_ms, Some(12.5));
assert_eq!(
got.tests[0].message, None,
"an empty wire message maps back to None"
);
assert_eq!(got.tests[1].name, "gunnar.red_case");
assert!(!got.tests[1].passed);
assert_eq!(
got.tests[1].duration_ms, None,
"has_duration=false maps back to None, not Some(0.0)"
);
assert_eq!(
got.tests[1].message.as_deref(),
Some("assertion left != right")
);
}
/// ★ A repo nothing has measured is an EMPTY VEC — a normal state for the mashup
/// to render — never an error.
#[test]
fn an_unmeasured_repo_reads_back_as_an_empty_vec_not_an_error() {
let (srv, _log) = testkit::spawn_mock_bench();
// Something IS in the warehouse — just not for this repo — so an empty answer
// here is a filtered read, not a server that returns nothing for everything.
submit_bench_run(&srv.endpoint, "", "nordisk", "gunnar", &measured_run())
.expect("seed a different repo's run");
let hist = fetch_bench_history(&srv.endpoint, "", "nordisk", "never-benched")
.expect("an unmeasured repo must be Ok, not an error");
assert!(
hist.is_empty(),
"no runs for this repo ⇒ empty vec: {hist:?}"
);
}
/// ★ The failure states stay LOUD: a dead port and a reachable-but-refusing
/// server are errors, never a silent empty history.
#[test]
fn a_dead_or_refusing_server_is_an_error_never_an_empty_history() {
// Dead port: bind-then-drop so nothing listens there.
let addr = {
let l = std::net::TcpListener::bind("127.0.0.1:0").expect("probe port");
l.local_addr().expect("probe addr")
};
let err = fetch_bench_history(&format!("http://{addr}"), "", "", "gunnar")
.expect_err("a dead port must not read as an empty history");
assert!(
format!("{err:#}").contains("connect to nornir-server"),
"{err:#}"
);
// Reachable but refusing (the reject knob): the RPC error surfaces.
let (srv, log) = testkit::spawn_mock_bench();
log.reject("warehouse is sealed");
let err = fetch_bench_history(&srv.endpoint, "", "nordisk", "gunnar")
.expect_err("a refusing server must not read as an empty history");
assert!(format!("{err:#}").contains("Bench.History RPC"), "{err:#}");
}
/// The pure inverse mapping, pinned on a hand-built wire message — every mapped
/// field asserted, so the flattening rules cannot rot unobserved behind the
/// network tests above.
#[test]
fn bench_run_from_pb_maps_every_field_and_flattens_honestly() {
let wire = pb::BenchRun {
// Empty on the wire is the LEGACY case: `Uuid::nil`, "no identity", which
// a consumer must join heuristically and must never deduplicate on.
id: String::new(),
machine_facts_json: String::new(),
date: "2026-08-18".into(),
timestamp: String::new(), // absent on the wire
version: "1.2.3".into(),
machine: "frigg".into(),
cores: 8,
results: vec![pb::BenchResult {
name: "korp.ingest".into(),
metrics: vec![
pb::Kvf {
key: "rows_per_sec".into(),
value: 42.0,
},
pb::Kvf {
key: "not_a_json_number".into(),
value: f64::NAN,
},
],
}],
tests: vec![pb::TestOutcome {
name: "korp.smoke".into(),
passed: true,
duration_ms: 0.0,
has_duration: true, // a REAL zero, distinct from "not recorded"
message: "flaky on ci".into(),
}],
};
let run = bench_run_from_pb(wire);
assert_eq!(run.date, "2026-08-18");
assert_eq!(
run.timestamp, None,
"empty wire timestamp is None, never Some(\"\")"
);
assert_eq!(run.version, "1.2.3");
assert_eq!(run.machine, "frigg");
assert_eq!(run.cores, 8);
assert_eq!(run.results.len(), 1);
assert_eq!(run.results[0].name, "korp.ingest");
assert_eq!(
run.results[0].source,
nornir_bench::BenchSource::Measured,
"the source tag has no proto field — every wire row reads back Measured"
);
assert_eq!(
run.results[0].metrics.get("rows_per_sec"),
Some(&serde_json::json!(42.0))
);
assert_eq!(
run.results[0].metrics.get("not_a_json_number"),
None,
"a non-finite double has no JSON number — dropped, never smuggled as null"
);
assert_eq!(run.tests.len(), 1);
assert_eq!(
run.tests[0].duration_ms,
Some(0.0),
"a recorded 0 ms stays Some(0.0)"
);
assert_eq!(run.tests[0].message.as_deref(), Some("flaky on ci"));
// And the two pure mappings compose: to_pb ∘ from_pb is the identity on
// everything the wire can carry.
let sent = measured_run();
let back = bench_run_from_pb(bench_run_to_pb(&sent));
assert_eq!(back.date, sent.date);
assert_eq!(back.timestamp, sent.timestamp);
assert_eq!(back.cores, sent.cores);
assert_eq!(
back.results[0].metrics.get("paths_per_sec"),
Some(&serde_json::json!(1234.5))
);
}