#![allow(clippy::print_stderr, clippy::print_stdout)]
use std::path::Path;
use std::process::Command;
#[derive(clap::Args)]
pub struct TestArgs {
#[arg(short, long)]
package: Option<String>,
#[arg(value_name = "TESTNAME")]
test_filter: Option<String>,
#[arg(last = true)]
test_args: Vec<String>,
#[arg(long)]
release: bool,
#[arg(long)]
ignored: bool,
#[arg(long)]
only_ignored: bool,
#[arg(long)]
quiet: bool,
#[arg(short, long)]
verbose: bool,
#[arg(long, value_delimiter = ',')]
features: Vec<String>,
}
pub fn execute(args: &TestArgs) -> Result<(), String> {
if !Path::new("Cargo.toml").exists() {
return Err("Cargo.toml not found. Are you in a Rust project directory?".to_string());
}
if args.verbose {
eprintln!("Running tests...");
}
let mut cmd = Command::new("cargo");
cmd.arg("test");
if let Some(ref package) = args.package {
cmd.arg("-p").arg(package);
}
if args.release {
cmd.arg("--release");
}
if args.verbose {
cmd.arg("--verbose");
}
if args.quiet {
cmd.arg("--quiet");
}
if !args.features.is_empty() {
cmd.arg("--features").arg(args.features.join(","));
}
if let Some(ref filter) = args.test_filter {
cmd.arg(filter);
}
if !args.test_args.is_empty() || args.ignored || args.only_ignored {
cmd.arg("--");
if args.only_ignored {
cmd.arg("--ignored");
} else if args.ignored {
cmd.arg("--include-ignored");
}
cmd.args(&args.test_args);
}
if args.verbose {
let mut command_str = String::from("cargo test");
if let Some(ref package) = args.package {
command_str.push_str(&format!(" -p {}", package));
}
if args.release {
command_str.push_str(" --release");
}
if !args.features.is_empty() {
command_str.push_str(&format!(" --features {}", args.features.join(",")));
}
if let Some(ref filter) = args.test_filter {
command_str.push_str(&format!(" {}", filter));
}
eprintln!("Executing: {}", command_str);
}
let status = cmd
.status()
.map_err(|e| format!("Failed to execute cargo: {}", e))?;
if !status.success() {
return Err("Tests failed".to_string());
}
Ok(())
}