mod test_interface;
use clap::Parser;
use cli::Cli;
use deflake::Deflake;
use std::{fs, thread::available_parallelism, time::Instant};
use test_interface::{TestCollector, TestMeta, TestResult, TestResults, TestRunner};
mod ast;
mod cli;
mod cov;
mod deflake;
mod git;
static VERSION: &str = "1.0.0";
fn exit(args: &Cli, results: &TestResults, meta: TestMeta) -> ! {
if let Some(output_file) = &args.output {
let s = results.serialise(meta);
fs::write(output_file, s).expect("ERR: Could not write results to file");
}
let exit_code = match results.has_failure() {
true => 1,
false => 0,
};
std::process::exit(exit_code);
}
fn main() {
let args = Cli::parse();
TestRunner::setup();
let now = Instant::now();
println!("Building and collecting tests...");
let tests = TestCollector::get_tests(&args);
println!("Done!");
TestRunner::cleanup();
if args.build_only {
println!("There are {} tests", tests.len());
std::process::exit(0);
}
let batch_size = match args.batch_size {
Some(s) => s.into(),
None => match available_parallelism() {
Ok(i) => i.into(),
Err(_) => 4,
},
};
let mut results = TestRunner::exec_batch(&tests, batch_size, args.timeout);
let test_exec_time = now.elapsed().as_millis();
let mut meta = TestMeta {
deflaker_version: VERSION.to_string(),
execution_time: test_exec_time,
tests: tests.len(),
deflake_time: None,
};
if !results.has_failure() || args.no_deflake || args.no_coverage {
if args.no_deflake {
println!("NOTE: not classifying flaky tests")
}
let fails = results.failures();
if fails.len() > 0 {
println!("Failing tests:");
for (id, fail) in results.failures() {
println!(
"{} - {} {}",
id,
fail.0.stdout_path(),
if fail.1 == TestResult::Timeout {
"(timeout)"
} else {
""
}
);
}
} else {
println!("No failures!");
}
exit(&args, &results, meta);
}
let failures = results.failures_no_timeout();
let flaky = Deflake::run(&args, failures);
for flake in flaky {
results.reclassify(flake, TestResult::Flaky);
}
let whole_time = now.elapsed().as_millis();
meta.deflake_time = Some(whole_time);
println!("Failing tests:");
for (id, fail) in results.failures() {
println!("{} - {}", id, fail.0.stdout_path());
}
println!("\nFlaky tests:");
for (id, flake) in results.flaky() {
println!("{} - {}", id, flake.0.stdout_path());
}
exit(&args, &results, meta);
}