Skip to main content

quickcheck/
lib.rs

1/*!
2This crate is a port of
3[Haskell's QuickCheck](https://hackage.haskell.org/package/QuickCheck).
4
5QuickCheck is a library for random testing of program properties. The
6programmer provides a specification of the program, in the form of properties
7which functions should satisfy, and QuickCheck then tests that the properties
8hold in a large number of randomly generated cases.
9
10For detailed examples, please see the
11[README](https://github.com/BurntSushi/quickcheck).
12
13# Compatibility
14
15In general, this crate considers the `Arbitrary` implementations provided as
16implementation details. Strategies may or may not change over time, which may
17cause new test failures, presumably due to the discovery of new bugs due to a
18new kind of witness being generated. These sorts of changes may happen in
19semver compatible releases.
20*/
21
22pub use crate::arbitrary::{
23    empty_shrinker, single_shrinker, Arbitrary, Gen, NoShrink,
24};
25pub use crate::tester::{quickcheck, QuickCheck, TestResult, Testable};
26
27/// A macro for writing quickcheck tests.
28///
29/// This macro takes as input one or more property functions to test, and
30/// produces a proper `#[test]` function for each property. If the property
31/// fails, the behavior is as if `quickcheck` were called on the property
32/// (i.e., it panics and fails the test).
33///
34/// Note that this macro doesn't support `mut` or patterns in parameters.
35///
36/// # Example
37///
38/// ```rust
39/// # #[macro_use] extern crate quickcheck; fn main() {
40/// quickcheck! {
41///     fn prop_reverse_reverse(xs: Vec<usize>) -> bool {
42///         let rev: Vec<_> = xs.clone().into_iter().rev().collect();
43///         let revrev: Vec<_> = rev.into_iter().rev().collect();
44///         xs == revrev
45///     }
46/// };
47/// # }
48/// ```
49#[macro_export]
50macro_rules! quickcheck {
51    (@as_items $($i:item)*) => ($($i)*);
52    {
53        $(
54            $(#[$m:meta])*
55            fn $fn_name:ident($($arg_name:ident : $arg_ty:ty),*) -> $ret:ty {
56                $($code:tt)*
57            }
58        )*
59    } => (
60        $crate::quickcheck! {
61            @as_items
62            $(
63                #[test]
64                $(#[$m])*
65                fn $fn_name() {
66                    fn prop($($arg_name: $arg_ty),*) -> $ret {
67                        $($code)*
68                    }
69                    $crate::quickcheck(prop as fn($($arg_ty),*) -> $ret);
70                }
71            )*
72        }
73    )
74}
75
76#[cfg(feature = "use_logging")]
77fn env_logger_init() -> Result<(), log::SetLoggerError> {
78    env_logger::try_init()
79}
80#[cfg(feature = "use_logging")]
81macro_rules! info {
82    ($($tt:tt)*) => {
83        log::info!($($tt)*)
84    };
85}
86
87#[cfg(not(feature = "use_logging"))]
88fn env_logger_init() {}
89#[cfg(not(feature = "use_logging"))]
90macro_rules! info {
91    ($($_ignore:tt)*) => {
92        ()
93    };
94}
95
96mod arbitrary;
97mod tester;
98
99#[cfg(test)]
100mod tests;