1use core::marker::PhantomData;
22
23use crate::strategy::*;
24use crate::test_runner::*;
25
26#[must_use = "strategies do nothing unless used"]
52#[derive(Clone, Copy, Debug)]
53pub struct UniformArrayStrategy<S, T> {
54 strategy: S,
55 _marker: PhantomData<T>,
56}
57
58impl<S, T> UniformArrayStrategy<S, T> {
59 pub fn new(strategy: S) -> Self {
68 UniformArrayStrategy {
69 strategy,
70 _marker: PhantomData,
71 }
72 }
73}
74
75#[derive(Clone, Copy, Debug)]
77pub struct ArrayValueTree<T> {
78 tree: T,
79 shrinker: usize,
80 last_shrinker: Option<usize>,
81}
82
83macro_rules! small_array {
84 ($n:tt $uni:ident : $($ix:expr),*) => {
85 pub fn $uni<S : Strategy>
94 (strategy: S) -> UniformArrayStrategy<S, [S::Value; $n]>
95 {
96 UniformArrayStrategy {
97 strategy,
98 _marker: PhantomData
99 }
100 }
101
102 impl<S : Strategy> Strategy for [S; $n] {
103 type Tree = ArrayValueTree<[S::Tree; $n]>;
104 type Value = [S::Value; $n];
105
106 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
107 Ok(ArrayValueTree {
108 tree: [$(self[$ix].new_tree(runner)?,)*],
109 shrinker: 0,
110 last_shrinker: None,
111 })
112 }
113 }
114
115 impl<S : Strategy> Strategy
116 for UniformArrayStrategy<S, [S::Value; $n]> {
117 type Tree = ArrayValueTree<[S::Tree; $n]>;
118 type Value = [S::Value; $n];
119
120 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
121 Ok(ArrayValueTree {
122 tree: [$({
123 let _ = $ix;
124 self.strategy.new_tree(runner)?
125 },)*],
126 shrinker: 0,
127 last_shrinker: None,
128 })
129 }
130 }
131
132 impl<T : ValueTree> ValueTree for ArrayValueTree<[T;$n]> {
133 type Value = [T::Value;$n];
134
135 fn current(&self) -> [T::Value;$n] {
136 [$(self.tree[$ix].current(),)*]
137 }
138
139 fn simplify(&mut self) -> bool {
140 while self.shrinker < $n {
141 if self.tree[self.shrinker].simplify() {
142 self.last_shrinker = Some(self.shrinker);
143 return true;
144 } else {
145 self.shrinker += 1;
146 }
147 }
148
149 false
150 }
151
152 fn complicate(&mut self) -> bool {
153 if let Some(shrinker) = self.last_shrinker {
154 self.shrinker = shrinker;
155 if self.tree[shrinker].complicate() {
156 true
157 } else {
158 self.last_shrinker = None;
159 false
160 }
161 } else {
162 false
163 }
164 }
165 }
166 }
167}
168
169small_array!(1 uniform1:
170 0);
171small_array!(2 uniform2:
172 0, 1);
173small_array!(3 uniform3:
174 0, 1, 2);
175small_array!(4 uniform4:
176 0, 1, 2, 3);
177small_array!(5 uniform5:
178 0, 1, 2, 3, 4);
179small_array!(6 uniform6:
180 0, 1, 2, 3, 4, 5);
181small_array!(7 uniform7:
182 0, 1, 2, 3, 4, 5, 6);
183small_array!(8 uniform8:
184 0, 1, 2, 3, 4, 5, 6, 7);
185small_array!(9 uniform9:
186 0, 1, 2, 3, 4, 5, 6, 7, 8);
187small_array!(10 uniform10:
188 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
189small_array!(11 uniform11:
190 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
191small_array!(12 uniform12:
192 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
193small_array!(13 uniform13:
194 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
195small_array!(14 uniform14:
196 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
197small_array!(15 uniform15:
198 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
199small_array!(16 uniform16:
200 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
201small_array!(17 uniform17:
202 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
203small_array!(18 uniform18:
204 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
205small_array!(19 uniform19:
206 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
207 18);
208small_array!(20 uniform20:
209 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
210 18, 19);
211small_array!(21 uniform21:
212 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
213 18, 19, 20);
214small_array!(22 uniform22:
215 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
216 18, 19, 20, 21);
217small_array!(23 uniform23:
218 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
219 18, 19, 20, 21, 22);
220small_array!(24 uniform24:
221 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
222 18, 19, 20, 21, 22, 23);
223small_array!(25 uniform25:
224 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
225 18, 19, 20, 21, 22, 23, 24);
226small_array!(26 uniform26:
227 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
228 18, 19, 20, 21, 22, 23, 24, 25);
229small_array!(27 uniform27:
230 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
231 18, 19, 20, 21, 22, 23, 24, 25, 26);
232small_array!(28 uniform28:
233 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
234 18, 19, 20, 21, 22, 23, 24, 25, 26, 27);
235small_array!(29 uniform29:
236 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
237 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
238small_array!(30 uniform30:
239 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
240 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29);
241small_array!(31 uniform31:
242 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
243 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30);
244small_array!(32 uniform32:
245 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
246 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31);
247
248#[cfg(test)]
249mod test {
250 use super::*;
251
252 #[test]
253 fn shrinks_fully_ltr() {
254 fn pass(a: [i32; 2]) -> bool {
255 a[0] * a[1] <= 9
256 }
257
258 let input = [0..32, 0..32];
259 let mut runner = TestRunner::deterministic();
260
261 let mut cases_tested = 0;
262 for _ in 0..256 {
263 let mut case = input.new_tree(&mut runner).unwrap();
265 if pass(case.current()) {
266 continue;
267 }
268
269 loop {
270 if pass(case.current()) {
271 if !case.complicate() {
272 break;
273 }
274 } else {
275 if !case.simplify() {
276 break;
277 }
278 }
279 }
280
281 let last = case.current();
282 assert!(!pass(last));
283 assert!(pass([last[0] - 1, last[1]]));
285 assert!(pass([last[0], last[1] - 1]));
286
287 cases_tested += 1;
288 }
289
290 assert!(cases_tested > 32, "Didn't find enough test cases");
291 }
292
293 #[test]
294 fn test_sanity() {
295 check_strategy_sanity([(0i32..1000), (1i32..1000)], None);
296 }
297}