1 #![allow(unstable_name_collisions)]
2 
3 use itertools::Itertools;
4 use quickcheck::Arbitrary;
5 use quickcheck::{quickcheck, TestResult};
6 use rand::Rng;
7 use std::fmt::Debug;
8 
9 struct Unspecialized<I>(I);
10 
11 impl<I> Iterator for Unspecialized<I>
12 where
13     I: Iterator,
14 {
15     type Item = I::Item;
16 
17     #[inline(always)]
next(&mut self) -> Option<Self::Item>18     fn next(&mut self) -> Option<Self::Item> {
19         self.0.next()
20     }
21 }
22 
23 impl<I> DoubleEndedIterator for Unspecialized<I>
24 where
25     I: DoubleEndedIterator,
26 {
27     #[inline(always)]
next_back(&mut self) -> Option<Self::Item>28     fn next_back(&mut self) -> Option<Self::Item> {
29         self.0.next_back()
30     }
31 }
32 
test_specializations<I>(it: &I) where I::Item: Eq + Debug + Clone, I: Iterator + Clone,33 fn test_specializations<I>(it: &I)
34 where
35     I::Item: Eq + Debug + Clone,
36     I: Iterator + Clone,
37 {
38     macro_rules! check_specialized {
39         ($src:expr, |$it:pat| $closure:expr) => {
40             // Many iterators special-case the first elements, so we test specializations for iterators that have already been advanced.
41             let mut src = $src.clone();
42             for _ in 0..5 {
43                 let $it = src.clone();
44                 let v1 = $closure;
45                 let $it = Unspecialized(src.clone());
46                 let v2 = $closure;
47                 assert_eq!(v1, v2);
48                 src.next();
49             }
50         }
51     }
52     check_specialized!(it, |i| i.count());
53     check_specialized!(it, |i| i.last());
54     check_specialized!(it, |i| i.collect::<Vec<_>>());
55     check_specialized!(it, |i| {
56         let mut parameters_from_fold = vec![];
57         let fold_result = i.fold(vec![], |mut acc, v: I::Item| {
58             parameters_from_fold.push((acc.clone(), v.clone()));
59             acc.push(v);
60             acc
61         });
62         (parameters_from_fold, fold_result)
63     });
64     check_specialized!(it, |mut i| {
65         let mut parameters_from_all = vec![];
66         let first = i.next();
67         let all_result = i.all(|x| {
68             parameters_from_all.push(x.clone());
69             Some(x) == first
70         });
71         (parameters_from_all, all_result)
72     });
73     let size = it.clone().count();
74     for n in 0..size + 2 {
75         check_specialized!(it, |mut i| i.nth(n));
76     }
77     // size_hint is a bit harder to check
78     let mut it_sh = it.clone();
79     for n in 0..size + 2 {
80         let len = it_sh.clone().count();
81         let (min, max) = it_sh.size_hint();
82         assert_eq!(size - n.min(size), len);
83         assert!(min <= len);
84         if let Some(max) = max {
85             assert!(len <= max);
86         }
87         it_sh.next();
88     }
89 }
90 
test_double_ended_specializations<I>(it: &I) where I::Item: Eq + Debug + Clone, I: DoubleEndedIterator + Clone,91 fn test_double_ended_specializations<I>(it: &I)
92 where
93     I::Item: Eq + Debug + Clone,
94     I: DoubleEndedIterator + Clone,
95 {
96     macro_rules! check_specialized {
97         ($src:expr, |$it:pat| $closure:expr) => {
98             // Many iterators special-case the first elements, so we test specializations for iterators that have already been advanced.
99             let mut src = $src.clone();
100             for step in 0..8 {
101                 let $it = src.clone();
102                 let v1 = $closure;
103                 let $it = Unspecialized(src.clone());
104                 let v2 = $closure;
105                 assert_eq!(v1, v2);
106                 if step % 2 == 0 {
107                     src.next();
108                 } else {
109                     src.next_back();
110                 }
111             }
112         }
113     }
114     check_specialized!(it, |i| {
115         let mut parameters_from_rfold = vec![];
116         let rfold_result = i.rfold(vec![], |mut acc, v: I::Item| {
117             parameters_from_rfold.push((acc.clone(), v.clone()));
118             acc.push(v);
119             acc
120         });
121         (parameters_from_rfold, rfold_result)
122     });
123     let size = it.clone().count();
124     for n in 0..size + 2 {
125         check_specialized!(it, |mut i| i.nth_back(n));
126     }
127 }
128 
129 quickcheck! {
130     fn interleave(v: Vec<u8>, w: Vec<u8>) -> () {
131         test_specializations(&v.iter().interleave(w.iter()));
132     }
133 
134     fn interleave_shortest(v: Vec<u8>, w: Vec<u8>) -> () {
135         test_specializations(&v.iter().interleave_shortest(w.iter()));
136     }
137 
138     fn batching(v: Vec<u8>) -> () {
139         test_specializations(&v.iter().batching(Iterator::next));
140     }
141 
142     fn tuple_windows(v: Vec<u8>) -> () {
143         test_specializations(&v.iter().tuple_windows::<(_,)>());
144         test_specializations(&v.iter().tuple_windows::<(_, _)>());
145         test_specializations(&v.iter().tuple_windows::<(_, _, _)>());
146     }
147 
148     fn circular_tuple_windows(v: Vec<u8>) -> () {
149         test_specializations(&v.iter().circular_tuple_windows::<(_,)>());
150         test_specializations(&v.iter().circular_tuple_windows::<(_, _)>());
151         test_specializations(&v.iter().circular_tuple_windows::<(_, _, _)>());
152     }
153 
154     fn tuples(v: Vec<u8>) -> () {
155         test_specializations(&v.iter().tuples::<(_,)>());
156         test_specializations(&v.iter().tuples::<(_, _)>());
157         test_specializations(&v.iter().tuples::<(_, _, _)>());
158     }
159 
160     fn cartesian_product(a: Vec<u8>, b: Vec<u8>) -> TestResult {
161         if a.len() * b.len() > 100 {
162             return TestResult::discard();
163         }
164         test_specializations(&a.iter().cartesian_product(&b));
165         TestResult::passed()
166     }
167 
168     fn multi_cartesian_product(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> TestResult {
169         if a.len() * b.len() * c.len() > 100 {
170             return TestResult::discard();
171         }
172         test_specializations(&vec![a, b, c].into_iter().multi_cartesian_product());
173         TestResult::passed()
174     }
175 
176     fn coalesce(v: Vec<u8>) -> () {
177         test_specializations(&v.iter().coalesce(|x, y| if x == y { Ok(x) } else { Err((x, y)) }))
178     }
179 
180     fn dedup(v: Vec<u8>) -> () {
181         test_specializations(&v.iter().dedup())
182     }
183 
184     fn dedup_by(v: Vec<u8>) -> () {
185         test_specializations(&v.iter().dedup_by(PartialOrd::ge))
186     }
187 
188     fn dedup_with_count(v: Vec<u8>) -> () {
189         test_specializations(&v.iter().dedup_with_count())
190     }
191 
192     fn dedup_by_with_count(v: Vec<u8>) -> () {
193         test_specializations(&v.iter().dedup_by_with_count(PartialOrd::ge))
194     }
195 
196     fn duplicates(v: Vec<u8>) -> () {
197         let it = v.iter().duplicates();
198         test_specializations(&it);
199         test_double_ended_specializations(&it);
200     }
201 
202     fn duplicates_by(v: Vec<u8>) -> () {
203         let it = v.iter().duplicates_by(|x| *x % 10);
204         test_specializations(&it);
205         test_double_ended_specializations(&it);
206     }
207 
208     fn unique(v: Vec<u8>) -> () {
209         let it = v.iter().unique();
210         test_specializations(&it);
211         test_double_ended_specializations(&it);
212     }
213 
214     fn unique_by(v: Vec<u8>) -> () {
215         let it = v.iter().unique_by(|x| *x % 50);
216         test_specializations(&it);
217         test_double_ended_specializations(&it);
218     }
219 
220     fn take_while_inclusive(v: Vec<u8>) -> () {
221         test_specializations(&v.iter().copied().take_while_inclusive(|&x| x < 100));
222     }
223 
224     fn while_some(v: Vec<u8>) -> () {
225         test_specializations(&v.iter().map(|&x| if x < 100 { Some(2 * x) } else { None }).while_some());
226     }
227 
228     fn pad_using(v: Vec<u8>) -> () {
229         use std::convert::TryFrom;
230         let it = v.iter().copied().pad_using(10, |i| u8::try_from(5 * i).unwrap_or(u8::MAX));
231         test_specializations(&it);
232         test_double_ended_specializations(&it);
233     }
234 
235     fn with_position(v: Vec<u8>) -> () {
236         test_specializations(&v.iter().with_position());
237     }
238 
239     fn positions(v: Vec<u8>) -> () {
240         let it = v.iter().positions(|x| x % 5 == 0);
241         test_specializations(&it);
242         test_double_ended_specializations(&it);
243     }
244 
245     fn update(v: Vec<u8>) -> () {
246         let it = v.iter().copied().update(|x| *x = x.wrapping_mul(7));
247         test_specializations(&it);
248         test_double_ended_specializations(&it);
249     }
250 
251     fn tuple_combinations(v: Vec<u8>) -> TestResult {
252         if v.len() > 10 {
253             return TestResult::discard();
254         }
255         test_specializations(&v.iter().tuple_combinations::<(_,)>());
256         test_specializations(&v.iter().tuple_combinations::<(_, _)>());
257         test_specializations(&v.iter().tuple_combinations::<(_, _, _)>());
258         TestResult::passed()
259     }
260 
261     fn intersperse(v: Vec<u8>) -> () {
262         test_specializations(&v.into_iter().intersperse(0));
263     }
264 
265     fn intersperse_with(v: Vec<u8>) -> () {
266         test_specializations(&v.into_iter().intersperse_with(|| 0));
267     }
268 
269     fn combinations(a: Vec<u8>, n: u8) -> TestResult {
270         if n > 3 || a.len() > 8 {
271             return TestResult::discard();
272         }
273         test_specializations(&a.iter().combinations(n as usize));
274         TestResult::passed()
275     }
276 
277     fn combinations_with_replacement(a: Vec<u8>, n: u8) -> TestResult {
278         if n > 3 || a.len() > 7 {
279             return TestResult::discard();
280         }
281         test_specializations(&a.iter().combinations_with_replacement(n as usize));
282         TestResult::passed()
283     }
284 
285     fn permutations(a: Vec<u8>, n: u8) -> TestResult {
286         if n > 3 || a.len() > 8 {
287             return TestResult::discard();
288         }
289         test_specializations(&a.iter().permutations(n as usize));
290         TestResult::passed()
291     }
292 
293     fn powerset(a: Vec<u8>) -> TestResult {
294         if a.len() > 6 {
295             return TestResult::discard();
296         }
297         test_specializations(&a.iter().powerset());
298         TestResult::passed()
299     }
300 
301     fn zip_longest(a: Vec<u8>, b: Vec<u8>) -> () {
302         let it = a.into_iter().zip_longest(b);
303         test_specializations(&it);
304         test_double_ended_specializations(&it);
305     }
306 
307     fn zip_eq(a: Vec<u8>) -> () {
308         test_specializations(&a.iter().zip_eq(a.iter().rev()))
309     }
310 
311     fn multizip(a: Vec<u8>) -> () {
312         let it = itertools::multizip((a.iter(), a.iter().rev(), a.iter().take(50)));
313         test_specializations(&it);
314         test_double_ended_specializations(&it);
315     }
316 
317     fn izip(a: Vec<u8>, b: Vec<u8>) -> () {
318         test_specializations(&itertools::izip!(b.iter(), a, b.iter().rev()));
319     }
320 
321     fn iproduct(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> TestResult {
322         if a.len() * b.len() * c.len() > 200 {
323             return TestResult::discard();
324         }
325         test_specializations(&itertools::iproduct!(a, b.iter(), c));
326         TestResult::passed()
327     }
328 
329     fn repeat_n(element: i8, n: u8) -> () {
330         let it = itertools::repeat_n(element, n as usize);
331         test_specializations(&it);
332         test_double_ended_specializations(&it);
333     }
334 
335     fn exactly_one_error(v: Vec<u8>) -> TestResult {
336         // Use `at_most_one` would be similar.
337         match v.iter().exactly_one() {
338             Ok(_) => TestResult::discard(),
339             Err(it) => {
340                 test_specializations(&it);
341                 TestResult::passed()
342             }
343         }
344     }
345 }
346 
347 quickcheck! {
348     fn put_back_qc(test_vec: Vec<i32>) -> () {
349         test_specializations(&itertools::put_back(test_vec.iter()));
350         let mut pb = itertools::put_back(test_vec.into_iter());
351         pb.put_back(1);
352         test_specializations(&pb);
353     }
354 
355     fn put_back_n(v: Vec<u8>, n: u8) -> () {
356         let mut it = itertools::put_back_n(v);
357         for k in 0..n {
358             it.put_back(k);
359         }
360         test_specializations(&it);
361     }
362 
363     fn multipeek(v: Vec<u8>, n: u8) -> () {
364         let mut it = v.into_iter().multipeek();
365         for _ in 0..n {
366             it.peek();
367         }
368         test_specializations(&it);
369     }
370 
371     fn peek_nth_with_peek(v: Vec<u8>, n: u8) -> () {
372         let mut it = itertools::peek_nth(v);
373         for _ in 0..n {
374             it.peek();
375         }
376         test_specializations(&it);
377     }
378 
379     fn peek_nth_with_peek_nth(v: Vec<u8>, n: u8) -> () {
380         let mut it = itertools::peek_nth(v);
381         it.peek_nth(n as usize);
382         test_specializations(&it);
383     }
384 
385     fn peek_nth_with_peek_mut(v: Vec<u8>, n: u8) -> () {
386         let mut it = itertools::peek_nth(v);
387         for _ in 0..n {
388             if let Some(x) = it.peek_mut() {
389                 *x = x.wrapping_add(50);
390             }
391         }
392         test_specializations(&it);
393     }
394 
395     fn peek_nth_with_peek_nth_mut(v: Vec<u8>, n: u8) -> () {
396         let mut it = itertools::peek_nth(v);
397         if let Some(x) = it.peek_nth_mut(n as usize) {
398             *x = x.wrapping_add(50);
399         }
400         test_specializations(&it);
401     }
402 }
403 
404 quickcheck! {
405     fn merge(a: Vec<u8>, b: Vec<u8>) -> () {
406         test_specializations(&a.into_iter().merge(b))
407     }
408 
409     fn merge_by(a: Vec<u8>, b: Vec<u8>) -> () {
410         test_specializations(&a.into_iter().merge_by(b, PartialOrd::ge))
411     }
412 
413     fn merge_join_by_ordering(i1: Vec<u8>, i2: Vec<u8>) -> () {
414         test_specializations(&i1.into_iter().merge_join_by(i2, Ord::cmp));
415     }
416 
417     fn merge_join_by_bool(i1: Vec<u8>, i2: Vec<u8>) -> () {
418         test_specializations(&i1.into_iter().merge_join_by(i2, PartialOrd::ge));
419     }
420 
421     fn kmerge(a: Vec<i8>, b: Vec<i8>, c: Vec<i8>) -> () {
422         test_specializations(&vec![a, b, c]
423             .into_iter()
424             .map(|v| v.into_iter().sorted())
425             .kmerge());
426     }
427 
428     fn kmerge_by(a: Vec<i8>, b: Vec<i8>, c: Vec<i8>) -> () {
429         test_specializations(&vec![a, b, c]
430             .into_iter()
431             .map(|v| v.into_iter().sorted_by_key(|a| a.abs()))
432             .kmerge_by(|a, b| a.abs() < b.abs()));
433     }
434 }
435 
436 quickcheck! {
437     fn map_into(v: Vec<u8>) -> () {
438         let it = v.into_iter().map_into::<u32>();
439         test_specializations(&it);
440         test_double_ended_specializations(&it);
441     }
442 
443     fn map_ok(v: Vec<Result<u8, char>>) -> () {
444         let it = v.into_iter().map_ok(|u| u.checked_add(1));
445         test_specializations(&it);
446         test_double_ended_specializations(&it);
447     }
448 
449     fn filter_ok(v: Vec<Result<u8, char>>) -> () {
450         test_specializations(&v.into_iter().filter_ok(|&i| i < 20));
451     }
452 
453     fn filter_map_ok(v: Vec<Result<u8, char>>) -> () {
454         test_specializations(&v.into_iter().filter_map_ok(|i| if i < 20 { Some(i * 2) } else { None }));
455     }
456 
457     // `SmallIter2<u8>` because `Vec<u8>` is too slow and we get bad coverage from a singleton like Option<u8>
458     fn flatten_ok(v: Vec<Result<SmallIter2<u8>, char>>) -> () {
459         let it = v.into_iter().flatten_ok();
460         test_specializations(&it);
461         test_double_ended_specializations(&it);
462     }
463 }
464 
465 quickcheck! {
466     // TODO Replace this function by a normal call to test_specializations
467     fn process_results(v: Vec<Result<u8, u8>>) -> () {
468         helper(v.iter().copied());
469         helper(v.iter().copied().filter(Result::is_ok));
470 
471         fn helper(it: impl DoubleEndedIterator<Item = Result<u8, u8>> + Clone) {
472             macro_rules! check_results_specialized {
473                 ($src:expr, |$it:pat| $closure:expr) => {
474                     assert_eq!(
475                         itertools::process_results($src.clone(), |$it| $closure),
476                         itertools::process_results($src.clone(), |i| {
477                             let $it = Unspecialized(i);
478                             $closure
479                         }),
480                     )
481                 }
482             }
483 
484             check_results_specialized!(it, |i| i.count());
485             check_results_specialized!(it, |i| i.last());
486             check_results_specialized!(it, |i| i.collect::<Vec<_>>());
487             check_results_specialized!(it, |i| i.rev().collect::<Vec<_>>());
488             check_results_specialized!(it, |i| {
489                 let mut parameters_from_fold = vec![];
490                 let fold_result = i.fold(vec![], |mut acc, v| {
491                     parameters_from_fold.push((acc.clone(), v));
492                     acc.push(v);
493                     acc
494                 });
495                 (parameters_from_fold, fold_result)
496             });
497             check_results_specialized!(it, |i| {
498                 let mut parameters_from_rfold = vec![];
499                 let rfold_result = i.rfold(vec![], |mut acc, v| {
500                     parameters_from_rfold.push((acc.clone(), v));
501                     acc.push(v);
502                     acc
503                 });
504                 (parameters_from_rfold, rfold_result)
505             });
506             check_results_specialized!(it, |mut i| {
507                 let mut parameters_from_all = vec![];
508                 let first = i.next();
509                 let all_result = i.all(|x| {
510                     parameters_from_all.push(x);
511                     Some(x)==first
512                 });
513                 (parameters_from_all, all_result)
514             });
515             let size = it.clone().count();
516             for n in 0..size + 2 {
517                 check_results_specialized!(it, |mut i| i.nth(n));
518             }
519             for n in 0..size + 2 {
520                 check_results_specialized!(it, |mut i| i.nth_back(n));
521             }
522         }
523     }
524 }
525 
526 /// Like `VecIntoIter<T>` with maximum 2 elements.
527 #[derive(Debug, Clone, Default)]
528 enum SmallIter2<T> {
529     #[default]
530     Zero,
531     One(T),
532     Two(T, T),
533 }
534 
535 impl<T: Arbitrary> Arbitrary for SmallIter2<T> {
arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self536     fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
537         match g.gen_range(0u8, 3) {
538             0 => Self::Zero,
539             1 => Self::One(T::arbitrary(g)),
540             2 => Self::Two(T::arbitrary(g), T::arbitrary(g)),
541             _ => unreachable!(),
542         }
543     }
544     // maybe implement shrink too, maybe not
545 }
546 
547 impl<T> Iterator for SmallIter2<T> {
548     type Item = T;
549 
next(&mut self) -> Option<Self::Item>550     fn next(&mut self) -> Option<Self::Item> {
551         match std::mem::take(self) {
552             Self::Zero => None,
553             Self::One(val) => Some(val),
554             Self::Two(val, second) => {
555                 *self = Self::One(second);
556                 Some(val)
557             }
558         }
559     }
560 
size_hint(&self) -> (usize, Option<usize>)561     fn size_hint(&self) -> (usize, Option<usize>) {
562         let len = match self {
563             Self::Zero => 0,
564             Self::One(_) => 1,
565             Self::Two(_, _) => 2,
566         };
567         (len, Some(len))
568     }
569 }
570 
571 impl<T> DoubleEndedIterator for SmallIter2<T> {
next_back(&mut self) -> Option<Self::Item>572     fn next_back(&mut self) -> Option<Self::Item> {
573         match std::mem::take(self) {
574             Self::Zero => None,
575             Self::One(val) => Some(val),
576             Self::Two(first, val) => {
577                 *self = Self::One(first);
578                 Some(val)
579             }
580         }
581     }
582 }
583