fn driver_can_reproduce_mutations()

in testsuite/src/lib.rs [471:555]


    fn driver_can_reproduce_mutations() {
        use lain::rand::Rng;
        use std::sync::{Arc, RwLock};

        #[derive(Debug, Default, NewFuzzed, Mutatable, Clone, PartialEq, BinarySerialize)]
        struct S {
            value: u32,
        }

        #[derive(Default)]
        struct LocalContext {}

        #[derive(Default, Debug)]
        struct GlobalContext {
            mutated_data: Vec<S>,
            iterations: usize,
        }

        fn fuzzer_routine<R: lain::rand::Rng>(
            mutator: &mut Mutator<R>,
            _ctx: &mut LocalContext,
            global_ctx: Option<Arc<RwLock<GlobalContext>>>,
        ) -> Result<(), ()> {
            let global_ctx = global_ctx.unwrap();
            let mut global_ctx = global_ctx.write().unwrap();

            let data = S::new_fuzzed(mutator, None);

            global_ctx.mutated_data.push(data);
            global_ctx.iterations += 1;

            Ok(())
        }

        // Do the first run

        let seed: u64 = lain::rand::thread_rng().gen();
        let mut driver = lain::driver::FuzzerDriver::<GlobalContext>::new(1);
        let global_context: Arc<RwLock<GlobalContext>> = Default::default();
        driver.set_global_context(global_context.clone());
        driver.set_seed(seed);

        let driver = Arc::new(driver);

        lain::driver::start_fuzzer(driver.clone(), fuzzer_routine);

        let one_milli = std::time::Duration::from_millis(1);
        loop {
            if driver.num_iterations() >= 20 {
                driver.signal_exit();
                break;
            }

            std::thread::sleep(one_milli);
        }

        driver.join_threads();

        // Recreate the driver for a reproduction run
        let mutated_data = &global_context.read().unwrap().mutated_data[10..15];
        let start_iteration: u64 = 10;
        let end_iteration: u64 = 15;

        let mut driver = lain::driver::FuzzerDriver::<GlobalContext>::new(1);
        let global_context: Arc<RwLock<GlobalContext>> = Default::default();

        driver.set_global_context(global_context.clone());
        driver.set_to_reproduce_mode(start_iteration, end_iteration);
        driver.set_seed(seed);

        let driver = Arc::new(driver);

        lain::driver::start_fuzzer(driver.clone(), fuzzer_routine);

        driver.join_threads();

        // Check for differences
        let reproduced_data = &global_context.read().unwrap().mutated_data;
        for i in 0..mutated_data.len() {
            let i = i as usize;
            assert_eq!(mutated_data[i], reproduced_data[i]);
        }

        //println!("{:?}", global_context.read().unwrap());
    }