use clap::Args;
use std::time::Instant;
use crate::{bench::runner::Bench, output::output::OutputKind, print_template, print_text, utils};
#[derive(Args)]
pub struct BenchArgs {
#[arg(long, short = 'a')]
action: Option<String>,
#[arg(long, short = 'v')]
verbose: bool,
}
pub async fn execute(args: BenchArgs) {
let bench = match Bench::load() {
Ok(b) => b,
Err(e) => {
print_text!(OutputKind::Error, "{}", e);
std::process::exit(1);
}
};
let actions: Vec<_> = if let Some(ref filter) = args.action {
bench
.config
.benchmarks
.iter()
.filter(|(name, _)| *name == filter)
.collect()
} else {
bench.config.benchmarks.iter().collect()
};
if actions.is_empty() {
print_text!(OutputKind::Info, "No benchmark found");
return;
}
let mut passed = 0;
let mut failed = 0;
let mut index = 0;
let total: usize = actions.iter().map(|(_, cases)| cases.len()).sum();
let start_time = Instant::now();
print_template!(
OutputKind::Info,
"Start execute task benchmarks ({total} cases)",
"total" => total
);
for (action, cases) in &actions {
print_template!(
OutputKind::Info,
"Start {action}...",
"action" => action
);
for case in cases.iter() {
index += 1;
let start = Instant::now();
match bench.run(action, case).await {
Ok(output) => {
passed += 1;
let duration = start.elapsed();
let args_str = case
.args
.iter()
.map(|(_, v)| v.split_whitespace().collect::<Vec<_>>().join(" "))
.collect::<Vec<_>>()
.join(", ");
let args_display = if args_str.is_empty() {
"(no args)".to_string()
} else if args_str.chars().count() > 100 {
let mut take_chars = args_str.chars().take(100).collect::<String>();
take_chars.push_str("...");
take_chars
} else {
args_str
};
if args.verbose {
print_template!(
OutputKind::Progress,
"{percent}% ({current}/{total}) | {duration} | {action} {args_display}",
"percent" => format!("{:.0}", (index as f32 / total as f32) * 100.0),
"current" => index.to_string(),
"total" => total.to_string(),
"duration" => utils::format::format_duration(duration),
"action" => action,
"args_display" => args_display
);
if output.is_empty() {
print_text!(OutputKind::Info, "No matches found.");
} else {
print_template!(
OutputKind::Success,
"{output}",
"output" => output
);
}
} else {
print_template!(
OutputKind::Progress,
"{percent}% ({current}/{total}) | {duration} | {args_display}",
"percent" => format!("{:.0}", (index as f32 / total as f32) * 100.0),
"current" => index.to_string(),
"total" => total.to_string(),
"duration" => utils::format::format_duration(duration),
"args_display" => args_display
);
}
}
Err(e) => {
failed += 1;
let duration = start.elapsed();
print_template!(
OutputKind::Progress,
"{current}/{total} | {duration} | FAIL: {error}",
"current" => index.to_string(),
"total" => total.to_string(),
"duration" => utils::format::format_duration(duration),
"error" => e.to_string()
);
}
}
}
}
print_template!(
OutputKind::Info,
"{passed} passed, {failed} failed in {duration}",
"passed" => passed.to_string(),
"failed" => failed.to_string(),
"duration" => utils::format::format_duration(start_time.elapsed())
);
}