//! `wai.delivery.fleet` (extensions/fleet.md): the committed corpus //! `live-conformance/fleet/vectors.json` regenerates byte for byte from its seeds and the metering //! corpus, and is the only file there besides its README; every vector gets the outcome it states; //! every reason the extension adds and every code it reuses refuses a vector; the accepted vectors //! are the cases §11 names, with measured, unmetered and partial energy stated as §5.4 states //! them; a fleet's records held as a service holds them sign the report the corpus holds; and §10 //! lists exactly the reasons the reference reports. #![cfg(feature = "fleet")] use std::collections::BTreeSet; use std::path::PathBuf; use serde_json::{json, Value}; use wai::fleet::{self, corpus, Held, Reason}; fn wai_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..") } fn read(p: &str) -> String { std::fs::read_to_string(wai_dir().join(p)).unwrap_or_else(|e| panic!("{p}: {e}")) } fn committed() -> String { read("live-conformance/fleet/vectors.json") } fn doc() -> Value { serde_json::from_str(&committed()).unwrap() } fn vector(d: &Value, name: &str) -> Value { d["vectors"].as_array().unwrap().iter().find(|v| v["name"] == name).unwrap_or_else(|| panic!("no vector {name}")).clone() } #[test] fn the_committed_corpus_regenerates_from_its_seeds_and_the_metering_corpus() { let generated = corpus::generate(&wai_dir()).expect("the corpus generates"); assert!(committed() == generated, "live-conformance/fleet/vectors.json differs from `wai_fleet_vectors gen`"); let mut files: Vec = std::fs::read_dir(wai_dir().join("live-conformance/fleet")).unwrap().flatten().map(|e| e.file_name().to_string_lossy().into_owned()).collect(); files.sort(); assert_eq!(files, ["README.md", "vectors.json"]); } #[test] fn every_vector_gets_its_stated_outcome() { let fails = corpus::verify(&committed()); assert!(fails.is_empty(), "{}", fails.join("\n")); } /// Every reason this extension adds and every code it reuses refuses a vector. #[test] fn the_corpus_refuses_every_reason() { let d = doc(); let seen: BTreeSet<&str> = d["vectors"].as_array().unwrap().iter().filter_map(|v| v["outcome"]["reason"].as_str()).collect(); for r in Reason::ALL.iter().chain(Reason::REUSED.iter()) { assert!(seen.contains(r.code()), "nothing in the corpus is refused {r}"); } } fn coverage(e: &Value, scope: &str) -> String { e[scope]["coverage"].as_str().unwrap().to_string() } fn classes(e: &Value, scope: &str) -> Vec { e[scope]["rows"].as_array().unwrap().iter().map(|r| r["class"].as_str().unwrap().to_string()).collect() } /// The accepted vectors are §11's, and state energy as §5.4 states it: measured with its class, /// unmetered as unmetered, a mix as partial, and a silent node as silent. #[test] fn the_accepted_vectors_state_measured_unmetered_and_partial_energy() { let d = doc(); let week = vector(&d, "a_week")["outcome"].clone(); assert_eq!(week["outcome"], "accept"); let lesson = &week["rooms"][0]; assert_eq!(classes(&lesson["energy"], "hops"), ["ModelBased", "Estimator", "OnChipCounter"], "one row per class, never one across them"); assert_eq!(coverage(&lesson["energy"], "hops"), "whole"); assert_eq!(coverage(&week["rooms"][1]["energy"], "hops"), "unmetered", "the reference relay's recorded hop"); assert_eq!(coverage(&week["totals"]["energy"], "hops"), "partial", "measured and unmetered hops together"); assert_eq!(coverage(&week["totals"]["energy"], "sessions"), "unmetered", "every session's figure is the marker"); assert_eq!(week["totals"]["energy"]["sessions"]["unmetered"], 7); assert_eq!(week["totals"]["energy"]["hops"]["unmetered"], 1); let silent: Vec<&str> = week["enrolments"].as_array().unwrap().iter().filter(|e| e["silent"] == true).map(|e| e["label"].as_str().unwrap()).collect(); assert_eq!(silent, ["room service"], "enrolled and silent: listed, with no line"); assert!(week["nodes"].as_array().unwrap().iter().all(|n| n["label"] != "room service")); let edge = week["nodes"].as_array().unwrap().iter().find(|n| n["label"] == "edge").unwrap(); let home = week["nodes"].as_array().unwrap().iter().find(|n| n["label"] == "home").unwrap(); assert_eq!((edge["links"].as_u64(), home["links"].as_u64()), (Some(1), Some(1)), "the edge's upstream link, one session at each end"); assert_eq!(edge["link_bytes_in"], home["link_bytes_out"], "what home sent over the link, the edge received"); assert!(week["nodes"].as_array().unwrap().iter().chain(week["rooms"].as_array().unwrap()).all(|l| !l["cites"].as_array().unwrap().is_empty()), "every line cites its records"); let measured = vector(&d, "measured_only")["outcome"].clone(); assert_eq!(coverage(&measured["totals"]["energy"], "hops"), "whole"); assert_eq!(coverage(&measured["totals"]["energy"], "sessions"), "none"); let row = &measured["totals"]["energy"]["hops"]["rows"][0]; assert_eq!((row["class"].as_str(), row["figures"].as_u64()), (Some("OnChipCounter"), Some(2))); assert!(row["max_ppm"].as_u64().unwrap() > 0, "the largest declared uncertainty of the two"); let unmetered = vector(&d, "unmetered_only")["outcome"].clone(); assert_eq!(coverage(&unmetered["totals"]["energy"], "sessions"), "unmetered"); assert_eq!(coverage(&unmetered["totals"]["energy"], "hops"), "none"); assert!(unmetered["totals"]["energy"]["sessions"]["rows"].as_array().unwrap().is_empty(), "no row, never a figure of zero joules"); let silent = vector(&d, "enrolled_and_silent")["outcome"].clone(); assert_eq!((silent["nodes"].as_array().unwrap().len(), silent["rooms"].as_array().unwrap().len()), (0, 0)); assert!(silent["enrolments"].as_array().unwrap().iter().all(|e| e["silent"] == true)); assert_eq!(coverage(&silent["totals"]["energy"], "hops"), "none"); } /// A fleet held as the service holds it (§9): the week's enrolments and records admitted one by /// one, in the corpus's order, sign the corpus's report byte for byte; each record is admitted /// once; and the per-hop records of a room come back in the ledger's source form (§8). #[test] fn a_held_fleet_signs_the_corpus_report() { let d = doc(); let week = vector(&d, "a_week"); let b = &week["bundle"]; let org_seed: [u8; 32] = { use sha2::{Digest, Sha256}; Sha256::new().chain_update(b"wai:fleet/corpus/key\x00").chain_update(b"organisation").finalize().into() }; let org = ed25519_dalek::SigningKey::from_bytes(&org_seed); let mut held = Held::new(org.verifying_key().to_bytes()); for e in b["enrolments"].as_array().unwrap() { held.enrol(&fleet::unhex(e.as_str().unwrap()).unwrap()).unwrap(); } assert_eq!(held.enrol(&fleet::unhex(b["enrolments"][0].as_str().unwrap()).unwrap()).unwrap_err(), Reason::EnrolmentDuplicate); for r in b["records"].as_array().unwrap() { held.admit(r).unwrap_or_else(|e| panic!("{r}: {e}")); } for r in b["records"].as_array().unwrap().iter().take(3) { assert_eq!(held.admit(r).unwrap_err(), Reason::RecordDuplicate, "a record is held once"); } let start = week["outcome"]["start"].as_u64().unwrap(); let end = week["outcome"]["end"].as_u64().unwrap(); let (report, bundle) = held.report(&org, start, end).unwrap(); assert_eq!(Value::String(fleet::hex(&report.to_bytes())), b["report"], "the corpus's report, byte for byte"); assert_eq!(fleet::outcome_json(&fleet::verify(&bundle)), week["outcome"]); let lesson = week["outcome"]["rooms"][0]["room"].as_str().unwrap(); let hops = held.hops_of(&fleet::unhex(lesson).unwrap().try_into().unwrap()); assert_eq!(hops.len(), 3); assert!(hops.iter().all(|h| h.as_object().unwrap().keys().cloned().collect::>() == ["record", "ledger"])); // A day of the week holds the lesson's records and none of the relay room's. let (_, day) = held.of_period(1_792_108_800_000_000, 1_792_195_200_000_000); assert!(day.iter().all(|(r, _)| !matches!(r, fleet::Record::Hop(h) if fleet::hex(&h.record.room) != lesson))); // A record of an unenrolled node, or before its descriptor, is refused. let mut empty = Held::new(org.verifying_key().to_bytes()); let hop = b["records"].as_array().unwrap().iter().find(|r| r["kind"] == "hop").unwrap(); assert_eq!(empty.admit(hop).unwrap_err(), Reason::SignerNotEnrolled); empty.enrol(&fleet::unhex(b["enrolments"][0].as_str().unwrap()).unwrap()).unwrap(); let e = empty.admit(&json!({"kind": "descriptor", "descriptor": "00"})); assert_eq!(e.unwrap_err(), Reason::Truncated); } /// §10 of the extension lists exactly the codes `Reason::ALL` has, each once, in order, and /// names every code `Reason::REUSED` has. #[test] fn the_extension_lists_the_reasons() { let text = read("extensions/fleet.md"); let section = text.split("\n## 10. Reasons").nth(1).unwrap().split("\n## 11.").next().unwrap(); let listed: Vec<&str> = section.lines().filter_map(|l| l.strip_prefix("| `")).filter_map(|l| l.split('`').next()).collect(); let ours: Vec<&str> = Reason::ALL.iter().map(|r| r.code()).collect(); assert_eq!(listed, ours); for r in Reason::REUSED { assert!(section.contains(&format!("`{}`", r.code())), "§10 does not name the reused code {r}"); } }