use rand::rngs::StdRng;
use rand::SeedableRng;
use std::panic::{catch_unwind, AssertUnwindSafe};
use typr_core::components::context::Context;
use typr_core::processes::parsing::parse_from_string;
use typr_core::processes::type_checking::type_checker::TypeChecker;
use typr_core::utils::program_gen::{self, Coverage};
const N_CASES: u64 = 256;
const MAX_DEPTH: u32 = 3;
#[test]
fn generated_programs_typecheck_and_transpile() {
let mut rejections: Vec<(u64, String, String)> = Vec::new();
let mut cov = Coverage::new();
let base_context = Context::default();
for seed in 0..N_CASES {
let mut rng = StdRng::seed_from_u64(seed);
let prog = program_gen::gen_program(&mut rng, MAX_DEPTH, &mut cov);
let src = prog.to_source();
let outcome = catch_unwind(AssertUnwindSafe(|| {
let ast = parse_from_string(&src, "generated");
let tc = TypeChecker::new(base_context.clone()).typing_no_panic(&ast);
if tc.has_errors() {
return Err(format!("{:?}", tc.get_errors()));
}
let _r = tc.transpile();
Ok(())
}));
match outcome {
Ok(Ok(())) => {}
Ok(Err(msg)) => rejections.push((seed, src, msg)),
Err(panic) => {
let msg = if let Some(s) = panic.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = panic.downcast_ref::<String>() {
s.clone()
} else {
"unknown panic payload".to_string()
};
rejections.push((seed, src, format!("PANIC: {msg}")));
}
}
}
eprintln!("{}", cov.summary());
if !rejections.is_empty() {
let mut dump = format!("{} rejected program(s) out of {N_CASES}:\n", rejections.len());
for (seed, src, msg) in &rejections {
dump.push_str(&format!("\n--- seed {seed} ---\n{src}\n{msg}\n"));
}
panic!("{dump}");
}
}