diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-19 05:54:00 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-19 06:15:20 +0800 |
| commit | ec9edc294fd5e7e29977fc7b0e6fb953422bc0e2 (patch) | |
| tree | bbf89ef4457b8de8a8a9bca5668045d612d27572 /mingling_ci/src/markdown/test.rs | |
| parent | 06dfc27194c11e1d1033c292c759a1c5d82e780b (diff) | |
Move CI, dev tools, and configs from root-level scattered locations into
a
unified `dev/` directory structure. Update all references across build
scripts, documentation, and editor configurations.
Also consolidate editor config generation into build.rs for automated
synchronization of rust-analyzer settings across VS Code and Zed.
Diffstat (limited to 'mingling_ci/src/markdown/test.rs')
| -rw-r--r-- | mingling_ci/src/markdown/test.rs | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/mingling_ci/src/markdown/test.rs b/mingling_ci/src/markdown/test.rs deleted file mode 100644 index 8ecf18d..0000000 --- a/mingling_ci/src/markdown/test.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! Parallel execution of markdown test projects. - -use std::collections::BTreeMap; -use std::path::{Path, PathBuf}; - -use colored::Colorize; - -use crate::progress::task_progress_bar; - -use super::project::{ - MarkdownTestProject, generate_build_rs, generate_cargo_toml, generate_main_rs, -}; - -/// Temporary root for the generated test crates. -const TEMP_BASE: &str = ".temp/doc-test"; - -/// Outcome of testing one code block. -pub(crate) struct MarkdownBlockOutcome { - pub source_file: String, - pub line: usize, - pub ok: bool, - /// Failure detail; empty when `ok`. - pub output: String, -} - -/// Runs the given projects in parallel. -/// -/// Projects sharing a dependency hash share one temporary crate (written -/// serially within the group); groups run in parallel. Progress is shown on -/// stderr; failures print there too. Returns one outcome per block. -pub(crate) async fn try_test_markdown_project( - projs: Vec<MarkdownTestProject>, -) -> Vec<MarkdownBlockOutcome> { - // Group by dependency hash for crate sharing. - let mut groups: BTreeMap<String, Vec<MarkdownTestProject>> = BTreeMap::new(); - for proj in projs { - groups.entry(proj.compute_hash()).or_default().push(proj); - } - - let total: usize = groups.values().map(Vec::len).sum(); - let pb = task_progress_bar(total, "Testing"); - pb.set_message("blocks"); - - // One blocking task per group; blocks within a group are serial because - // they share the same crate directory. - let mut handles = Vec::new(); - for (hash, blocks) in groups { - let pb = pb.clone(); - handles.push(tokio::task::spawn_blocking(move || { - let crate_dir = PathBuf::from(TEMP_BASE).join(&hash); - let src_dir = crate_dir.join("src"); - let manifest_path = crate_dir.join("Cargo.toml"); - let cargo_toml = generate_cargo_toml(&blocks[0], &manifest_path); - - let mut group_outcomes = Vec::new(); - for proj in &blocks { - let label = format!("{}:{}", proj.source_file, proj.line); - pb.set_message(label.clone()); - - let main_rs = if proj.is_build_time { - generate_build_rs(proj) - } else { - generate_main_rs(proj) - }; - let (ok, err) = build_block( - &src_dir, - &manifest_path, - &cargo_toml, - &main_rs, - proj.is_build_time, - ); - pb.inc(1); - - if !ok { - // Plain stderr: `pb.println` is swallowed on non-TTY (CI). - eprintln!(" {} {label}", "failed".bold().bright_red()); - eprintln!(" {label} FAILED:\n{err}"); - } - group_outcomes.push(MarkdownBlockOutcome { - source_file: proj.source_file.clone(), - line: proj.line, - ok, - output: err, - }); - } - group_outcomes - })); - } - - let mut all_outcomes = Vec::new(); - for handle in handles { - if let Ok(group_outcomes) = handle.await { - all_outcomes.extend(group_outcomes); - } - } - - pb.finish_and_clear(); - all_outcomes -} - -/// Writes the temporary crate files and runs `cargo check`. -/// -/// When `is_build_time` is true, the content goes to `build.rs` with a stub -/// `main.rs`; otherwise it goes to `src/main.rs`. -fn build_block( - src_dir: &Path, - manifest_path: &Path, - cargo_toml: &str, - content: &str, - is_build_time: bool, -) -> (bool, String) { - if let Err(e) = std::fs::create_dir_all(src_dir) { - return (false, format!("mkdir: {e}")); - } - if let Err(e) = std::fs::write(manifest_path, cargo_toml) { - return (false, format!("write Cargo.toml: {e}")); - } - - if is_build_time { - let crate_dir = manifest_path - .parent() - .expect("manifest path has a parent directory"); - if let Err(e) = std::fs::write(crate_dir.join("build.rs"), content) { - return (false, format!("write build.rs: {e}")); - } - if let Err(e) = std::fs::write(src_dir.join("main.rs"), "fn main() {}\n") { - return (false, format!("write main.rs: {e}")); - } - } else if let Err(e) = std::fs::write(src_dir.join("main.rs"), content) { - return (false, format!("write main.rs: {e}")); - } - - let output = std::process::Command::new("cargo") - .args(["check", "--color=always", "--manifest-path"]) - .arg(manifest_path) - .output(); - match output { - Ok(output) if output.status.success() => (true, String::new()), - Ok(output) => { - let mut log = String::from_utf8_lossy(&output.stdout).into_owned(); - log.push_str(&String::from_utf8_lossy(&output.stderr)); - let lines: Vec<&str> = log.lines().collect(); - let tail = &lines[lines.len().saturating_sub(20)..]; - let exit = output - .status - .code() - .map_or_else(|| "?".to_string(), |c| c.to_string()); - (false, format!("exit code {exit}\n{}", tail.join("\n"))) - } - Err(e) => (false, format!("failed to run cargo: {e}")), - } -} |
