xtask/tests/front_tests_run_in_ci.rs
//! ★ **`cargo xtask ci` runs gunnar-front's tests** (OX-WIRED 2026-10-28).
//!
//! gunnar-front is a DETACHED workspace (the root excludes it: it takes crates that live only
//! in sibling checkouts), so `cargo test --workspace` never reaches it, and until this file no
//! CI step did either: `tests/grpc_hole.rs` (the CLI to the main's control plane through the
//! front's 443) and every other gunnar-front test ran nowhere. `xtask ci` runs each DETACHED
//! entry by manifest path; this holds that the front is one of them, once at its default
//! features and once with every feature a front test requires, so a test gated on a feature
//! nobody turns on cannot hide either.
fn root() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("xtask has a parent")
.to_path_buf()
}
fn text(rel: &str) -> String {
std::fs::read_to_string(root().join(rel)).unwrap_or_else(|e| panic!("{rel}: {e}"))
}
/// The `DETACHED` table of `xtask/src/main.rs`, as written.
fn detached() -> String {
let main = text("xtask/src/main.rs");
let at = main
.find("const DETACHED")
.expect("xtask/src/main.rs declares DETACHED");
let end = main[at..].find("];").expect("DETACHED ends") + at;
main[at..end].to_string()
}
/// The names in a one-line `key = ["a", "b"]` of gunnar-front's Cargo.toml, every such line.
fn listed(key: &str) -> std::collections::BTreeSet<String> {
let manifest = text("crates/gunnar-front/Cargo.toml");
let mut out = std::collections::BTreeSet::new();
for line in manifest.lines().filter(|l| {
l.trim_start()
.strip_prefix(key)
.is_some_and(|r| r.trim_start().starts_with('='))
}) {
let list = line
.split_once('[')
.and_then(|(_, r)| r.split_once(']'))
.map(|(l, _)| l)
.unwrap_or_default();
out.extend(
list.split(',')
.map(|f| f.trim().trim_matches('"').to_string())
.filter(|f| !f.is_empty()),
);
}
out
}
/// Every feature a `[[test]]` of gunnar-front names in `required-features` that its default
/// features do not already turn on (a featured run keeps the defaults).
fn required_by_the_front_tests() -> std::collections::BTreeSet<String> {
let defaults = listed("default");
listed("required-features")
.into_iter()
.filter(|f| !defaults.contains(f))
.collect()
}
#[test]
fn xtask_ci_runs_the_fronts_tests_at_its_defaults() {
let table = detached();
assert!(
table.contains(r#""crates/gunnar-front/Cargo.toml", &[])"#),
"`cargo xtask ci` must run gunnar-front's tests at its default features (a DETACHED entry \
with no extra arguments):\n{table}"
);
}
#[test]
fn xtask_ci_runs_every_feature_gated_front_test() {
let table = detached();
let required = required_by_the_front_tests();
assert!(
!required.is_empty(),
"gunnar-front's Cargo.toml names required-features (metered, mcp, …)"
);
let featured: Vec<&str> = table
.split("(\"")
.filter(|e| e.contains(r#""crates/gunnar-front/Cargo.toml", &["--features""#))
.collect();
assert!(
!featured.is_empty(),
"no DETACHED entry runs gunnar-front with --features:\n{table}"
);
for f in &required {
assert!(
featured.iter().any(|e| e.split('"').any(|w| w.split(',').any(|x| x == f))),
"a gunnar-front test requires `{f}`, and no `cargo xtask ci` step turns it on:\n{table}"
);
}
}