use crate::std_facade::fmt;
use crate::strategy::traits::*;
use crate::test_runner::*;
pub trait FilterFn<T> {
fn apply(&self, t: &T) -> bool;
}
#[derive(Clone)]
#[must_use = "strategies do nothing unless used"]
pub struct Filter<S, F> {
source: S,
whence: Reason,
fun: F,
}
impl<S, F> Filter<S, F> {
pub fn new(source: S, whence: Reason, filter: F) -> Self {
Filter {
source,
whence,
fun: filter,
}
}
}
impl<S: fmt::Debug, F> fmt::Debug for Filter<S, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Filter")
.field("source", &self.source)
.field("whence", &self.whence)
.field("fun", &"<function>")
.finish()
}
}
impl<S: Strategy, F: FilterFn<S::Value> + Clone> Strategy for Filter<S, F> {
type Tree = Filter<S::Tree, F>;
type Value = S::Value;
fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
loop {
let val = self.source.new_tree(runner)?;
if !self.fun.apply(&val.current()) {
runner.reject_local(self.whence.clone())?;
} else {
return Ok(Filter {
source: val,
whence: "unused".into(),
fun: self.fun.clone(),
});
}
}
}
}
impl<S: ValueTree, F: FilterFn<S::Value>> Filter<S, F> {
fn ensure_acceptable(&mut self) {
while !self.fun.apply(&self.source.current()) {
if !self.source.complicate() {
panic!(
"Unable to complicate filtered strategy \
back into acceptable value"
);
}
}
}
}
impl<S: ValueTree, F: FilterFn<S::Value>> ValueTree for Filter<S, F> {
type Value = S::Value;
fn current(&self) -> S::Value {
self.source.current()
}
fn simplify(&mut self) -> bool {
if self.source.simplify() {
self.ensure_acceptable();
true
} else {
false
}
}
fn complicate(&mut self) -> bool {
if self.source.complicate() {
self.ensure_acceptable();
true
} else {
false
}
}
}
pub trait MapFn<T> {
#[allow(missing_docs)]
type Output: fmt::Debug;
fn apply(&self, t: T) -> Self::Output;
}
#[derive(Clone)]
#[must_use = "strategies do nothing unless used"]
pub struct Map<S, F> {
source: S,
fun: F,
}
impl<S, F> Map<S, F> {
pub fn new(source: S, fun: F) -> Self {
Map { source, fun }
}
}
impl<S: fmt::Debug, F> fmt::Debug for Map<S, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Map")
.field("source", &self.source)
.field("fun", &"<function>")
.finish()
}
}
impl<S: Strategy, F: Clone + MapFn<S::Value>> Strategy for Map<S, F> {
type Tree = Map<S::Tree, F>;
type Value = F::Output;
fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
self.source.new_tree(runner).map(|v| Map {
source: v,
fun: self.fun.clone(),
})
}
}
impl<S: ValueTree, F: MapFn<S::Value>> ValueTree for Map<S, F> {
type Value = F::Output;
fn current(&self) -> F::Output {
self.fun.apply(self.source.current())
}
fn simplify(&mut self) -> bool {
self.source.simplify()
}
fn complicate(&mut self) -> bool {
self.source.complicate()
}
}
impl<I, O: fmt::Debug> MapFn<I> for fn(I) -> O {
type Output = O;
fn apply(&self, x: I) -> Self::Output {
self(x)
}
}
pub(crate) fn static_map<S: Strategy, O: fmt::Debug>(
strat: S,
fun: fn(S::Value) -> O,
) -> Map<S, fn(S::Value) -> O> {
Map::new(strat, fun)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_static_filter() {
#[derive(Clone, Copy, Debug)]
struct MyFilter;
impl FilterFn<i32> for MyFilter {
fn apply(&self, &v: &i32) -> bool {
0 == v % 3
}
}
let input = Filter::new(0..256, "%3".into(), MyFilter);
for _ in 0..256 {
let mut runner = TestRunner::default();
let mut case = input.new_tree(&mut runner).unwrap();
assert!(0 == case.current() % 3);
while case.simplify() {
assert!(0 == case.current() % 3);
}
assert!(0 == case.current() % 3);
}
}
#[test]
fn test_static_map() {
#[derive(Clone, Copy, Debug)]
struct MyMap;
impl MapFn<i32> for MyMap {
type Output = i32;
fn apply(&self, v: i32) -> i32 {
v * 2
}
}
let input = Map::new(0..10, MyMap);
TestRunner::default()
.run(&input, |v| {
assert!(0 == v % 2);
Ok(())
})
.unwrap();
}
}