use crate::strategy::*;
use crate::test_runner::*;
#[derive(Debug, Clone, Copy)]
#[must_use = "strategies do nothing unless used"]
pub struct Fuse<T> {
inner: T,
may_simplify: bool,
may_complicate: bool,
}
impl<T> Fuse<T> {
pub fn new(inner: T) -> Self {
Fuse {
inner,
may_simplify: true,
may_complicate: false,
}
}
}
impl<T: Strategy> Strategy for Fuse<T> {
type Tree = Fuse<T::Tree>;
type Value = T::Value;
fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
self.inner.new_tree(runner).map(Fuse::new)
}
}
impl<T: ValueTree> Fuse<T> {
pub fn may_simplify(&self) -> bool {
self.may_simplify
}
pub fn disallow_simplify(&mut self) {
self.may_simplify = false;
}
pub fn may_complicate(&self) -> bool {
self.may_complicate
}
pub fn disallow_complicate(&mut self) {
self.may_complicate = false;
}
pub fn freeze(&mut self) {
self.disallow_simplify();
self.disallow_complicate();
}
}
impl<T: ValueTree> ValueTree for Fuse<T> {
type Value = T::Value;
fn current(&self) -> T::Value {
self.inner.current()
}
fn simplify(&mut self) -> bool {
if self.may_simplify {
if self.inner.simplify() {
self.may_complicate = true;
true
} else {
self.may_simplify = false;
false
}
} else {
false
}
}
fn complicate(&mut self) -> bool {
if self.may_complicate {
if self.inner.complicate() {
self.may_simplify = true;
true
} else {
self.may_complicate = false;
false
}
} else {
false
}
}
}
#[cfg(test)]
mod test {
use super::*;
struct StrictValueTree {
min: u32,
curr: u32,
max: u32,
ready: bool,
}
impl StrictValueTree {
fn new(start: u32) -> Self {
StrictValueTree {
min: 0,
curr: start,
max: start,
ready: false,
}
}
}
impl ValueTree for StrictValueTree {
type Value = u32;
fn current(&self) -> u32 {
self.curr
}
fn simplify(&mut self) -> bool {
assert!(self.min <= self.curr);
if self.curr > self.min {
self.max = self.curr;
self.curr -= 1;
self.ready = true;
true
} else {
self.min += 1;
false
}
}
fn complicate(&mut self) -> bool {
assert!(self.max >= self.curr);
assert!(self.ready);
if self.curr < self.max {
self.curr += 1;
true
} else {
self.max -= 1;
false
}
}
}
#[test]
fn test_sanity() {
check_strategy_sanity(Fuse::new(0i32..100i32), None);
}
#[test]
fn guards_bad_transitions() {
let mut vt = Fuse::new(StrictValueTree::new(5));
assert!(!vt.complicate());
assert_eq!(5, vt.current());
assert!(vt.simplify()); assert!(vt.simplify()); assert!(vt.simplify()); assert!(vt.simplify()); assert!(vt.simplify()); assert_eq!(0, vt.current());
assert!(!vt.simplify()); assert!(!vt.simplify()); assert_eq!(0, vt.current());
assert!(vt.complicate()); assert_eq!(1, vt.current());
assert!(!vt.complicate()); assert!(!vt.complicate()); assert_eq!(1, vt.current());
}
}