Skip to main content

pbt_tests/
lib.rs

1use {
2    core::convert::Infallible,
3    pbt::{
4        Pbt,
5        sigma::{Predicate, Sigma},
6    },
7};
8
9#[non_exhaustive]
10#[derive(Clone, Debug, Eq, PartialEq, Pbt)]
11pub enum Foo {
12    Bar,
13    Baz { a: u64, b: u64, c: Vec<Foo> },
14}
15
16#[derive(Clone, Debug, Eq, PartialEq, Pbt)]
17pub enum PartiallyInstantiable {
18    Instantiable,
19    Uninstantiable(Infallible),
20}
21
22#[derive(Clone, Debug, Eq, PartialEq, Pbt)]
23pub enum Uninhabited {}
24
25pub type NonAnswer = Sigma<u8, NotTheAnswer>;
26
27pub enum NotTheAnswer {}
28
29impl Foo {
30    #[inline]
31    #[must_use]
32    pub fn bus_factor(&self) -> usize {
33        match *self {
34            Self::Bar => 0,
35            Self::Baz { ref c, .. } => c.len(),
36        }
37    }
38}
39
40impl Predicate<u8> for NotTheAnswer {
41    type Error = String;
42
43    #[inline]
44    fn check(candidate: &u8) -> Result<(), Self::Error> {
45        if *candidate == 42 {
46            Err(format!(
47                "The Answer to the Ultimate Question of Life, the Universe, and Everything is {candidate}",
48            ))
49        } else {
50            Ok(())
51        }
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use {super::*, pbt::search, pretty_assertions::assert_eq};
58
59    const N_CASES: usize = 1_000;
60
61    #[test]
62    fn instantiability_logic() {
63        search::assert_eq(N_CASES, |pi: &PartiallyInstantiable| {
64            (pi.clone(), PartiallyInstantiable::Instantiable)
65        });
66    }
67
68    #[test]
69    fn search_and_minimize() {
70        let maybe_witness: Option<Foo> =
71            search::witness(N_CASES, |foo: &Foo| foo.bus_factor() >= 3);
72        assert_eq!(
73            maybe_witness,
74            Some(Foo::Baz {
75                a: 0,
76                b: 0,
77                c: vec![Foo::Bar, Foo::Bar, Foo::Bar],
78            }),
79        );
80    }
81
82    #[test]
83    fn sigma() {
84        search::assert(N_CASES, |u: &NonAnswer| **u != 42);
85    }
86
87    #[test]
88    fn empty_enum_is_supported() {
89        let maybe_witness: Option<Uninhabited> = search::witness(N_CASES, |_| true);
90        assert_eq!(maybe_witness, None);
91    }
92}