1use crate::strategy::*;
16use crate::test_runner::*;
17
18#[derive(Clone, Copy, Debug)]
20pub struct TupleValueTree<T> {
21 tree: T,
22 shrinker: u32,
23 prev_shrinker: Option<u32>,
24}
25
26impl<T> TupleValueTree<T> {
27 pub fn new(inner: T) -> Self {
32 TupleValueTree {
33 tree: inner,
34 shrinker: 0,
35 prev_shrinker: None,
36 }
37 }
38}
39
40macro_rules! tuple {
41 ($($fld:tt : $typ:ident),*) => {
42 impl<$($typ : Strategy),*> Strategy for ($($typ,)*) {
43 type Tree = TupleValueTree<($($typ::Tree,)*)>;
44 type Value = ($($typ::Value,)*);
45
46 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
47 let values = ($(self.$fld.new_tree(runner)?,)*);
48 Ok(TupleValueTree::new(values))
49 }
50 }
51
52 impl<$($typ : ValueTree),*> ValueTree
53 for TupleValueTree<($($typ,)*)> {
54 type Value = ($($typ::Value,)*);
55
56 fn current(&self) -> Self::Value {
57 ($(self.tree.$fld.current(),)*)
58 }
59
60 fn simplify(&mut self) -> bool {
61 $(
62 if $fld == self.shrinker {
63 if self.tree.$fld.simplify() {
64 self.prev_shrinker = Some(self.shrinker);
65 return true;
66 } else {
67 self.shrinker += 1;
68 }
69 }
70 )*
71 false
72 }
73
74 fn complicate(&mut self) -> bool {
75 if let Some(shrinker) = self.prev_shrinker {$(
76 if $fld == shrinker {
77 if self.tree.$fld.complicate() {
78 self.shrinker = shrinker;
79 return true;
80 } else {
81 self.prev_shrinker = None;
82 return false;
83 }
84 }
85 )*}
86 false
87 }
88 }
89 }
90}
91
92tuple!(0: A);
93tuple!(0: A, 1: B);
94tuple!(0: A, 1: B, 2: C);
95tuple!(0: A, 1: B, 2: C, 3: D);
96tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
97tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
98tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);
99tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H);
100tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I);
101tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J);
102tuple!(
103 0: A,
104 1: B,
105 2: C,
106 3: D,
107 4: E,
108 5: F,
109 6: G,
110 7: H,
111 8: I,
112 9: J,
113 10: K
114);
115tuple!(
116 0: A,
117 1: B,
118 2: C,
119 3: D,
120 4: E,
121 5: F,
122 6: G,
123 7: H,
124 8: I,
125 9: J,
126 10: K,
127 11: L
128);
129
130#[cfg(test)]
131mod test {
132 use crate::strategy::*;
133
134 use super::*;
135
136 #[test]
137 fn shrinks_fully_ltr() {
138 fn pass(a: (i32, i32)) -> bool {
139 a.0 * a.1 <= 9
140 }
141
142 let input = (0..32, 0..32);
143 let mut runner = TestRunner::default();
144
145 let mut cases_tested = 0;
146 for _ in 0..256 {
147 let mut case = input.new_tree(&mut runner).unwrap();
149 if pass(case.current()) {
150 continue;
151 }
152
153 loop {
154 if pass(case.current()) {
155 if !case.complicate() {
156 break;
157 }
158 } else {
159 if !case.simplify() {
160 break;
161 }
162 }
163 }
164
165 let last = case.current();
166 assert!(!pass(last));
167 assert!(pass((last.0 - 1, last.1)));
169 assert!(pass((last.0, last.1 - 1)));
170
171 cases_tested += 1;
172 }
173
174 assert!(cases_tested > 32, "Didn't find enough test cases");
175 }
176
177 #[test]
178 fn test_sanity() {
179 check_strategy_sanity((0i32..100, 0i32..1000, 0i32..10000), None);
180 }
181}