xtask/src/suite_check.rs
//! **`cargo xtask suite-check`: the Holger MVP suite, compiled and tested on every push**
//! (lane G2, 2026-10-23; A18 §4 #1, #2, #3 and #9).
//!
//! Before this verb, the MVP rows were compiled only by the manual gate, the 42
//! `paired.rs` unit tests ran nowhere, holger-estate-front's tests ran nowhere (it is
//! its own workspace, so `--workspace` does not reach it), and the `sign`-gated
//! evidence tests were never turned on. This verb runs them all, one step after the
//! other, and is red if any step is red.
//!
//! The plan is READ OFF THE DECLARATION, never restated:
//!
//! * `row-check:<row>`: every cargo row of the MVP delivery
//! (`holger_build_space::build_variant_set`) is compiled with `cargo check` and its
//! OWN argv (package, features, `--no-default-features`, target); a row with its own
//! `manifest_dir` is checked by its manifest path;
//! * `row-test:<row>`: every MVP row of the `holger` server binary on the host target
//! runs its unit tests under its own features (`--bins`; the MVP rows carry `paired`,
//! so this is where `paired.rs`'s tests run);
//! * `build:<feature>`: the `holger` binary with `paired`, `appliance` and
//! `secure_update` each on its own, the three builds A18 named;
//! * `front:mount`: server-lib's public-page mount under `--features front` (A28 M14: no default build has it);
//! * `front:default`, `front:metered`: holger-estate-front's whole suite, both ways;
//! * `front:wg-hub`: the front's `open_hub` on a REAL TUN (lane HOLGER-WG, A18 §4 #6) —
//! `wg_only::tests::open_hub_opens_the_overlay_interface_on_a_real_tun`, which skips by
//! name where `/dev/net/tun` cannot be opened, and is REQUIRED (`HOLGER_WG_TUN_REQUIRED=1`
//! in its environment) where this runner can open the node: a privileged container, the
//! KVM host. The step is the whole suite's test run again by its name, so it can be run
//! alone on such a runner (`--only front:wg-hub`);
//! * `trust:<name>`: the trust-depth tests of lane HOLGER-G3 ([`TRUST_STEPS`]): the
//! secrets scanner and its gate;
//! * `downstream:<name>`: the H3 downstream ([`DOWNSTREAM_STEPS`]): its shape guard, its
//! rules and its one line out, the real `holger-downstream` binary, the WireGuard
//! downstream (`downstream-wg`: its binary and its tunnel tests), and that binary
//! importing, pulling and serving an upstream's signed export;
//! * `estate:<name>`: H2's estate cut ([`estate_steps`]): server-lib's estate modules
//! and integration tests with `estate`, and the off halves without it;
//! * `sign:holger-server-lib`: every server-lib test target whose `required-features`
//! name `sign`, found in `cargo metadata` and run with exactly the features those
//! targets require;
//! * `board:admission`: the estate board's integration test, which counts consumers
//! only where the door admission's book is kept, run with `admission` DECLARED
//! (A18 §4 #10: before, that branch was reached by feature unification or not at all).
//!
//! It runs HOST cargo, like `cargo xtask test`: run it inside the toolchain container
//! (`nordisk-cargo-toolchain:live`), or in CI's job container. `--list` prints the plan
//! and runs nothing; `--only <prefix>` runs the steps whose label starts with it.
use std::path::Path;
use std::process::Command;
use anyhow::{bail, Context, Result};
/// One cargo invocation of the plan.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Step {
pub label: String,
pub args: Vec<String>,
/// Its environment beyond the runner's (`front:wg-hub` requires the TUN where it can).
pub env: Vec<(String, String)>,
}
impl Step {
fn new(label: impl Into<String>, args: Vec<String>) -> Step {
Step {
label: label.into(),
args,
env: Vec::new(),
}
}
}
/// The front's real-TUN test (holger-estate-front `wg_only::tests`).
pub const WG_HUB_TEST: &str = "wg_only::tests::open_hub_opens_the_overlay_interface_on_a_real_tun";
/// Its switch (holger-estate-front `wg_only::TUN_REQUIRED_ENV`): set, the test may not skip.
pub const WG_TUN_REQUIRED_ENV: &str = "HOLGER_WG_TUN_REQUIRED";
/// Pure: **the `front:wg-hub` step** — the real-TUN test by name, with `--nocapture` so a
/// skip is said. It is REQUIRED (the test may not skip) only when `required` — which the caller
/// takes from the runner's own [`WG_TUN_REQUIRED_ENV`]: a privileged runner that can create a
/// TUN (the KVM gate host, a privileged CI container) exports `HOLGER_WG_TUN_REQUIRED=1` before
/// `cargo xtask suite-check`, and the step hands it to the test; a plain container leaves it
/// unset and the test skips by name where `/dev/net/tun` cannot be used. Opening the node is
/// NOT the gate (opening succeeds without `CAP_NET_ADMIN`, which `TUNSETIFF` then needs), so the
/// requirement is the runner's explicit word, never a guess.
pub fn wg_hub_step(required: bool) -> Step {
let args = [
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--lib",
WG_HUB_TEST,
"--",
"--nocapture",
]
.map(String::from)
.to_vec();
Step {
label: "front:wg-hub".into(),
args,
env: if required {
vec![(WG_TUN_REQUIRED_ENV.to_string(), "1".to_string())]
} else {
Vec::new()
},
}
}
/// Did the runner ask for the real TUN (exported `HOLGER_WG_TUN_REQUIRED=1`)?
pub fn tun_required() -> bool {
std::env::var(WG_TUN_REQUIRED_ENV).is_ok_and(|v| v.trim() == "1")
}
/// The suite whose rows this verb compiles.
pub const SUITE: &str = "MVP";
/// **The trust-depth arms** (lane G3, A18 P0 #2): the tests of the scanners and
/// verifiers G3 added, each its own step `trust:<name>`, `(name, cargo args)`. One line per arm.
pub const TRUST_STEPS: &[(&str, &[&str])] = &[
// Wolfi APK provenance: real Wolfi indexes (RSA256 and RSA/SHA-1) and packages, offline.
(
"apk-provenance",
&[
"test",
"-p",
"holger-provenance",
"--test",
"apk_wolfi",
"--test",
"minted",
],
),
// The same through the server: the apk source, the worker's keys, the intake chain.
(
"apk-intake",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"supply-chain,jobs,pull-apk",
"--lib",
"--",
"apk",
],
),
// Lane T8: the APK pull-through (real Wolfi bytes behind a fake upstream): the pinned
// upstream index, the not-yet answers, Holger's own signed index of AVAILABLE packages.
(
"apk-pull",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"jobs,online,supply-chain,pull-apk",
"--test",
"pull_through_apk",
],
),
// The secrets scanner in the scan worker, its rules and the gates.secrets policy.
(
"secrets",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"supply-chain,jobs",
"--no-fail-fast",
"--lib",
"--test",
"tier1_sources_steps_rules",
"--",
"secret",
],
),
// T9b: OpenPGP (Maven Central's `.asc`) is opt-in. With holger-provenance's `pgp`:
// T9's real Central signatures, and the build-feature tests on their built side.
(
"maven-pgp",
&[
"test",
"-p",
"holger-provenance",
"--features",
"pgp",
"--test",
"maven_pgp",
"--test",
"pgp_build_feature",
"--test",
"minted",
],
),
// Without it, as the default `holger` is built: every pgp pin refused by name.
(
"pgp-not-built",
&[
"test",
"-p",
"holger-provenance",
"--lib",
"--test",
"pgp_build_feature",
],
),
// The same through the server without `maven-pgp`: the pull-through source, the
// scanner's floor and the worker's keys refuse the pin by name.
(
"pgp-intake-not-built",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"supply-chain,jobs",
"--lib",
"--",
"pgp",
],
),
// And with `maven-pgp`: the worker, the scanner and T9's Maven Central pull-through
// held to its `.asc` (server-lib's `online` does not carry the verifier; the CLI's does).
(
"maven-pgp-intake",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"jobs,online,supply-chain,maven-pgp",
"--lib",
"--test",
"pull_through_npm_maven_crates",
"--",
"pgp",
],
),
// H4, the sync protocol: the signed documents, the ledger and the alarm.
("sync-protocol", &["test", "-p", "holger-sync"]),
// Two Holgers in one process: USB mode, pull mode over the door, the alarm, the tick job.
(
"sync-two-holgers",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"jobs,online,sync,supply-chain",
"--test",
"sync_between_two_holgers",
],
),
// The airgap bundle that carries the manifest, and the CLI's stick verbs.
(
"sync-bundle",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign,sync",
"--test",
"airgap_export_import",
"--",
"sync",
],
),
// The whole airgap export and import (the AVAILABLE set with its evidence and signed
// attestations, verified and imported on the other side; lane OX-WIRED2).
(
"airgap-export",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign",
"--test",
"airgap_export_import",
],
),
// An invalidated package drops out of every index (Maven, cargo, npm, PEP 503/691, OCI tags).
(
"sync-indexes",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"jobs,online,supply-chain",
"--test",
"pull_through_npm_maven_crates",
"--test",
"pull_through_runs_the_intake_chain",
"--",
"invalidated",
],
),
// H6: Go modules pulled from a GOPROXY through the intake chain (held to the module zip
// rules, scanned as the module at its version), and served from the sealed store.
(
"go-pull",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"jobs,online,supply-chain",
"--lib",
"--test",
"pull_through_npm_maven_crates",
"--",
"go_",
"pull_intake::go",
],
),
// The image catalog: the rpm sqlite database, Go build info and cargo-auditable.
(
"image-catalog",
&["test", "-p", "holger-inspect", "--lib", "--no-fail-fast"],
),
// Those packages reaching the advisory match, and the `wolfi` apk grammar (modgunn 0.0.8).
(
"image-match",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"supply-chain,jobs",
"--lib",
"--no-fail-fast",
"--",
"sandbox::tests::an_image",
"intel::tests::a_wolfi_rebuild",
],
),
];
/// **The public page's mount, tested where it is built** (A28 M14): `front` left server-lib's
/// `default`, so its mount tests (`exposed::http`) and the page half of
/// `the_default_server_serves_no_page` run here, under `--features front`, and nowhere else.
pub const FRONT_MOUNT_STEP: &[&str] = &[
"test",
"-p",
"holger-server-lib",
"--features",
"front",
"--no-fail-fast",
"--lib",
"--test",
"the_default_server_serves_no_page",
"--",
"the_front_door_is_reached_by_head_and_by_a_write",
"the_mount_names_every_path_the_door_owns",
"the_http_door_serves_the_page_only_where_front_is_built",
"the_default_features_name_no_front",
];
/// The three server builds A18 §4 #3 names besides the rows.
pub const FEATURE_BUILDS: [&str; 3] = ["paired", "appliance", "secure_update"];
/// A row's own argv with the verb swapped and the profile dropped: `check` and
/// `test` share one debug cache, and a profile changes no feature. A row with its own
/// `manifest_dir` (holger-estate-front) is reached by its manifest path, not `-p`.
pub(crate) fn row_args(v: &nornir_build_thing::BuildVariant, verb: &str) -> Vec<String> {
let mut out = vec![verb.to_string()];
let args = v.cargo_args();
if let Some(dir) = &v.manifest_dir {
if !args.iter().any(|a| a == "--manifest-path") {
out.push("--manifest-path".into());
out.push(format!("{dir}/Cargo.toml"));
}
}
let mut it = args.into_iter().skip(1);
while let Some(a) = it.next() {
match a.as_str() {
"--profile" => {
it.next();
}
"-p" if v.manifest_dir.is_some() => {
it.next();
}
_ => out.push(a),
}
}
out
}
fn is_mvp_cargo(v: &nornir_build_thing::BuildVariant) -> bool {
v.suites.iter().any(|s| s == SUITE) && v.kind.is_cargo()
}
/// **The downstream's steps** (Holger v2.0 H3), each `downstream:<name>`, `(name, cargo args)`,
/// in order: the shape (no scanner, no wasm, no estate, no renderer, no internet client, and
/// clearly smaller than the default), its rules, its one line out, its views, the real
/// `holger-downstream` binary, the WireGuard downstream's binary and tunnel tests
/// (`downstream-wg`), and that binary importing, pulling and serving an upstream's
/// signed export, and the H6 end-to-end gate compiled (`cargo xtask e2e` runs it with its
/// real clients: pip, uv, cargo, mvn, skopeo and go).
pub const DOWNSTREAM_STEPS: &[(&str, &[&str])] = &[
(
"shape",
&[
"test",
"--manifest-path",
"estate/Cargo.toml",
"-p",
"holger-recipe",
"--test",
"downstream_shape",
],
),
("rules", &["test", "-p", "holger-downstream-rules"]),
(
"egress",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"downstream,gateway",
"--test",
"a_downstream_dials_only_its_upstream",
],
),
// The fetching downstream's one line out (lane HOL-CDS: `fetch` built, `boundary: Fetch`);
// the step above is the one-way downstream's (a mirror refused by line, nothing dialled).
(
"egress-fetch",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"downstream,gateway,fetch",
"--test",
"a_downstream_dials_only_its_upstream",
],
),
(
"views",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"downstream,gateway",
"--lib",
"--",
"pull_intake::crates",
"pull_intake::go",
],
),
// `sandbox-off`: the toolchain image has no container engine, so the binary's
// verify-bundle jobs run in-process (lane HOL-SANDBOX-TRAIT); a shipped one never does.
(
"build",
&[
"build",
"--manifest-path",
"holger-downstream/Cargo.toml",
"-p",
"holger-downstream",
"--features",
"sandbox-off",
"--bin",
"holger-downstream",
],
),
// Lane HOL-CDS: that binary is ONE-WAY. The upstream pushes into the diode folder, the
// binary imports through its inbox after the admin's first-import authorization and
// refuses a way out by line; its tree links no client and no server-lib `fetch`. Run
// here, while the binary beside the tests is still the one-way build (wg-build below
// overwrites it with the fetching one, which `serve` drives).
(
"one-way",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign,jobs,sync",
"--test",
"one_way_downstream",
"--test",
"one_way_ships_no_client",
],
),
// F9 (the field test of 2026-11-01): a downstream written as the guide writes it
// (`steps:` and `sources:`, each source with no `url`) serves the image it imported, with
// its referrers, from the ONE-WAY binary as well; `serve` below drives the fetching one.
(
"one-way-sources",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign,jobs,sync",
"--test",
"downstream_serves_the_build_systems",
"--",
"a_downstream_written_with_sources",
],
),
// The WireGuard downstream (lane HOL-WGDS, `downstream-wg`, default-off): the binary built
// with its tunnel, and the tunnel's own tests (the signed invite kept once, the one route).
(
"wg-build",
&[
"build",
"--manifest-path",
"holger-downstream/Cargo.toml",
"-p",
"holger-downstream",
"--features",
"downstream-wg,sandbox-off",
"--bin",
"holger-downstream",
],
),
(
"wg-tunnel",
&[
"test",
"-p",
"holger-server-lib",
"--no-default-features",
"--features",
"downstream,downstream-wg",
"--lib",
"--",
"sync::tunnel",
],
),
// The WireGuard downstream takes the upstream's signed invite through its own door
// (OX-WGDS3; lane OX-WIRED2 put it in a step).
(
"wg-invite",
&[
"test",
"-p",
"holger-server-lib",
"--features",
"downstream-wg",
"--test",
"a_downstream_takes_its_invite_through_its_door",
],
),
(
"serve",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign,jobs,sync",
"--test",
"downstream_serves_the_build_systems",
// The two `boundary: Fetch` tests (pull, invalidation ack) need the FETCHING
// binary, which downstream:wg-build left beside holger; a run after the one-way
// build leaves them ignored by name. Not the real-client one (podman, CI full set).
"--",
"--include-ignored",
"a_downstream_",
"an_invalidated_package",
],
),
// H6: the end-to-end gate, compiled on every push. Here it skips by name (no mvn, go,
// uv or skopeo in the toolchain image); `cargo xtask e2e` runs it in its clients image.
(
"e2e",
&[
"test",
"-p",
"holger",
"--features",
"supply-chain,secure_update,sign,jobs,sync,online,fmt-all",
"--test",
"e2e_internet_to_build_systems",
],
),
];
/// **The thin client's steps** (lane B3, .nornir/SUITES.md `cli`), each `cli:<name>`: its
/// units; every console call is a command (the sibling holger-ui read when it is beside us);
/// thin and airgapped (its dependencies, the one connection to `--at`); every command group
/// against a REAL holger in the test process, the bundle export and the first-key doors among
/// them; and the binary `cargo install --path holger-cli` gives.
pub const CLI_STEPS: &[(&str, &[&str])] = &[
("unit", &["test", "-p", "holger-cli", "--lib", "--bins"]),
(
"parity",
&[
"test",
"-p",
"holger-cli",
"--test",
"every_ui_call_is_a_command",
],
),
(
"thin",
&["test", "-p", "holger-cli", "--test", "thin_and_airgapped"],
),
(
"server",
&["test", "-p", "holger-cli", "--test", "against_a_holger"],
),
(
"build",
&["build", "-p", "holger-cli", "--bin", "holger-cli"],
),
// `holger-cli --at https://<repo host>` through vm1's front to a real primary (B3 train 3).
(
"front",
&[
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--test",
"holger_cli_reaches_the_estate_through_the_front",
],
),
];
/// **The estate's integration tests** (H2's estate cut, HCUT 2026-10-26): server-lib test
/// targets whose `required-features` are `["estate"]` — the twin over mutual TLS, certify,
/// the recharge lane and the pairing renewal. No default or downstream build reaches them.
pub const ESTATE_TESTS: &[&str] = &[
"a_dead_main_is_recharged_from_its_remote_twin",
"pairing_renewal",
"the_twin_follows_over_mutual_tls_across_addresses",
"the_twin_follows_at_once_when_certified",
];
/// **The shipped estate declaration's tests**: they boot `holger_recipe::estate_ron`, which
/// names a `replication_door`, so they need `estate` (and `supply-chain`, the declaration's
/// intake chain).
pub const ESTATE_DECLARATION_TESTS: &[&str] = &[
"the_estate_declaration_runs_the_intake_chain",
"the_estate_declaration_serves_npm_through_the_intake_chain",
"the_shipped_declaration_keeps_the_fronts_installer_material",
"an_airgap_estate_box_imports_signed_intel",
"the_shipped_declaration_lets_the_front_certify_the_twin",
"the_fed_public_repositories_are_read_with_no_sign_in",
// HOL-MVP-FORMATS: the shipped declaration installs the provenance scanner.
"the_estate_declaration_runs_the_provenance_scanner",
];
/// **The estate's steps**, each `estate:<name>`: server-lib's estate modules' unit tests
/// with `estate` (`lib`), the estate integration tests ([`ESTATE_TESTS`], `twin`), and the
/// off halves a build without the estate answers with (`off`, the default features).
pub fn estate_steps() -> Vec<Step> {
let s = |v: &[&str]| v.iter().map(|a| a.to_string()).collect::<Vec<_>>();
let lib = s(&[
"test",
"-p",
"holger-server-lib",
"--features",
"estate",
"--lib",
"--",
"grow::",
"twin_tls::",
"admin_view::",
"cert_health::",
"recharge_lane::",
"twin::",
"admin_view_tests::the_admins_snapshot",
]);
let mut twin = s(&[
"test",
"-p",
"holger-server-lib",
"--features",
"estate",
"--no-fail-fast",
]);
for t in ESTATE_TESTS {
twin.extend(["--test".to_string(), t.to_string()]);
}
let off = s(&[
"test",
"-p",
"holger-server-lib",
"--lib",
"--",
"plane_off",
"mtls_off",
"disks_off",
"admin_view_tests::the_admins_snapshot",
]);
let mut decl = s(&[
"test",
"-p",
"holger-server-lib",
"--features",
"estate,supply-chain,auth-passkey",
"--no-fail-fast",
]);
for t in ESTATE_DECLARATION_TESTS {
decl.extend(["--test".to_string(), t.to_string()]);
}
vec![
Step::new("estate:lib", lib),
Step::new("estate:twin", twin),
Step::new("estate:declaration", decl),
Step::new("estate:off", off),
]
}
/// The plan from the declared rows (not yet the `sign` steps, which need cargo metadata).
pub fn plan_from_rows(rows: &[nornir_build_thing::BuildVariant]) -> Vec<Step> {
let mut steps = Vec::new();
let mut checked = std::collections::BTreeSet::new();
for v in rows.iter().filter(|v| is_mvp_cargo(v)) {
if checked.insert(v.name.clone()) {
steps.push(Step::new(
format!("row-check:{}", v.name),
row_args(v, "check"),
));
}
}
// The server rows' unit tests, on the host: `--bins` and no `--bin` (every bin the
// features enable runs its tests) and no `--target` (a musl row's tests run on the host
// triple). A row whose feature set an earlier row already tested is not tested again.
// The DEV `…-narrate` rows are their payloads plus the sender: checked above, not tested.
let mut tested: std::collections::BTreeSet<Vec<String>> = std::collections::BTreeSet::new();
for v in rows.iter().filter(|v| {
is_mvp_cargo(v)
&& v.package.as_deref() == Some(holger_recipe::variants::SERVER_CLI)
&& v.manifest_dir.is_none()
&& !v.features.iter().any(|f| f == "dev-narrate")
}) {
let mut key = v.features.clone();
key.sort();
if !tested.insert(key) {
continue;
}
let mut args: Vec<String> = row_args(v, "test");
for flag in ["--bin", "--target"] {
if let Some(i) = args.iter().position(|a| a == flag) {
args.drain(i..i + 2);
}
}
args.insert(3, "--bins".into());
args.push("--no-fail-fast".into());
steps.push(Step::new(format!("row-test:{}", v.name), args));
}
for f in FEATURE_BUILDS {
steps.push(Step::new(
format!("build:{f}"),
[
"check",
"-p",
holger_recipe::variants::SERVER_CLI,
"--features",
f,
]
.map(String::from)
.to_vec(),
));
}
for (name, args) in TRUST_STEPS {
steps.push(Step::new(
format!("trust:{name}"),
args.iter().map(|a| a.to_string()).collect(),
));
}
for (name, args) in DOWNSTREAM_STEPS {
steps.push(Step::new(
format!("downstream:{name}"),
args.iter().map(|a| a.to_string()).collect(),
));
}
for (name, args) in CLI_STEPS {
steps.push(Step::new(
format!("cli:{name}"),
args.iter().map(|a| a.to_string()).collect(),
));
}
steps.extend(estate_steps());
steps.push(Step::new(
"front:mount",
FRONT_MOUNT_STEP.iter().map(|a| a.to_string()).collect(),
));
let front = [
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--no-fail-fast",
]
.map(String::from)
.to_vec();
steps.push(Step::new("front:default", front.clone()));
let mut metered = front;
metered.extend(["--features".to_string(), "metered".to_string()]);
steps.push(Step::new("front:metered", metered));
steps.push(wg_hub_step(tun_required()));
steps
}
/// The `sign` steps from `cargo metadata --no-deps --format-version 1`: per package
/// that has them, its test targets whose `required-features` name `sign`, run together
/// with the union of what they require.
pub fn sign_steps(metadata: &serde_json::Value) -> Vec<Step> {
let mut steps = Vec::new();
for pkg in metadata["packages"].as_array().into_iter().flatten() {
let name = pkg["name"].as_str().unwrap_or_default();
if name != SIGN_PACKAGE {
continue;
}
let mut tests = std::collections::BTreeSet::new();
let mut features = std::collections::BTreeSet::new();
for t in pkg["targets"].as_array().into_iter().flatten() {
let is_test = t["kind"]
.as_array()
.is_some_and(|k| k.iter().any(|k| k == "test"));
let req: Vec<&str> = t["required-features"]
.as_array()
.into_iter()
.flatten()
.filter_map(|f| f.as_str())
.collect();
if is_test && req.contains(&"sign") {
tests.insert(t["name"].as_str().unwrap_or_default().to_string());
features.extend(req.iter().map(|f| f.to_string()));
}
}
if tests.is_empty() {
continue;
}
let mut args = vec![
"test".to_string(),
"-p".into(),
name.to_string(),
"--features".into(),
features.into_iter().collect::<Vec<_>>().join(","),
"--no-fail-fast".into(),
];
for t in tests {
args.push("--test".into());
args.push(t);
}
steps.push(Step::new(format!("sign:{name}"), args));
}
steps
}
/// The package whose `sign`-gated tests are dark without this verb (A18 §3).
pub const SIGN_PACKAGE: &str = "holger-server-lib";
/// The estate board's integration test (A13), and the feature it declares (A18 §4 #10).
pub const BOARD_TEST: &str = "the_estate_board_counts_upstreams_downstreams_and_consumers";
pub const BOARD_FEATURE: &str = "admission";
/// The board step: the one test, with its declared feature.
pub fn board_step() -> Step {
Step {
label: format!("board:{BOARD_FEATURE}"),
args: [
"test",
"-p",
SIGN_PACKAGE,
"--features",
BOARD_FEATURE,
"--no-fail-fast",
"--test",
BOARD_TEST,
]
.map(String::from)
.to_vec(),
env: Vec::new(),
}
}
fn cargo() -> std::ffi::OsString {
std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into())
}
/// The whole plan: the rows', then the `sign` steps from this checkout's metadata.
pub fn plan(root: &Path) -> Result<Vec<Step>> {
let set = holger_build_space::build_variant_set()?;
let mut steps = plan_from_rows(&set.variants);
let out = Command::new(cargo())
.args(["metadata", "--no-deps", "--format-version", "1"])
.current_dir(root)
.output()
.context("running cargo metadata")?;
if !out.status.success() {
bail!(
"cargo metadata failed: {}",
String::from_utf8_lossy(&out.stderr)
);
}
let meta: serde_json::Value =
serde_json::from_slice(&out.stdout).context("reading cargo metadata")?;
let sign = sign_steps(&meta);
if sign.is_empty() {
bail!("no {SIGN_PACKAGE} test target requires `sign`: the sign step would run nothing");
}
steps.extend(sign);
steps.push(board_step());
Ok(steps)
}
fn only() -> Option<String> {
let args: Vec<String> = std::env::args().skip(2).collect();
args.iter()
.position(|a| a == "--only")
.and_then(|i| args.get(i + 1).cloned())
}
pub fn list(root: &Path) -> Result<()> {
for s in plan(root)? {
let env: String = s.env.iter().map(|(k, v)| format!("{k}={v} ")).collect();
println!("{:<34} {env}cargo {}", s.label, s.args.join(" "));
}
Ok(())
}
/// `holger-downstream` is a workspace of its own: a build of it goes into the ROOT's target
/// directory (`--target-dir`), beside the `holger` whose tests look for it there.
pub fn with_root_target(root: &Path, args: &[String]) -> Vec<String> {
let mut out = args.to_vec();
if let Some(i) = out.iter().position(|a| a == "holger-downstream/Cargo.toml") {
let target = std::env::var_os("CARGO_TARGET_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|| root.join("target"));
out.insert(i + 1, "--target-dir".into());
out.insert(i + 2, target.display().to_string());
}
out
}
pub fn run(root: &Path) -> Result<()> {
let only = only();
let steps: Vec<Step> = plan(root)?
.into_iter()
.filter(|s| only.as_deref().is_none_or(|p| s.label.starts_with(p)))
.collect();
if steps.is_empty() {
bail!(
"suite-check: no step matches --only {}",
only.unwrap_or_default()
);
}
let mut red = Vec::new();
for s in &steps {
let env: String = s.env.iter().map(|(k, v)| format!("{k}={v} ")).collect();
println!(
"\n=== suite-check {} : {env}cargo {} ===",
s.label,
s.args.join(" ")
);
let t0 = std::time::Instant::now();
let ok = Command::new(cargo())
.args(with_root_target(root, &s.args))
.envs(s.env.iter().cloned())
.current_dir(root)
.status()
.with_context(|| format!("running {}", s.label))?
.success();
println!(
"=== {} : {} in {:.0} s ===",
s.label,
if ok { "green" } else { "RED" },
t0.elapsed().as_secs_f64()
);
if !ok {
red.push(s.label.clone());
}
}
println!(
"\n=== suite-check: {} of {} step(s) green ===",
steps.len() - red.len(),
steps.len()
);
if red.is_empty() {
return Ok(());
}
bail!("suite-check RED: {}", red.join(", "))
}
#[cfg(test)]
mod tests {
use super::*;
fn rows() -> Vec<nornir_build_thing::BuildVariant> {
holger_build_space::build_variant_set()
.expect("the declaration loads")
.variants
}
fn labels(steps: &[Step]) -> Vec<String> {
steps.iter().map(|s| s.label.clone()).collect()
}
#[test]
fn every_mvp_cargo_row_is_checked_with_its_own_features() {
let rows = rows();
let steps = plan_from_rows(&rows);
let mvp: Vec<_> = rows
.iter()
.filter(|v| v.suites.iter().any(|s| s == SUITE) && v.kind.is_cargo())
.collect();
assert!(
mvp.len() >= 5,
"the MVP delivery has its cargo rows: {:?}",
mvp.iter().map(|v| &v.name).collect::<Vec<_>>()
);
for v in mvp {
let step = steps
.iter()
.find(|s| s.label == format!("row-check:{}", v.name))
.unwrap_or_else(|| panic!("{} is not checked: {:?}", v.name, labels(&steps)));
assert_eq!(step.args[0], "check");
if !v.features.is_empty() {
let i = step
.args
.iter()
.position(|a| a == "--features")
.expect("the row's features are passed");
assert_eq!(step.args[i + 1], v.features.join(","), "{}", v.name);
}
if let Some(t) = &v.target {
assert!(
step.args
.windows(2)
.any(|w| w[0] == "--target" && &w[1] == t),
"{} keeps its target",
v.name
);
}
if let Some(dir) = &v.manifest_dir {
assert!(
step.args
.windows(2)
.any(|w| w[0] == "--manifest-path" && w[1] == format!("{dir}/Cargo.toml")),
"{} is checked by its own manifest: {:?}",
v.name,
step.args
);
assert!(
!step.args.iter().any(|a| a == "-p"),
"{}: no -p beside a manifest path",
v.name
);
assert_eq!(
step.args.iter().filter(|a| *a == "--manifest-path").count(),
1,
"{}: one manifest path: {:?}",
v.name,
step.args
);
}
}
}
#[test]
fn the_paired_unit_tests_run_under_the_mvp_server_row() {
let steps = plan_from_rows(&rows());
let step = steps
.iter()
.find(|s| s.label == "row-test:mvp-server-musl")
.unwrap_or_else(|| panic!("no row-test:mvp-server-musl: {:?}", labels(&steps)));
assert_eq!(&step.args[..3], ["test", "-p", "holger"]);
assert!(
step.args.iter().any(|a| a == "--bins"),
"the bins' unit tests: {:?}",
step.args
);
let i = step.args.iter().position(|a| a == "--features").unwrap();
assert!(
step.args[i + 1].split(',').any(|f| f == "paired"),
"the row carries paired: {:?}",
step.args
);
assert!(
!step.args.iter().any(|a| a == "--bin" || a == "--target"),
"all bins, host target: {:?}",
step.args
);
}
#[test]
fn paired_appliance_and_secure_update_each_build() {
let steps = plan_from_rows(&rows());
for f in FEATURE_BUILDS {
let step = steps
.iter()
.find(|s| s.label == format!("build:{f}"))
.unwrap_or_else(|| panic!("no build:{f}"));
assert_eq!(step.args, ["check", "-p", "holger", "--features", f]);
}
}
#[test]
fn the_trust_depth_tests_are_steps() {
let steps = plan_from_rows(&rows());
for (name, args) in TRUST_STEPS {
let step = steps
.iter()
.find(|s| s.label == format!("trust:{name}"))
.unwrap_or_else(|| panic!("trust:{name}"));
assert_eq!(
step.args,
args.iter().map(|a| a.to_string()).collect::<Vec<_>>()
);
}
assert!(steps.iter().any(|s| s.label == "trust:image-catalog"));
}
/// H4: the sync protocol's documents, the two Holgers in one process (USB, pull,
/// the alarm, the tick job), the bundle that carries a manifest, and every index
/// dropping an invalidated package each run in the suite with their features.
#[test]
fn the_sync_protocol_runs_in_the_suite() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
assert_eq!(step("trust:sync-protocol"), ["test", "-p", "holger-sync"]);
let two = step("trust:sync-two-holgers");
assert!(
two.windows(2)
.any(|w| w == ["--features", "jobs,online,sync,supply-chain"]),
"{two:?}"
);
assert!(
two.windows(2)
.any(|w| w == ["--test", "sync_between_two_holgers"]),
"{two:?}"
);
let bundle = step("trust:sync-bundle");
assert!(
bundle.windows(2).any(|w| w == ["-p", "holger"])
&& bundle.iter().any(|a| a.contains("sync")),
"{bundle:?}"
);
let idx = step("trust:sync-indexes");
for t in [
"pull_through_npm_maven_crates",
"pull_through_runs_the_intake_chain",
] {
assert!(idx.windows(2).any(|w| w == ["--test", t]), "{idx:?}");
}
assert_eq!(
idx.last().map(String::as_str),
Some("invalidated"),
"{idx:?}"
);
// B1: the Go index is one of them (its `@v/list` and `@latest` drop the version).
let go = std::fs::read_to_string(
crate::workspace_root().join("server/lib/tests/pull_through_npm_maven_crates.rs"),
)
.expect("the test");
assert!(
go.contains(
"fn an_invalidated_go_module_version_drops_from_list_and_latest_and_is_refused()"
),
"the Go index's invalidation test is in pull_through_npm_maven_crates"
);
}
/// ★ H3: the downstream's steps run in order, the real binary built before the test
/// that drives it, and the shape guard first.
#[test]
fn the_downstream_is_built_and_tested_on_every_push() {
let steps = plan_from_rows(&rows());
let at = |n: &str| {
steps
.iter()
.position(|s| s.label == format!("downstream:{n}"))
.unwrap_or_else(|| panic!("no downstream:{n}: {:?}", labels(&steps)))
};
assert!(
at("shape") < at("build") && at("build") < at("serve"),
"{:?}",
labels(&steps)
);
// The one-way tests drive the one-way binary: after `build`, before `wg-build` (fetch).
for one_way in ["one-way", "one-way-sources"] {
assert!(
at("build") < at(one_way) && at(one_way) < at("wg-build"),
"{one_way}: {:?}",
labels(&steps)
);
}
let build = &steps[at("build")];
assert!(
build
.args
.windows(2)
.any(|w| w[0] == "-p" && w[1] == "holger-downstream"),
"the product crate: {:?}",
build.args
);
let t = std::fs::read_to_string(
crate::workspace_root().join("server/cli/tests/downstream_serves_the_build_systems.rs"),
)
.expect("the test");
assert!(
t.contains("with_file_name(\"holger-downstream\")"),
"the test drives the binary the build step made"
);
}
/// ★ The WireGuard downstream (`downstream-wg`, lane HOL-WGDS) is compiled and its
/// tunnel tested on every push: the product crate with `downstream-wg`, and server-lib's
/// `sync::tunnel` tests with `downstream-wg`.
#[test]
fn the_wireguard_downstream_is_built_and_its_tunnel_tested_on_every_push() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
let build = step("downstream:wg-build");
assert_eq!(build[0], "build", "{build:?}");
assert!(
build.windows(2).any(|w| w == ["-p", "holger-downstream"]),
"{build:?}"
);
// …into the root's target directory, beside the `holger` its tests run.
let at = with_root_target(
Path::new("/r"),
&build.iter().map(|a| a.to_string()).collect::<Vec<_>>(),
);
assert!(at.windows(2).any(|w| w[0] == "--target-dir"), "{at:?}");
// `sandbox-off` beside it (lane HOL-SANDBOX-TRAIT): no container engine in the image.
assert!(
build
.windows(2)
.any(|w| w[0] == "--features" && w[1].split(',').any(|f| f == "downstream-wg")),
"{build:?}"
);
assert!(
build
.windows(2)
.any(|w| w == ["--bin", "holger-downstream"]),
"{build:?}"
);
let tunnel = step("downstream:wg-tunnel");
assert_eq!(tunnel[0], "test", "{tunnel:?}");
assert!(
tunnel.windows(2).any(|w| w == ["-p", "holger-server-lib"]),
"{tunnel:?}"
);
assert!(
tunnel
.windows(2)
.any(|w| w[0] == "--features" && w[1].split(',').any(|f| f == "downstream-wg")),
"{tunnel:?}"
);
assert!(
tunnel.iter().any(|a| a == "sync::tunnel"),
"the tunnel's tests: {tunnel:?}"
);
}
/// ★ Lane OX-WIRED2: the WireGuard downstream's invite door and the whole airgap export
/// and import are run on every push (before, the invite door ran in no CI step, and of
/// airgap_export_import only its `sync` tests ran).
#[test]
fn the_wireguard_invite_door_and_the_whole_airgap_export_run_on_every_push() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
let invite = step("downstream:wg-invite");
assert_eq!(invite[0], "test", "{invite:?}");
assert!(
invite
.windows(2)
.any(|w| w[0] == "--features" && w[1].split(',').any(|f| f == "downstream-wg")),
"{invite:?}"
);
assert!(
invite
.windows(2)
.any(|w| w == ["--test", "a_downstream_takes_its_invite_through_its_door"]),
"{invite:?}"
);
let airgap = step("trust:airgap-export");
assert!(
airgap
.windows(2)
.any(|w| w == ["--test", "airgap_export_import"]),
"{airgap:?}"
);
assert!(
!airgap.iter().any(|a| a == "--"),
"every test of it, not a filter: {airgap:?}"
);
for f in ["supply-chain", "secure_update", "sign"] {
assert!(
airgap
.windows(2)
.any(|w| w[0] == "--features" && w[1].split(',').any(|x| x == f)),
"{f}: {airgap:?}"
);
}
}
/// ★ H2's estate cut (HCUT): the estate's own tests run in the suite with `estate`,
/// which no default or downstream build carries, and the off halves without it.
#[test]
fn the_estate_code_is_tested_with_and_without_its_feature() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
let lib = step("estate:lib");
assert!(
lib.windows(2).any(|w| w == ["--features", "estate"])
&& lib.iter().any(|a| a == "--lib"),
"{lib:?}"
);
for m in [
"grow::",
"twin_tls::",
"admin_view::",
"cert_health::",
"recharge_lane::",
] {
assert!(lib.iter().any(|a| a == m), "estate:lib runs `{m}`: {lib:?}");
}
let twin = step("estate:twin");
assert!(
twin.windows(2).any(|w| w == ["--features", "estate"]),
"{twin:?}"
);
let manifest =
std::fs::read_to_string(crate::workspace_root().join("server/lib/Cargo.toml"))
.expect("server-lib manifest");
for t in ESTATE_TESTS {
assert!(
twin.windows(2).any(|w| w[0] == "--test" && w[1] == *t),
"estate:twin runs `{t}`: {twin:?}"
);
assert!(
manifest.contains(&format!("name = \"{t}\"\nrequired-features = [\"estate\"]")),
"`{t}` requires `estate` in server/lib/Cargo.toml"
);
}
let decl = step("estate:declaration");
for t in ESTATE_DECLARATION_TESTS {
assert!(
decl.windows(2).any(|w| w[0] == "--test" && w[1] == *t),
"estate:declaration runs `{t}`: {decl:?}"
);
let at = manifest
.find(&format!("name = \"{t}\""))
.unwrap_or_else(|| panic!("no [[test]] {t}"));
let req = manifest[at..]
.lines()
.find(|l| l.starts_with("required-features"))
.unwrap_or_default();
assert!(req.contains("\"estate\""), "`{t}` requires `estate`: {req}");
}
let off = step("estate:off");
assert!(
!off.iter().any(|a| a == "estate" || a.contains("estate,")),
"the off halves run without the estate: {off:?}"
);
for m in ["plane_off", "mtls_off", "disks_off"] {
assert!(off.iter().any(|a| a == m), "estate:off runs `{m}`: {off:?}");
}
}
/// ★ H6: the end-to-end gate is compiled on every push with the features `cargo xtask e2e`
/// builds it with, and the Go pull's tests run.
#[test]
fn the_e2e_gate_is_compiled_on_every_push_and_the_go_pull_is_tested() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
let e2e = step("downstream:e2e");
assert!(
e2e.windows(2)
.any(|w| w[0] == "--features" && w[1] == crate::e2e::GATE_FEATURES),
"the verb's features: {e2e:?}"
);
assert!(
e2e.windows(2)
.any(|w| w == ["--test", crate::e2e::GATE_TEST]),
"{e2e:?}"
);
let go = step("trust:go-pull");
assert!(
go.windows(2)
.any(|w| w == ["--test", "pull_through_npm_maven_crates"])
&& go.iter().any(|a| a == "go_"),
"{go:?}"
);
let t = std::fs::read_to_string(
crate::workspace_root().join("server/lib/tests/pull_through_npm_maven_crates.rs"),
)
.expect("the test");
assert!(t.contains("fn a_go_module_is_pulled_from_a_goproxy_held_for_a_person_and_served_from_the_sealed_store()"));
}
/// ★ A28 M14: the page's mount tests run with `front`, which no default build carries.
#[test]
fn the_thin_client_is_tested_against_a_real_holger_on_every_push() {
let steps = plan_from_rows(&rows());
let got: Vec<String> = labels(&steps)
.into_iter()
.filter(|l| l.starts_with("cli:"))
.collect();
assert_eq!(
got,
[
"cli:unit",
"cli:parity",
"cli:thin",
"cli:server",
"cli:build",
"cli:front"
]
);
let repo = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap();
for (name, args) in CLI_STEPS {
let dir = if args.contains(&"holger-estate-front/Cargo.toml") {
"holger-estate-front/tests"
} else {
"holger-cli/tests"
};
if let Some(i) = args.iter().position(|a| *a == "--test") {
assert!(
repo.join(dir).join(format!("{}.rs", args[i + 1])).is_file(),
"cli:{name} names a test that exists: {}",
args[i + 1]
);
}
}
}
#[test]
fn the_front_mount_is_tested_with_its_feature() {
let steps = plan_from_rows(&rows());
let step = steps
.iter()
.find(|s| s.label == "front:mount")
.unwrap_or_else(|| panic!("no front:mount: {:?}", labels(&steps)));
assert_eq!(
&step.args[..5],
["test", "-p", "holger-server-lib", "--features", "front"]
);
let lib =
std::fs::read_to_string(crate::workspace_root().join("server/lib/src/exposed/http.rs"))
.expect("http.rs");
for name in [
"the_front_door_is_reached_by_head_and_by_a_write",
"the_mount_names_every_path_the_door_owns",
] {
assert!(
step.args.iter().any(|a| a == name),
"{name} is in the step: {:?}",
step.args
);
assert!(
lib.contains(&format!("fn {name}()")),
"{name} is still a test in exposed/http.rs"
);
}
let t = std::fs::read_to_string(
crate::workspace_root().join("server/lib/tests/the_default_server_serves_no_page.rs"),
)
.expect("the test");
assert!(t.contains("fn the_http_door_serves_the_page_only_where_front_is_built()"));
}
#[test]
fn the_estate_fronts_suite_runs_both_ways() {
let steps = plan_from_rows(&rows());
let front = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
assert_eq!(
front("front:default"),
[
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--no-fail-fast"
]
);
assert_eq!(
front("front:metered"),
[
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--no-fail-fast",
"--features",
"metered"
]
);
}
/// ★ The front's `open_hub` runs on a REAL TUN where the runner can open one (required
/// there, by its environment), and may skip by name where it cannot (lane HOLGER-WG).
#[test]
fn the_fronts_real_tun_test_is_required_where_the_runner_can_open_the_node() {
let steps = plan_from_rows(&rows());
let step = steps
.iter()
.find(|s| s.label == "front:wg-hub")
.unwrap_or_else(|| panic!("no front:wg-hub: {:?}", labels(&steps)));
assert_eq!(
step.args,
[
"test",
"--manifest-path",
"holger-estate-front/Cargo.toml",
"--lib",
WG_HUB_TEST,
"--",
"--nocapture"
]
);
assert_eq!(
step.env.is_empty(),
!tun_required(),
"required exactly when the runner exported {WG_TUN_REQUIRED_ENV}: {:?}",
step.env
);
assert_eq!(
wg_hub_step(true).env,
[(WG_TUN_REQUIRED_ENV.to_string(), "1".to_string())]
);
assert!(wg_hub_step(false).env.is_empty());
assert_eq!(
wg_hub_step(true).args,
wg_hub_step(false).args,
"the same test either way; only the requirement differs"
);
let src = std::fs::read_to_string(
crate::workspace_root().join("holger-estate-front/src/wg_only.rs"),
)
.expect("wg_only.rs");
assert!(
src.contains(&format!("fn {}(", WG_HUB_TEST.rsplit("::").next().unwrap())),
"the test exists by that name"
);
assert!(
src.contains(&format!("\"{WG_TUN_REQUIRED_ENV}\"")),
"the switch is the front's"
);
}
#[test]
fn the_sign_gated_tests_are_found_in_the_metadata_and_run_with_their_features() {
let meta = serde_json::json!({ "packages": [
{ "name": "holger-server-lib", "targets": [
{ "name": "plain", "kind": ["test"] },
{ "name": "b_signed", "kind": ["test"], "required-features": ["supply-chain", "sign"] },
{ "name": "a_signed", "kind": ["test"], "required-features": ["sign"] },
{ "name": "metered_only", "kind": ["test"], "required-features": ["metered"] },
]},
{ "name": "other", "targets": [ { "name": "x", "kind": ["test"], "required-features": ["sign"] } ] },
]});
let steps = sign_steps(&meta);
assert_eq!(steps.len(), 1, "{steps:?}");
assert_eq!(steps[0].label, "sign:holger-server-lib");
assert_eq!(
steps[0].args,
[
"test",
"-p",
"holger-server-lib",
"--features",
"sign,supply-chain",
"--no-fail-fast",
"--test",
"a_signed",
"--test",
"b_signed"
]
);
}
#[test]
fn the_real_manifest_has_the_three_signed_evidence_tests() {
let root = crate::workspace_root();
let out = Command::new(std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into()))
.args([
"metadata",
"--no-deps",
"--format-version",
"1",
"--offline",
])
.current_dir(&root)
.output()
.expect("cargo metadata runs");
assert!(
out.status.success(),
"{}",
String::from_utf8_lossy(&out.stderr)
);
let meta: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
let steps = sign_steps(&meta);
let all = steps
.iter()
.flat_map(|s| s.args.iter().cloned())
.collect::<Vec<_>>()
.join(" ");
for t in [
"the_evidence_rpc_returns_signed_records",
"the_license_scanner_signs_its_evidence",
"the_scanner_framework_records_signed_evidence",
] {
assert!(all.contains(t), "{t} is not in the sign steps: {all}");
}
}
#[test]
fn the_trust_depth_arms_run() {
let steps = plan_from_rows(&rows());
let apk = steps
.iter()
.find(|s| s.label == "trust:apk-provenance")
.unwrap_or_else(|| panic!("no apk arm: {:?}", labels(&steps)));
assert_eq!(&apk.args[..3], ["test", "-p", "holger-provenance"]);
assert!(
steps.iter().any(|s| s.label == "trust:apk-intake"),
"{:?}",
labels(&steps)
);
}
/// T9b: the OpenPGP verifier is tested both ways, built (`pgp`) and not built.
#[test]
fn the_pgp_feature_is_tested_built_and_not_built() {
let steps = plan_from_rows(&rows());
let step = |l: &str| {
steps
.iter()
.find(|s| s.label == l)
.unwrap_or_else(|| panic!("no {l}: {:?}", labels(&steps)))
.args
.clone()
};
let on = step("trust:maven-pgp");
assert_eq!(
&on[..5],
["test", "-p", "holger-provenance", "--features", "pgp"]
);
assert!(
on.windows(2).any(|w| w == ["--test", "maven_pgp"]),
"{on:?}"
);
let off = step("trust:pgp-not-built");
assert!(
!off.iter()
.any(|a| a.contains("pgp") && a.starts_with("--features"))
&& !off.contains(&"--features".to_string()),
"{off:?}"
);
assert!(
off.windows(2).any(|w| w == ["--test", "pgp_build_feature"]),
"{off:?}"
);
let intake = step("trust:pgp-intake-not-built");
assert!(
intake.contains(&"--no-default-features".to_string())
&& !intake
.iter()
.any(|a| a.contains("online") || a.contains("maven-pgp")),
"{intake:?}"
);
let intake_on = step("trust:maven-pgp-intake");
assert!(
intake_on
.iter()
.any(|a| a.split(',').any(|f| f == "maven-pgp")),
"{intake_on:?}"
);
assert!(
intake_on
.windows(2)
.any(|w| w == ["--test", "pull_through_npm_maven_crates"]),
"{intake_on:?}"
);
}
#[test]
fn the_apk_pull_through_runs_in_the_suite() {
// Lane T8: the APK pull-through's tests (real Wolfi bytes behind a fake upstream)
// need `jobs,online`; no other step turns them on. `pull-apk` carries Holger's own
// APK re-signing key (H3 on H2: no longer `jobs`).
let steps = plan_from_rows(&rows());
let s = steps
.iter()
.find(|s| s.label == "trust:apk-pull")
.unwrap_or_else(|| panic!("no trust:apk-pull: {:?}", labels(&steps)));
assert_eq!(&s.args[..3], ["test", "-p", "holger-server-lib"]);
assert!(
s.args
.windows(2)
.any(|w| w == ["--features", "jobs,online,supply-chain,pull-apk"]),
"{:?}",
s.args
);
assert!(
s.args
.windows(2)
.any(|w| w == ["--test", "pull_through_apk"]),
"{:?}",
s.args
);
// The real `apk add` needs podman and the network: it is the demo's row, not the suite's.
assert!(
!s.args.iter().any(|a| a.contains("ignored")),
"{:?}",
s.args
);
}
#[test]
fn the_trust_depth_tests_run_in_the_suite() {
let steps = plan_from_rows(&rows());
let s = steps
.iter()
.find(|s| s.label == "trust:secrets")
.unwrap_or_else(|| panic!("no trust:secrets: {:?}", labels(&steps)));
assert_eq!(&s.args[..3], ["test", "-p", "holger-server-lib"]);
assert!(
s.args
.windows(2)
.any(|w| w[0] == "--test" && w[1] == "tier1_sources_steps_rules"),
"{:?}",
s.args
);
assert_eq!(
s.args.last().map(String::as_str),
Some("secret"),
"the secrets tests by name"
);
}
#[test]
fn the_board_test_runs_with_admission_declared_and_the_manifest_declares_it() {
let step = board_step();
assert_eq!(step.label, "board:admission");
assert_eq!(
step.args,
[
"test",
"-p",
"holger-server-lib",
"--features",
"admission",
"--no-fail-fast",
"--test",
BOARD_TEST
]
);
let root = crate::workspace_root();
assert!(root
.join("server/lib/tests")
.join(format!("{BOARD_TEST}.rs"))
.is_file());
let manifest = std::fs::read_to_string(root.join("server/lib/Cargo.toml")).unwrap();
let at = manifest
.find(&format!("name = \"{BOARD_TEST}\""))
.expect("the board test is a declared [[test]]");
let rest = &manifest[at..];
let req = rest.lines().nth(1).unwrap_or_default();
assert!(
req.starts_with("required-features") && req.contains(&format!("\"{BOARD_FEATURE}\"")),
"the board test declares admission: {req}"
);
}
#[test]
fn the_list_is_not_empty_and_labels_are_unique() {
let steps = plan_from_rows(&rows());
let mut l = labels(&steps);
let n = l.len();
l.sort();
l.dedup();
assert_eq!(l.len(), n, "labels are unique");
assert!(n >= 11, "{n} steps");
}
}