1use crate::TestDispatcher;
2use rand::prelude::*;
3use std::{
4 env,
5 panic::{self, RefUnwindSafe},
6};
7
8pub fn run_test(
9 mut num_iterations: u64,
10 max_retries: usize,
11 test_fn: &mut (dyn RefUnwindSafe + Fn(TestDispatcher, u64)),
12 on_fail_fn: Option<fn()>,
13 _fn_name: String, // todo!("re-enable fn_name")
14) {
15 let starting_seed = env::var("SEED")
16 .map(|seed| seed.parse().expect("invalid SEED variable"))
17 .unwrap_or(0);
18 let is_randomized = num_iterations > 1;
19 if let Ok(iterations) = env::var("ITERATIONS") {
20 num_iterations = iterations.parse().expect("invalid ITERATIONS variable");
21 }
22
23 for seed in starting_seed..starting_seed + num_iterations {
24 let mut retry = 0;
25 loop {
26 if is_randomized {
27 eprintln!("seed = {seed}");
28 }
29 let result = panic::catch_unwind(|| {
30 let dispatcher = TestDispatcher::new(StdRng::seed_from_u64(seed));
31 test_fn(dispatcher, seed);
32 });
33
34 match result {
35 Ok(_) => break,
36 Err(error) => {
37 if retry < max_retries {
38 println!("retrying: attempt {}", retry);
39 retry += 1;
40 } else {
41 if is_randomized {
42 eprintln!("failing seed: {}", seed);
43 }
44 on_fail_fn.map(|f| f());
45 panic::resume_unwind(error);
46 }
47 }
48 }
49 }
50 }
51}