use std::fmt::Debug;
use rand::rngs::StdRng;
use rand::SeedableRng;
use crate::property::shrink::shrink_counterexample;
use crate::property::strategy::Strategy;
const DEFAULT_NUM_TESTS: u64 = 100;
const DEFAULT_SHRINKS: u64 = 1000;
#[derive(Debug, Clone)]
pub struct PropertyConfig {
pub num_tests: u64,
pub max_shrinks: u64,
pub seed: Option<u64>,
}
impl Default for PropertyConfig {
fn default() -> Self {
PropertyConfig { num_tests: DEFAULT_NUM_TESTS, max_shrinks: DEFAULT_SHRINKS, seed: None }
}
}
pub fn check<T, S>(
_name: &str,
strategy: S,
property: impl Fn(&T) -> bool,
) where
T: Debug,
S: Strategy<T>,
{
check_with(_name, strategy, property, PropertyConfig::default());
}
pub fn check_with<T, S>(
_name: &str,
strategy: S,
property: impl Fn(&T) -> bool,
config: PropertyConfig,
) where
T: Debug,
S: Strategy<T>,
{
let seed = config.seed.unwrap_or_else(rand::random);
let mut rng = StdRng::seed_from_u64(seed);
for _ in 0..config.num_tests {
let value = strategy.generate(&mut rng);
if !property(&value) {
let shrunk = shrink_counterexample(&value, &strategy, &property, config.max_shrinks);
panic!(
"property falsified after {} test(s)\n\
seed: {seed}\n\
counterexample: {value:?}\n\
shrunk to: {shrunk:?}",
config.num_tests,
);
}
}
}