1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{DriverMode, Error, IntoTestResult, TestFailure, TestInput, ValueGenerator};
use std::panic::RefUnwindSafe;

pub trait Test: Sized {
    type Value;

    fn test<T: TestInput<Result<bool, Error>>>(&mut self, input: &mut T) -> Result<bool, Error>;
    fn generate_value<T: TestInput<Self::Value>>(&self, input: &mut T) -> Self::Value;
    fn shrink(
        &mut self,
        input: Vec<u8>,
        seed: Option<u64>,
        driver_mode: Option<DriverMode>,
    ) -> Option<TestFailure<Self::Value>> {
        crate::shrink::shrink(self, input, seed, driver_mode)
    }
}

impl<F: RefUnwindSafe + FnMut(&[u8]) -> Ret, Ret> Test for F
where
    Ret: IntoTestResult,
{
    type Value = Vec<u8>;

    fn test<T: TestInput<Result<bool, Error>>>(&mut self, input: &mut T) -> Result<bool, Error> {
        input.with_slice(&mut |slice| {
            crate::panic::catch(&mut || (self)(slice))?.into_test_result()?;
            Ok(true)
        })
    }

    fn generate_value<T: TestInput<Self::Value>>(&self, input: &mut T) -> Self::Value {
        input.with_slice(&mut |slice| slice.to_owned())
    }
}

pub struct GeneratorTest<F, G> {
    fun: F,
    gen: G,
}

impl<F, G> GeneratorTest<F, G> {
    pub fn new(fun: F, gen: G) -> Self {
        Self { fun, gen }
    }
}

impl<F: RefUnwindSafe + FnMut(G::Output) -> Ret, G: RefUnwindSafe + ValueGenerator, Ret> Test
    for GeneratorTest<F, G>
where
    Ret: IntoTestResult,
    G::Output: RefUnwindSafe,
{
    type Value = G::Output;

    fn test<T: TestInput<Result<bool, Error>>>(&mut self, input: &mut T) -> Result<bool, Error> {
        input.with_driver(&mut |driver| {
            crate::panic::catch(&mut || {
                if let Some(value) = self.gen.generate(driver) {
                    (self.fun)(value).into_test_result().map(|_| true)
                } else {
                    Ok(false)
                }
            })?
        })
    }

    fn generate_value<T: TestInput<Self::Value>>(&self, input: &mut T) -> Self::Value {
        input.with_driver(&mut |driver| self.gen.generate(driver).unwrap())
    }
}