#[macro_export]
macro_rules! unit_test_describe {
($(run_unit_test($name: path);)* ) => {{
let panic_infos: std::sync::Arc<std::sync::Mutex<Vec<String>>> = Default::default();
let c_infos = panic_infos.clone();
std::panic::set_hook(Box::new(move |info| {
println!("... {}", "failed".red());
let info_str = format!("{}", info);
c_infos.lock().unwrap().push(info_str)
}));
let count = unit_test_describe!(count $($name)*);
println!("running {} test", count);
let mut res = Result::Ok(());
$(
res = std::panic::catch_unwind(|| {
print!("test {}::{} ", module_path!(), stringify!($name));
$name();
println!("... {}", "ok".green());
}).and(res);
)*
let _ = std::panic::take_hook();
let infos = panic_infos.lock().unwrap();
let failed = infos.len();
let pass = count - failed;
let result = if res.is_err() {
"failed".red()
} else {
"ok".green()
};
println!("");
println!("test results: {}. {} passed; {} failed;\n", result, pass, failed);
if !infos.is_empty() {
println!("--------- {} failed stdout ---------", module_path!());
infos.iter().for_each(|info| println!("{}", info))
}
if let Result::Err(err) = res {
std::panic::resume_unwind(err);
}
}};
(count) => (0usize);
(count $x:tt $($xs:tt)* ) => {
1usize + unit_test_describe!(count $($xs)*)
};
}