diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-15 02:26:21 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-15 02:37:21 +0800 |
| commit | e174bf5983906b0fd5c23041df42287a5f200cfb (patch) | |
| tree | 0278d9c5cda7f08c9bad5394613be30b4711f7eb | |
| parent | 48cfd06560db6155536f45f3a0209289779a134e (diff) | |
refactor: parallelize example builds in test-examples tool
Split test-examples into two phases: build all examples in parallel
first, then run tests serially against pre-built binaries. Abort on any
build failure instead of skipping tests for that example.
| -rw-r--r-- | .run/src/bin/test-examples.rs | 44 | ||||
| -rw-r--r-- | docs/dev/pages/abouts/ci.md | 7 |
2 files changed, 33 insertions, 18 deletions
diff --git a/.run/src/bin/test-examples.rs b/.run/src/bin/test-examples.rs index 55976ef..617a745 100644 --- a/.run/src/bin/test-examples.rs +++ b/.run/src/bin/test-examples.rs @@ -3,7 +3,7 @@ use std::path::Path; use colored::Colorize; use indicatif::ProgressBar; use serde::Deserialize; -use tools::{eprintln_cargo_style, println_cargo_style}; +use tools::{eprintln_cargo_style, println_cargo_style, run_parallel}; /// An example's `test.toml` (`[[runs]]` entries). #[derive(Deserialize)] @@ -31,7 +31,13 @@ fn main() { let configs = load_all_test_configs(); - // Count total test cases upfront + // Phase 1: build all examples in parallel. + if let Err(code) = build_all_examples(&configs) { + // `run_parallel` already printed every failed build above. + std::process::exit(code); + } + + // Phase 2: run the tests serially against the pre-built binaries. let total: usize = configs.iter().map(|(_, cases)| cases.len()).sum(); let bar = ProgressBar::new(total as u64); bar.set_style( @@ -97,18 +103,31 @@ fn load_all_test_configs() -> Vec<(String, Vec<TestCase>)> { configs } -/// Run all example test groups, return number passed +/// Phase 1: build every example that has a `test.toml` in parallel. +/// +/// Build tasks are spawned in parallel (like `ci.rs`'s `build_all`); on any +/// build failure the whole run aborts with the first failure's exit code. +fn build_all_examples(configs: &[(String, Vec<TestCase>)]) -> Result<(), i32> { + let tasks: Vec<(String, String, String)> = configs + .iter() + .map(|(name, _)| { + ( + format!("Build: {name}"), + name.clone(), + format!("cargo build --manifest-path examples/{name}/Cargo.toml --color always"), + ) + }) + .collect(); + run_parallel("Building", tasks) +} + +/// Phase 2: run all example test groups serially, return number passed fn run_all_tests(configs: &[(String, Vec<TestCase>)], bar: &ProgressBar) -> usize { let mut passed = 0; for (example_name, test_cases) in configs { bar.set_message(example_name.clone()); - if !build_example(example_name) { - bar.inc(test_cases.len() as u64); - continue; - } - for test_case in test_cases { if run_single_test(example_name, test_case, bar) { passed += 1; @@ -120,15 +139,6 @@ fn run_all_tests(configs: &[(String, Vec<TestCase>)], bar: &ProgressBar) -> usiz passed } -/// Build the example binary, return true on success -fn build_example(example_name: &str) -> bool { - let manifest = format!("examples/{example_name}/Cargo.toml"); - tools::run_cmd_capture(format!( - "cargo build --manifest-path {manifest} --color always", - )) - .is_ok() -} - /// Run a single test case, return true on pass fn run_single_test(example_name: &str, test_case: &TestCase, bar: &ProgressBar) -> bool { let binary_path = format!(".temp/target/debug/{}", get_binary_name(example_name)); diff --git a/docs/dev/pages/abouts/ci.md b/docs/dev/pages/abouts/ci.md index 659a5fc..9f638d7 100644 --- a/docs/dev/pages/abouts/ci.md +++ b/docs/dev/pages/abouts/ci.md @@ -51,7 +51,12 @@ Finally, it runs `cargo fmt` to unify code formatting. Because the refresh tools ### Examples in detail -`--check-examples` runs the `test-examples` tool, which scans `examples/*/test.toml`. Each file contains `[[runs]]` entries declaring the CLI arguments (`input`) and the expected `exit-code` / `result`. The tool builds every example that has a `test.toml` and executes each run against the built binary, so an example that changes its behavior only needs its own `test.toml` updated. +`--check-examples` runs the `test-examples` tool in two phases: + +1. **Build** — every example that has a `test.toml` is built in parallel (one `cargo build` task per example, reusing the shared `.temp/target` cache). +2. **Test** — each `[[runs]]` entry in `examples/*/test.toml` is executed serially against the pre-built binary, asserting the CLI arguments (`input`) and the expected `exit-code` / `result`. + +An example that changes its behavior only needs its own `test.toml` updated. ### Combining steps |
