use crate::strategy::*;
use crate::test_runner::*;
use rand::Rng;
#[derive(Clone, Copy, Debug)]
pub struct Any(());
pub const ANY: Any = Any(());
impl Strategy for Any {
type Tree = BoolValueTree;
type Value = bool;
fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
Ok(BoolValueTree::new(runner.rng().gen()))
}
}
pub fn weighted(probability: f64) -> Weighted {
Weighted(probability)
}
#[must_use = "strategies do nothing unless used"]
#[derive(Clone, Copy, Debug)]
pub struct Weighted(f64);
impl Strategy for Weighted {
type Tree = BoolValueTree;
type Value = bool;
fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
Ok(BoolValueTree::new(runner.rng().gen_bool(self.0)))
}
}
#[derive(Clone, Copy, Debug)]
pub struct BoolValueTree {
current: bool,
state: ShrinkState,
}
#[derive(Clone, Copy, Debug, PartialEq)]
enum ShrinkState {
Untouched,
Simplified,
Final,
}
impl BoolValueTree {
fn new(current: bool) -> Self {
BoolValueTree {
current,
state: ShrinkState::Untouched,
}
}
}
impl ValueTree for BoolValueTree {
type Value = bool;
fn current(&self) -> bool {
self.current
}
fn simplify(&mut self) -> bool {
match self.state {
ShrinkState::Untouched if self.current => {
self.current = false;
self.state = ShrinkState::Simplified;
true
}
ShrinkState::Untouched
| ShrinkState::Simplified
| ShrinkState::Final => {
self.state = ShrinkState::Final;
false
}
}
}
fn complicate(&mut self) -> bool {
match self.state {
ShrinkState::Untouched | ShrinkState::Final => {
self.state = ShrinkState::Final;
false
}
ShrinkState::Simplified => {
self.current = true;
self.state = ShrinkState::Final;
true
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_sanity() {
check_strategy_sanity(ANY, None);
}
#[test]
fn shrinks_properly() {
let mut tree = BoolValueTree::new(true);
assert!(tree.simplify());
assert!(!tree.current());
assert!(!tree.clone().simplify());
assert!(tree.complicate());
assert!(!tree.clone().complicate());
assert!(tree.current());
assert!(!tree.simplify());
assert!(tree.current());
tree = BoolValueTree::new(false);
assert!(!tree.clone().simplify());
assert!(!tree.clone().complicate());
assert!(!tree.current());
}
}