use crate::executor::{CatchUnwind, CraneliftJIT, FnReport, JITBencher, TestReport};
use edlc_core::prelude::edl_type::EdlTypeId;
pub(crate) struct UnitTest {
pub(crate) id: EdlTypeId,
pub(crate) stub: extern "C" fn(),
pub(crate) setup: Vec<extern "C" fn()>,
pub(crate) teardown: Vec<extern "C" fn()>,
}
pub struct TestExec {
pub(crate) stubs: Vec<UnitTest>,
}
impl TestExec {
pub fn run<R: 'static>(&self, compiler: &CraneliftJIT<R>) -> Result<TestReport, anyhow::Error> {
let mut report = TestReport::default();
'outer: for UnitTest { id, stub, setup, teardown } in self.stubs.iter() {
for setup_fn in setup.into_iter() {
if let Err(err) = compiler.catch_unwind(*setup_fn, ()) {
report.insert(*id, FnReport::SetupErr(err));
continue 'outer;
}
}
match compiler.catch_unwind(*stub, ()) {
Ok(()) => (),
Err(err) => {
report.insert(*id, FnReport::Err(err));
continue 'outer;
},
}
for teardown_fn in teardown.into_iter() {
if let Err(err) = compiler.catch_unwind(*teardown_fn, ()) {
report.insert(*id, FnReport::TeardownError(err));
continue 'outer;
}
}
report.insert(*id, FnReport::Ok);
}
Ok(report)
}
pub fn bench<R: 'static>(
&self,
bencher: &mut impl JITBencher<R>,
compiler: &CraneliftJIT<R>,
) -> Result<TestReport, anyhow::Error> {
let mut report = TestReport::default();
for UnitTest { id, stub, setup, teardown } in self.stubs.iter() {
let full_name = compiler.compiler.phase.types
.get_fn_qualifier(*id)?
.as_ref()
.unwrap();
let n = bencher.start_bench(full_name, compiler);
let mut ok = true;
'outer: for _ in 0..n {
for setup_fn in setup.iter() {
if let Err(err) = compiler.catch_unwind(*setup_fn, ()) {
report.insert(*id, FnReport::SetupErr(err));
ok = false;
break 'outer;
}
}
bencher.start_round(compiler);
let res = compiler.catch_unwind(*stub, ());
bencher.stop_round(compiler);
if let Err(err) = res {
report.insert(*id, FnReport::Err(err));
ok = false;
break 'outer;
}
for teardown_fn in teardown.iter() {
if let Err(err) = compiler.catch_unwind(*teardown_fn, ()) {
report.insert(*id, FnReport::TeardownError(err));
ok = false;
break 'outer;
}
}
}
if ok {
report.insert(*id, FnReport::Ok);
}
bencher.end_bench(compiler);
}
Ok(report)
}
}