use colored::Colorize;
use super::UseCase;
use crate::CommonOpts;
use crate::common::LogDiffOptions;
use crate::common::RunEnvironment;
use crate::common::TestArtifacts;
use crate::common::Verify;
use crate::use_case::run_hermit::output_stderr;
use crate::use_case::run_hermit::output_stdout;
fn compare_results<T: UseCase>(
use_case: &T,
common_args: &CommonOpts,
left: &RunEnvironment,
right: &RunEnvironment,
) -> anyhow::Result<bool> {
let options = use_case.options();
let verify = Verify::new(common_args.hermit_bin.as_path());
let mut result = true;
if options.verify_stdout {
result &= verify.verify_stdout(left, right)?;
}
if options.verify_stderr {
result &= verify.verify_stderr(left, right)?;
}
if options.should_log_diff() {
result &= verify.verify_logs(
left,
right,
LogDiffOptions {
ignore_lines: options.ignore_lines,
skip_commits: !options.verify_commits,
skip_detlog_others: !options.verify_detlog_others,
skip_detlog_syscalls: !options.verify_detlog_syscalls,
skip_detlog_syscall_results: !options.verify_detlog_syscall_results,
syscall_history: 5,
},
)?;
}
if options.verify_exit_statuses {
result &= verify.verify_exit_statuses(left, right)?;
}
if options.verify_desync {
result &= verify.verify_desync(right)?;
}
if options.verify_schedules {
result &= verify.verify_schedules(left, right)?;
}
Ok(result)
}
pub fn run_use_case<T: UseCase>(use_case: T, common_args: &CommonOpts) -> anyhow::Result<bool> {
let temp_env = use_case.build_temp_env(common_args).build()?;
let mut iter = temp_env.runs().iter();
let mut current = iter.next().expect("use case must contain at least one run");
let mut counter = 0;
let options = use_case.options();
println!("{}", format!(":: Run #{}...", counter + 1).yellow().bold());
use_case.exec_first_run(common_args, &temp_env, current)?;
let mut result = true;
loop {
counter += 1;
if let Some(next) = iter.next() {
println!("{}", format!(":: Run #{}...", counter + 1).yellow().bold());
use_case.exec_next_run(common_args, counter + 1, &temp_env, current, next)?;
if !compare_results(&use_case, common_args, current, next)? {
result = false;
break;
} else {
if counter == 1 {
if options.output_stdout {
output_stdout(current)?;
}
if options.output_stderr {
output_stderr(current)?;
}
}
}
current = next;
} else {
break;
}
}
if !common_args.ignore_test_result_artifacts_dir
&& let Some(path) = &common_args.test_result_artifact_dir
{
println!(
"{}",
format!(":: Copy artifacts to {}", path.display())
.yellow()
.bold()
);
let test_artifacts = TestArtifacts::new(path.to_owned());
test_artifacts.copy_run_results(&temp_env)?;
}
Ok(result)
}