use std::process::{Command, ExitCode}; use std::time::Instant; struct TestStep { label: &'static str, args: &'static [&'static str], } const BASIC_TESTS: &[TestStep] = &[ TestStep { label: "root crate", args: &["test"], }, TestStep { label: "datastream", args: &["test", "-p", "datastream"], }, TestStep { label: "distribution", args: &["test", "-p", "distribution"], }, TestStep { label: "iroh-driver", args: &["test", "-p", "iroh-driver"], }, TestStep { label: "mvp-system", args: &["test", "-p", "mvp-system"], }, TestStep { label: "swactor-process", args: &["test", "-p", "swactor-process"], }, TestStep { label: "swactor-transport", args: &["test", "-p", "swactor-transport"], }, TestStep { label: "dashboard", args: &["test", "-p", "dashboard"], }, TestStep { label: "swactor-vastai", args: &["test", "-p", "swactor-vastai"], }, TestStep { label: "xtask", args: &["test", "-p", "xtask"], }, ]; fn cargo_bin() -> String { option_env!("CARGO") .map(str::to_string) .unwrap_or_else(|| "cargo".to_string()) } fn print_usage() { println!( "\ USAGE: cargo xtask test COMMANDS: test Run all basic non-binding tests. This includes the root crate with\n `cargo test` plus each non-binding workspace package with `cargo test -p`.\n Feature-gated E2E/bin tests are intentionally excluded." ); } fn run_step(step: &TestStep) -> bool { println!("\n=== {} ===", step.label); println!(" cargo {}", step.args.join(" ")); println!(); match Command::new(cargo_bin()).args(step.args).status() { Ok(status) => status.success(), Err(error) => { eprintln!("Failed to execute cargo: {error}"); false } } } fn run_tests() -> ExitCode { let start = Instant::now(); for (index, step) in BASIC_TESTS.iter().enumerate() { if !run_step(step) { eprintln!( "\n--- FAILED after {:.1}s ({index} passed, 1 failed) ---", start.elapsed().as_secs_f64() ); return ExitCode::from(1); } } println!( "\n--- All {} step(s) passed in {:.1}s ---", BASIC_TESTS.len(), start.elapsed().as_secs_f64() ); ExitCode::SUCCESS } fn main() -> ExitCode { let mut args = std::env::args().skip(1); match (args.next().as_deref(), args.next()) { (Some("test"), None) => run_tests(), (Some("help" | "--help" | "-h"), None) | (None, None) => { print_usage(); ExitCode::SUCCESS } _ => { print_usage(); ExitCode::from(1) } } }