in tools/testinfra/runner/src/main.rs [56:143]
fn main() -> Result<()> {
// parse command line
let options = Options::from_args();
if options.ignored.len() > 0 {
eprintln!(
"Warning: Unimplemented options were ignored: {:?}\n",
options.ignored
);
}
// validate and collect tests which are not auto-excluded
let tests: Vec<Test> = buck_test::read(&options.spec)?
.into_iter()
.map(|spec| buck_test::validate(spec).unwrap())
.flatten()
.collect();
// don't run anything when just listing
if options.list {
for test in tests {
println!("{}", test.name);
}
exit(0);
}
// run tests in parallel (retries share the same thread)
let total = tests.len();
eprintln!("Running {} tests...", total);
let _ = rayon::ThreadPoolBuilder::new()
.num_threads(options.threads)
.build_global();
let mut tests: Vec<TestResult> = tests
.into_par_iter()
.map(|test| {
let test = test.run(options.retries);
if test.passed {
print!("[OK] {} ({} ms)", test.name, test.duration.as_millis());
if test.attempts > 1 {
print!(" ({} attempts needed)\n", test.attempts);
} else {
print!("\n");
}
} else {
println!("[FAIL] {} ({} ms)", test.name, test.duration.as_millis());
}
return test;
})
.collect();
// collect and print results
let mut passed = 0;
let mut errors: Vec<String> = Vec::new();
for test in tests.iter_mut() {
if test.passed {
passed += 1;
} else {
let mut message = format!(
"\nTest {} failed after {} unsuccessful attempts:\n",
test.name, test.attempts
);
for line in test.stderr.split("\n") {
let line = format!(" {}\n", line);
message.push_str(&line);
}
if test.contacts.len() > 0 {
let contacts = format!("Please report this to {:?}\n", test.contacts);
message.push_str(&contacts);
}
errors.push(message);
}
}
for error in errors {
eprintln!("{}", error);
}
let failed = total - passed;
println!(
"Out of {} tests, {} passed, {} failed",
total, passed, failed
);
// generate test report
match options.report {
None => {}
Some(path) => report(tests, path)?,
}
exit(failed as i32);
}