test.rs

 1use std::{
 2    panic::{self, RefUnwindSafe},
 3    rc::Rc,
 4    sync::{
 5        atomic::{AtomicU64, Ordering::SeqCst},
 6        Arc,
 7    },
 8};
 9
10use crate::{executor, platform, FontCache, MutableAppContext, Platform, TestAppContext};
11
12#[cfg(test)]
13#[ctor::ctor]
14fn init_logger() {
15    env_logger::builder()
16        .filter_level(log::LevelFilter::Info)
17        .init();
18}
19
20pub fn run_sync_test(
21    mut num_iterations: u64,
22    mut starting_seed: u64,
23    max_retries: usize,
24    test_fn: &mut (dyn RefUnwindSafe + Fn(&mut MutableAppContext, u64)),
25) {
26    let is_randomized = num_iterations > 1;
27    if is_randomized {
28        if let Ok(value) = std::env::var("SEED") {
29            starting_seed = value.parse().expect("invalid SEED variable");
30        }
31        if let Ok(value) = std::env::var("ITERATIONS") {
32            num_iterations = value.parse().expect("invalid ITERATIONS variable");
33        }
34    }
35
36    let atomic_seed = AtomicU64::new(starting_seed as u64);
37    let mut retries = 0;
38
39    loop {
40        let result = panic::catch_unwind(|| {
41            let foreground_platform = Rc::new(platform::test::foreground_platform());
42            let platform = Arc::new(platform::test::platform());
43            let font_system = platform.fonts();
44            let font_cache = Arc::new(FontCache::new(font_system));
45
46            loop {
47                let seed = atomic_seed.load(SeqCst);
48                if seed >= starting_seed + num_iterations {
49                    break;
50                }
51
52                if is_randomized {
53                    dbg!(seed);
54                }
55
56                let (foreground, background) = executor::deterministic(seed);
57                let mut cx = TestAppContext::new(
58                    foreground_platform.clone(),
59                    platform.clone(),
60                    foreground.clone(),
61                    background.clone(),
62                    font_cache.clone(),
63                    0,
64                );
65                cx.update(|cx| test_fn(cx, seed));
66
67                atomic_seed.fetch_add(1, SeqCst);
68            }
69        });
70
71        match result {
72            Ok(_) => {
73                break;
74            }
75            Err(error) => {
76                if retries < max_retries {
77                    retries += 1;
78                    println!("retrying: attempt {}", retries);
79                } else {
80                    if is_randomized {
81                        eprintln!("failing seed: {}", atomic_seed.load(SeqCst));
82                    }
83                    panic::resume_unwind(error);
84                }
85            }
86        }
87    }
88}