From c9eb2884d6a620b90b9986c65916eebc57084e89 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Sat, 8 Mar 2014 02:34:05 -0500 Subject: [PATCH] Shrinking appears to be working. --- qc.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 qc.rs diff --git a/qc.rs b/qc.rs new file mode 100644 index 0000000..cf545a1 --- /dev/null +++ b/qc.rs @@ -0,0 +1,95 @@ +use std::iter::Unfold; +use std::rand; +use std::vec; + +trait Arbitrary { + fn arbitrary(rng: &mut R) -> Self; +} + +trait Shrink> { + fn shrink(&self) -> T; +} + +impl Arbitrary for T { + fn arbitrary(rng: &mut R) -> T { rng.gen() } +} + +impl Shrink> for () { + fn shrink(&self) -> vec::MoveItems<()> { (~[]).move_iter() } +} + +impl Shrink> for bool { + fn shrink(&self) -> vec::MoveItems { + match *self { + true => (~[false]).move_iter(), + false => (~[]).move_iter(), + } + } +} + +struct OptionState { + state: Option, + started: bool, +} + +impl, Ia: Iterator> + Shrink, OptionState>> + for Option +{ + fn shrink(&self) -> Unfold<'static, Option, OptionState> { + let init = match *self { + None => None, + Some(ref x) => Some(x.shrink()), + }; + let st = OptionState{ + state: init, + started: false, + }; + Unfold::new(st, |st: &mut OptionState| -> Option> { + match st.state { + None => return None, + Some(ref mut x) => { + if !st.started { + st.started = true; + return Some(None) + } + match x.next() { + None => None, + Some(it) => Some(Some(it)), + } + } + } + }) + } +} + +impl, B: Shrink, Ia: Iterator, Ib: Iterator> + Shrink, Result>> + for Result +{ + fn shrink(&self) -> Unfold<'static, Result, Result> { + let init = match *self { + Ok(ref a) => Ok(a.shrink()), + Err(ref b) => Err(b.shrink()), + }; + Unfold::new(init, |st: &mut Result| -> Option> { + match *st { + Ok(ref mut a) => match a.next() { + None => return None, + Some(a) => Some(Ok(a)), + }, + Err(ref mut b) => match b.next() { + None => return None, + Some(b) => Some(Err(b)), + }, + } + }) + } +} + +fn main() { + // let mut rng = ~rand::rng(); + let r: Option, ()>> = Some(Ok(Some(true))); + println!("{}", Some(true).shrink().to_owned_vec()); + println!("{}", r.shrink().to_owned_vec()); +}