1 //! The purpose of these tests is to cover corner cases of iterators
2 //! and adaptors.
3 //!
4 //! In particular we test the tedious size_hint and exact size correctness.
5 
6 #![allow(deprecated, unstable_name_collisions)]
7 
8 use itertools::free::{
9     cloned, enumerate, multipeek, peek_nth, put_back, put_back_n, rciter, zip, zip_eq,
10 };
11 use itertools::Itertools;
12 use itertools::{iproduct, izip, multizip, EitherOrBoth};
13 use quickcheck as qc;
14 use std::cmp::{max, min, Ordering};
15 use std::collections::{HashMap, HashSet};
16 use std::default::Default;
17 use std::num::Wrapping;
18 use std::ops::Range;
19 
20 use quickcheck::TestResult;
21 use rand::seq::SliceRandom;
22 use rand::Rng;
23 
24 /// Trait for size hint modifier types
25 trait HintKind: Copy + Send + qc::Arbitrary {
loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>)26     fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>);
27 }
28 
29 /// Exact size hint variant that leaves hints unchanged
30 #[derive(Clone, Copy, Debug)]
31 struct Exact {}
32 
33 impl HintKind for Exact {
loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>)34     fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) {
35         org_hint
36     }
37 }
38 
39 impl qc::Arbitrary for Exact {
arbitrary<G: qc::Gen>(_: &mut G) -> Self40     fn arbitrary<G: qc::Gen>(_: &mut G) -> Self {
41         Self {}
42     }
43 }
44 
45 /// Inexact size hint variant to simulate imprecise (but valid) size hints
46 ///
47 /// Will always decrease the lower bound and increase the upper bound
48 /// of the size hint by set amounts.
49 #[derive(Clone, Copy, Debug)]
50 struct Inexact {
51     underestimate: usize,
52     overestimate: usize,
53 }
54 
55 impl HintKind for Inexact {
loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>)56     fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) {
57         let (org_lower, org_upper) = org_hint;
58         (
59             org_lower.saturating_sub(self.underestimate),
60             org_upper.and_then(move |x| x.checked_add(self.overestimate)),
61         )
62     }
63 }
64 
65 impl qc::Arbitrary for Inexact {
arbitrary<G: qc::Gen>(g: &mut G) -> Self66     fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
67         let ue_value = usize::arbitrary(g);
68         let oe_value = usize::arbitrary(g);
69         // Compensate for quickcheck using extreme values too rarely
70         let ue_choices = &[0, ue_value, usize::MAX];
71         let oe_choices = &[0, oe_value, usize::MAX];
72         Self {
73             underestimate: *ue_choices.choose(g).unwrap(),
74             overestimate: *oe_choices.choose(g).unwrap(),
75         }
76     }
77 
shrink(&self) -> Box<dyn Iterator<Item = Self>>78     fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
79         let underestimate_value = self.underestimate;
80         let overestimate_value = self.overestimate;
81         Box::new(underestimate_value.shrink().flat_map(move |ue_value| {
82             overestimate_value.shrink().map(move |oe_value| Self {
83                 underestimate: ue_value,
84                 overestimate: oe_value,
85             })
86         }))
87     }
88 }
89 
90 /// Our base iterator that we can impl Arbitrary for
91 ///
92 /// By default we'll return inexact bounds estimates for size_hint
93 /// to make tests harder to pass.
94 ///
95 /// NOTE: Iter is tricky and is not fused, to help catch bugs.
96 /// At the end it will return None once, then return Some(0),
97 /// then return None again.
98 #[derive(Clone, Debug)]
99 struct Iter<T, SK: HintKind = Inexact> {
100     iterator: Range<T>,
101     // fuse/done flag
102     fuse_flag: i32,
103     hint_kind: SK,
104 }
105 
106 impl<T, HK> Iter<T, HK>
107 where
108     HK: HintKind,
109 {
new(it: Range<T>, hint_kind: HK) -> Self110     fn new(it: Range<T>, hint_kind: HK) -> Self {
111         Self {
112             iterator: it,
113             fuse_flag: 0,
114             hint_kind,
115         }
116     }
117 }
118 
119 impl<T, HK> Iterator for Iter<T, HK>
120 where
121     Range<T>: Iterator,
122     <Range<T> as Iterator>::Item: Default,
123     HK: HintKind,
124 {
125     type Item = <Range<T> as Iterator>::Item;
126 
next(&mut self) -> Option<Self::Item>127     fn next(&mut self) -> Option<Self::Item> {
128         let elt = self.iterator.next();
129         if elt.is_none() {
130             self.fuse_flag += 1;
131             // check fuse flag
132             if self.fuse_flag == 2 {
133                 return Some(Default::default());
134             }
135         }
136         elt
137     }
138 
size_hint(&self) -> (usize, Option<usize>)139     fn size_hint(&self) -> (usize, Option<usize>) {
140         let org_hint = self.iterator.size_hint();
141         self.hint_kind.loosen_bounds(org_hint)
142     }
143 }
144 
145 impl<T, HK> DoubleEndedIterator for Iter<T, HK>
146 where
147     Range<T>: DoubleEndedIterator,
148     <Range<T> as Iterator>::Item: Default,
149     HK: HintKind,
150 {
next_back(&mut self) -> Option<Self::Item>151     fn next_back(&mut self) -> Option<Self::Item> {
152         self.iterator.next_back()
153     }
154 }
155 
156 impl<T> ExactSizeIterator for Iter<T, Exact>
157 where
158     Range<T>: ExactSizeIterator,
159     <Range<T> as Iterator>::Item: Default,
160 {
161 }
162 
163 impl<T, HK> qc::Arbitrary for Iter<T, HK>
164 where
165     T: qc::Arbitrary,
166     HK: HintKind,
167 {
arbitrary<G: qc::Gen>(g: &mut G) -> Self168     fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
169         Self::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g))
170     }
171 
shrink(&self) -> Box<dyn Iterator<Item = Self>>172     fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
173         let r = self.iterator.clone();
174         let hint_kind = self.hint_kind;
175         Box::new(r.start.shrink().flat_map(move |a| {
176             r.end
177                 .shrink()
178                 .map(move |b| Self::new(a.clone()..b, hint_kind))
179         }))
180     }
181 }
182 
183 /// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are
184 /// increased or decreased linearly on each iteration.
185 #[derive(Clone, Debug)]
186 struct ShiftRange<HK = Inexact> {
187     range_start: i32,
188     range_end: i32,
189     start_step: i32,
190     end_step: i32,
191     iter_count: u32,
192     hint_kind: HK,
193 }
194 
195 impl<HK> Iterator for ShiftRange<HK>
196 where
197     HK: HintKind,
198 {
199     type Item = Iter<i32, HK>;
200 
next(&mut self) -> Option<Self::Item>201     fn next(&mut self) -> Option<Self::Item> {
202         if self.iter_count == 0 {
203             return None;
204         }
205 
206         let iter = Iter::new(self.range_start..self.range_end, self.hint_kind);
207 
208         self.range_start += self.start_step;
209         self.range_end += self.end_step;
210         self.iter_count -= 1;
211 
212         Some(iter)
213     }
214 }
215 
216 impl ExactSizeIterator for ShiftRange<Exact> {}
217 
218 impl<HK> qc::Arbitrary for ShiftRange<HK>
219 where
220     HK: HintKind,
221 {
arbitrary<G: qc::Gen>(g: &mut G) -> Self222     fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
223         const MAX_STARTING_RANGE_DIFF: i32 = 32;
224         const MAX_STEP_MODULO: i32 = 8;
225         const MAX_ITER_COUNT: u32 = 3;
226 
227         let range_start = qc::Arbitrary::arbitrary(g);
228         let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1);
229         let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1);
230         let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1);
231         let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1);
232         let hint_kind = qc::Arbitrary::arbitrary(g);
233 
234         Self {
235             range_start,
236             range_end,
237             start_step,
238             end_step,
239             iter_count,
240             hint_kind,
241         }
242     }
243 }
244 
correct_count<I, F>(get_it: F) -> bool where I: Iterator, F: Fn() -> I,245 fn correct_count<I, F>(get_it: F) -> bool
246 where
247     I: Iterator,
248     F: Fn() -> I,
249 {
250     let mut counts = vec![get_it().count()];
251 
252     'outer: loop {
253         let mut it = get_it();
254 
255         for _ in 0..(counts.len() - 1) {
256             #[allow(clippy::manual_assert)]
257             if it.next().is_none() {
258                 panic!("Iterator shouldn't be finished, may not be deterministic");
259             }
260         }
261 
262         if it.next().is_none() {
263             break 'outer;
264         }
265 
266         counts.push(it.count());
267     }
268 
269     let total_actual_count = counts.len() - 1;
270 
271     for (i, returned_count) in counts.into_iter().enumerate() {
272         let actual_count = total_actual_count - i;
273         if actual_count != returned_count {
274             println!(
275                 "Total iterations: {} True count: {} returned count: {}",
276                 i, actual_count, returned_count
277             );
278 
279             return false;
280         }
281     }
282 
283     true
284 }
285 
correct_size_hint<I: Iterator>(mut it: I) -> bool286 fn correct_size_hint<I: Iterator>(mut it: I) -> bool {
287     // record size hint at each iteration
288     let initial_hint = it.size_hint();
289     let mut hints = Vec::with_capacity(initial_hint.0 + 1);
290     hints.push(initial_hint);
291     while let Some(_) = it.next() {
292         hints.push(it.size_hint())
293     }
294 
295     let mut true_count = hints.len(); // start off +1 too much
296 
297     // check all the size hints
298     for &(low, hi) in &hints {
299         true_count -= 1;
300         if low > true_count || (hi.is_some() && hi.unwrap() < true_count) {
301             println!("True size: {:?}, size hint: {:?}", true_count, (low, hi));
302             //println!("All hints: {:?}", hints);
303             return false;
304         }
305     }
306     true
307 }
308 
exact_size<I: ExactSizeIterator>(mut it: I) -> bool309 fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
310     // check every iteration
311     let (mut low, mut hi) = it.size_hint();
312     if Some(low) != hi {
313         return false;
314     }
315     while let Some(_) = it.next() {
316         let (xlow, xhi) = it.size_hint();
317         if low != xlow + 1 {
318             return false;
319         }
320         low = xlow;
321         hi = xhi;
322         if Some(low) != hi {
323             return false;
324         }
325     }
326     let (low, hi) = it.size_hint();
327     low == 0 && hi == Some(0)
328 }
329 
330 // Exact size for this case, without ExactSizeIterator
exact_size_for_this<I: Iterator>(mut it: I) -> bool331 fn exact_size_for_this<I: Iterator>(mut it: I) -> bool {
332     // check every iteration
333     let (mut low, mut hi) = it.size_hint();
334     if Some(low) != hi {
335         return false;
336     }
337     while let Some(_) = it.next() {
338         let (xlow, xhi) = it.size_hint();
339         if low != xlow + 1 {
340             return false;
341         }
342         low = xlow;
343         hi = xhi;
344         if Some(low) != hi {
345             return false;
346         }
347     }
348     let (low, hi) = it.size_hint();
349     low == 0 && hi == Some(0)
350 }
351 
352 /*
353  * NOTE: Range<i8> is broken!
354  * (all signed ranges are)
355 #[quickcheck]
356 fn size_range_i8(a: Iter<i8>) -> bool {
357     exact_size(a)
358 }
359 
360 #[quickcheck]
361 fn size_range_i16(a: Iter<i16>) -> bool {
362     exact_size(a)
363 }
364 
365 #[quickcheck]
366 fn size_range_u8(a: Iter<u8>) -> bool {
367     exact_size(a)
368 }
369  */
370 
371 macro_rules! quickcheck {
372     // accept several property function definitions
373     // The property functions can use pattern matching and `mut` as usual
374     // in the function arguments, but the functions can not be generic.
375     {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => (
376         $(
377             #[test]
378             $(#$attr)*
379             fn $fn_name() {
380                 fn prop($($arg)*) -> $ret {
381                     $($code)*
382                 }
383                 ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*));
384             }
385         )*
386     );
387     // parse argument list (with patterns allowed) into prop as fn(_, _) -> _
388     (@fn $f:ident [$($t:tt)*]) => {
389         $f as fn($($t),*) -> _
390     };
391     (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => {
392         quickcheck!(@fn $f [$($p)* _] $($tail)*)
393     };
394     (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => {
395         quickcheck!(@fn $f [$($p)*] $($tail)*)
396     };
397 }
398 
399 quickcheck! {
400 
401     fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
402         correct_size_hint(a.cartesian_product(b))
403     }
404     fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
405         correct_size_hint(iproduct!(a, b, c))
406     }
407 
408     fn correct_cartesian_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>,
409                                   take_manual: usize) -> ()
410     {
411         // test correctness of iproduct through regular iteration (take)
412         // and through fold.
413         let ac = a.clone();
414         let br = &b.clone();
415         let cr = &c.clone();
416         let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect();
417         let mut product_iter = iproduct!(a, b, c);
418         let mut actual = Vec::new();
419 
420         actual.extend((&mut product_iter).take(take_manual));
421         if actual.len() == take_manual {
422             product_iter.fold((), |(), elt| actual.push(elt));
423         }
424         assert_eq!(answer, actual);
425     }
426 
427     fn size_multi_product(a: ShiftRange) -> bool {
428         correct_size_hint(a.multi_cartesian_product())
429     }
430     fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () {
431         // Fix no. of iterators at 3
432         let a = ShiftRange { iter_count: 3, ..a };
433 
434         // test correctness of MultiProduct through regular iteration (take)
435         // and through fold.
436         let mut iters = a.clone();
437         let i0 = iters.next().unwrap();
438         let i1r = &iters.next().unwrap();
439         let i2r = &iters.next().unwrap();
440         let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect();
441         let mut multi_product = a.clone().multi_cartesian_product();
442         let mut actual = Vec::new();
443 
444         actual.extend((&mut multi_product).take(take_manual));
445         if actual.len() == take_manual {
446             multi_product.fold((), |(), elt| actual.push(elt));
447         }
448         assert_eq!(answer, actual);
449 
450         assert_eq!(answer.into_iter().last(), a.multi_cartesian_product().last());
451     }
452 
453     fn correct_empty_multi_product() -> () {
454         let empty = Vec::<std::vec::IntoIter<i32>>::new().into_iter().multi_cartesian_product();
455         assert!(correct_size_hint(empty.clone()));
456         itertools::assert_equal(empty, std::iter::once(Vec::new()))
457     }
458 
459     fn size_multipeek(a: Iter<u16, Exact>, s: u8) -> bool {
460         let mut it = multipeek(a);
461         // peek a few times
462         for _ in 0..s {
463             it.peek();
464         }
465         exact_size(it)
466     }
467 
468     fn size_peek_nth(a: Iter<u16, Exact>, s: u8) -> bool {
469         let mut it = peek_nth(a);
470         // peek a few times
471         for n in 0..s {
472             it.peek_nth(n as usize);
473         }
474         exact_size(it)
475     }
476 
477     fn equal_merge(mut a: Vec<i16>, mut b: Vec<i16>) -> bool {
478         a.sort();
479         b.sort();
480         let mut merged = a.clone();
481         merged.extend(b.iter().cloned());
482         merged.sort();
483         itertools::equal(&merged, a.iter().merge(&b))
484     }
485     fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
486         correct_size_hint(a.merge(b))
487     }
488     fn size_zip(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool {
489         let filt = a.clone().dedup();
490         correct_size_hint(multizip((filt, b.clone(), c.clone()))) &&
491             exact_size(multizip((a, b, c)))
492     }
493     fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool {
494         let rc = rciter(a);
495         correct_size_hint(multizip((&rc, &rc, b)))
496     }
497 
498     fn size_zip_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool {
499         let filt = a.clone().dedup();
500         correct_size_hint(izip!(filt, b.clone(), c.clone())) &&
501             exact_size(izip!(a, b, c))
502     }
503     fn equal_kmerge(mut a: Vec<i16>, mut b: Vec<i16>, mut c: Vec<i16>) -> bool {
504         use itertools::free::kmerge;
505         a.sort();
506         b.sort();
507         c.sort();
508         let mut merged = a.clone();
509         merged.extend(b.iter().cloned());
510         merged.extend(c.iter().cloned());
511         merged.sort();
512         itertools::equal(merged.into_iter(), kmerge(vec![a, b, c]))
513     }
514 
515     // Any number of input iterators
516     fn equal_kmerge_2(mut inputs: Vec<Vec<i16>>) -> bool {
517         use itertools::free::kmerge;
518         // sort the inputs
519         for input in &mut inputs {
520             input.sort();
521         }
522         let mut merged = inputs.concat();
523         merged.sort();
524         itertools::equal(merged.into_iter(), kmerge(inputs))
525     }
526 
527     // Any number of input iterators
528     fn equal_kmerge_by_ge(mut inputs: Vec<Vec<i16>>) -> bool {
529         // sort the inputs
530         for input in &mut inputs {
531             input.sort();
532             input.reverse();
533         }
534         let mut merged = inputs.concat();
535         merged.sort();
536         merged.reverse();
537         itertools::equal(merged.into_iter(),
538                          inputs.into_iter().kmerge_by(|x, y| x >= y))
539     }
540 
541     // Any number of input iterators
542     fn equal_kmerge_by_lt(mut inputs: Vec<Vec<i16>>) -> bool {
543         // sort the inputs
544         for input in &mut inputs {
545             input.sort();
546         }
547         let mut merged = inputs.concat();
548         merged.sort();
549         itertools::equal(merged.into_iter(),
550                          inputs.into_iter().kmerge_by(|x, y| x < y))
551     }
552 
553     // Any number of input iterators
554     fn equal_kmerge_by_le(mut inputs: Vec<Vec<i16>>) -> bool {
555         // sort the inputs
556         for input in &mut inputs {
557             input.sort();
558         }
559         let mut merged = inputs.concat();
560         merged.sort();
561         itertools::equal(merged.into_iter(),
562                          inputs.into_iter().kmerge_by(|x, y| x <= y))
563     }
564     fn size_kmerge(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
565         use itertools::free::kmerge;
566         correct_size_hint(kmerge(vec![a, b, c]))
567     }
568     fn equal_zip_eq(a: Vec<i32>, b: Vec<i32>) -> bool {
569         let len = std::cmp::min(a.len(), b.len());
570         let a = &a[..len];
571         let b = &b[..len];
572         itertools::equal(zip_eq(a, b), zip(a, b))
573     }
574 
575     #[should_panic]
576     fn zip_eq_panics(a: Vec<u8>, b: Vec<u8>) -> TestResult {
577         if a.len() == b.len() { return TestResult::discard(); }
578         zip_eq(a.iter(), b.iter()).for_each(|_| {});
579         TestResult::passed() // won't come here
580     }
581 
582     fn equal_positions(a: Vec<i32>) -> bool {
583         let with_pos = a.iter().positions(|v| v % 2 == 0);
584         let without = a.iter().enumerate().filter(|(_, v)| *v % 2 == 0).map(|(i, _)| i);
585         itertools::equal(with_pos.clone(), without.clone())
586             && itertools::equal(with_pos.rev(), without.rev())
587     }
588     fn size_zip_longest(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool {
589         let filt = a.clone().dedup();
590         let filt2 = b.clone().dedup();
591         correct_size_hint(filt.zip_longest(b.clone())) &&
592         correct_size_hint(a.clone().zip_longest(filt2)) &&
593             exact_size(a.zip_longest(b))
594     }
595     fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
596         let it = a.clone().zip_longest(b.clone());
597         let jt = a.clone().zip_longest(b.clone());
598         itertools::equal(a,
599                          it.filter_map(|elt| match elt {
600                              EitherOrBoth::Both(x, _) => Some(x),
601                              EitherOrBoth::Left(x) => Some(x),
602                              _ => None,
603                          }
604                          ))
605             &&
606         itertools::equal(b,
607                          jt.filter_map(|elt| match elt {
608                              EitherOrBoth::Both(_, y) => Some(y),
609                              EitherOrBoth::Right(y) => Some(y),
610                              _ => None,
611                          }
612                          ))
613     }
614     fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
615         correct_size_hint(a.interleave(b))
616     }
617     fn exact_interleave(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool {
618         exact_size_for_this(a.interleave(b))
619     }
620     fn size_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool {
621         correct_size_hint(a.interleave_shortest(b))
622     }
623     fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool {
624         exact_size_for_this(a.iter().interleave_shortest(&b))
625     }
626     fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
627         correct_size_hint(a.intersperse(x))
628     }
629     fn equal_intersperse(a: Vec<i32>, x: i32) -> bool {
630         let mut inter = false;
631         let mut i = 0;
632         for elt in a.iter().cloned().intersperse(x) {
633             if inter {
634                 if elt != x { return false }
635             } else {
636                 if elt != a[i] { return false }
637                 i += 1;
638             }
639             inter = !inter;
640         }
641         true
642     }
643 
644     fn equal_combinations_2(a: Vec<u8>) -> bool {
645         let mut v = Vec::new();
646         for (i, x) in enumerate(&a) {
647             for y in &a[i + 1..] {
648                 v.push((x, y));
649             }
650         }
651         itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v)
652     }
653 
654     fn collect_tuple_matches_size(a: Iter<i16>) -> bool {
655         let size = a.clone().count();
656         a.collect_tuple::<(_, _, _)>().is_some() == (size == 3)
657     }
658 
659     fn correct_permutations(vals: HashSet<i32>, k: usize) -> () {
660         // Test permutations only on iterators of distinct integers, to prevent
661         // false positives.
662 
663         const MAX_N: usize = 5;
664 
665         let n = min(vals.len(), MAX_N);
666         let vals: HashSet<i32> = vals.into_iter().take(n).collect();
667 
668         let perms = vals.iter().permutations(k);
669 
670         let mut actual = HashSet::new();
671 
672         for perm in perms {
673             assert_eq!(perm.len(), k);
674 
675             let all_items_valid = perm.iter().all(|p| vals.contains(p));
676             assert!(all_items_valid, "perm contains value not from input: {:?}", perm);
677 
678             // Check that all perm items are distinct
679             let distinct_len = {
680                 let perm_set: HashSet<_> = perm.iter().collect();
681                 perm_set.len()
682             };
683             assert_eq!(perm.len(), distinct_len);
684 
685             // Check that the perm is new
686             assert!(actual.insert(perm.clone()), "perm already encountered: {:?}", perm);
687         }
688     }
689 
690     fn permutations_lexic_order(a: usize, b: usize) -> () {
691         let a = a % 6;
692         let b = b % 6;
693 
694         let n = max(a, b);
695         let k = min (a, b);
696 
697         let expected_first: Vec<usize> = (0..k).collect();
698         let expected_last: Vec<usize> = ((n - k)..n).rev().collect();
699 
700         let mut perms = (0..n).permutations(k);
701 
702         let mut curr_perm = match perms.next() {
703             Some(p) => p,
704             None => { return; }
705         };
706 
707         assert_eq!(expected_first, curr_perm);
708 
709         for next_perm in perms {
710             assert!(
711                 next_perm > curr_perm,
712                 "next perm isn't greater-than current; next_perm={:?} curr_perm={:?} n={}",
713                 next_perm, curr_perm, n
714             );
715 
716             curr_perm = next_perm;
717         }
718 
719         assert_eq!(expected_last, curr_perm);
720 
721     }
722 
723     fn permutations_count(n: usize, k: usize) -> bool {
724         let n = n % 6;
725 
726         correct_count(|| (0..n).permutations(k))
727     }
728 
729     fn permutations_size(a: Iter<i32>, k: usize) -> bool {
730         correct_size_hint(a.take(5).permutations(k))
731     }
732 
733     fn permutations_k0_yields_once(n: usize) -> () {
734         let k = 0;
735         let expected: Vec<Vec<usize>> = vec![vec![]];
736         let actual = (0..n).permutations(k).collect_vec();
737 
738         assert_eq!(expected, actual);
739     }
740 }
741 
742 quickcheck! {
743     fn correct_peek_nth(mut a: Vec<u16>) -> () {
744         let mut it = peek_nth(a.clone());
745         for start_pos in 0..a.len() + 2 {
746             for real_idx in start_pos..a.len() + 2 {
747                 let peek_idx = real_idx - start_pos;
748                 assert_eq!(it.peek_nth(peek_idx), a.get(real_idx));
749                 assert_eq!(it.peek_nth_mut(peek_idx), a.get_mut(real_idx));
750             }
751             assert_eq!(it.next(), a.get(start_pos).copied());
752         }
753     }
754 
755     fn peek_nth_mut_replace(a: Vec<u16>, b: Vec<u16>) -> () {
756         let mut it = peek_nth(a.iter());
757         for (i, m) in b.iter().enumerate().take(a.len().min(b.len())) {
758             *it.peek_nth_mut(i).unwrap() = m;
759         }
760         for (i, m) in a.iter().enumerate() {
761              assert_eq!(it.next().unwrap(), b.get(i).unwrap_or(m));
762         }
763         assert_eq!(it.next(), None);
764         assert_eq!(it.next(), None);
765     }
766 
767     fn peek_nth_next_if(a: Vec<u8>) -> () {
768         let mut it = peek_nth(a.clone());
769         for (idx, mut value) in a.iter().copied().enumerate() {
770             let should_be_none = it.next_if(|x| x != &value);
771             assert_eq!(should_be_none, None);
772             if value % 5 == 0 {
773                 // Sometimes, peek up to 3 further.
774                 let n = value as usize % 3;
775                 let nth = it.peek_nth(n);
776                 assert_eq!(nth, a.get(idx + n));
777             } else if value % 5 == 1 {
778                 // Sometimes, peek next element mutably.
779                 if let Some(v) = it.peek_mut() {
780                     *v = v.wrapping_sub(1);
781                     let should_be_none = it.next_if_eq(&value);
782                     assert_eq!(should_be_none, None);
783                     value = value.wrapping_sub(1);
784                 }
785             }
786             let eq = it.next_if_eq(&value);
787             assert_eq!(eq, Some(value));
788         }
789     }
790 }
791 
792 quickcheck! {
793     fn dedup_via_coalesce(a: Vec<i32>) -> bool {
794         let mut b = a.clone();
795         b.dedup();
796         itertools::equal(
797             &b,
798             a
799                 .iter()
800                 .coalesce(|x, y| {
801                     if x==y {
802                         Ok(x)
803                     } else {
804                         Err((x, y))
805                     }
806                 })
807                 .fold(vec![], |mut v, n| {
808                     v.push(n);
809                     v
810                 })
811         )
812     }
813 }
814 
815 quickcheck! {
816     fn equal_dedup(a: Vec<i32>) -> bool {
817         let mut b = a.clone();
818         b.dedup();
819         itertools::equal(&b, a.iter().dedup())
820     }
821 }
822 
823 quickcheck! {
824     fn equal_dedup_by(a: Vec<(i32, i32)>) -> bool {
825         let mut b = a.clone();
826         b.dedup_by(|x, y| x.0==y.0);
827         itertools::equal(&b, a.iter().dedup_by(|x, y| x.0==y.0))
828     }
829 }
830 
831 quickcheck! {
832     fn size_dedup(a: Vec<i32>) -> bool {
833         correct_size_hint(a.iter().dedup())
834     }
835 }
836 
837 quickcheck! {
838     fn size_dedup_by(a: Vec<(i32, i32)>) -> bool {
839         correct_size_hint(a.iter().dedup_by(|x, y| x.0==y.0))
840     }
841 }
842 
843 quickcheck! {
844     fn exact_repeatn((n, x): (usize, i32)) -> bool {
845         let it = itertools::repeat_n(x, n);
846         exact_size(it)
847     }
848 }
849 
850 quickcheck! {
851     fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool {
852         let mut it = put_back(a.into_iter());
853         if let Some(t) = x {
854             it.put_back(t);
855         }
856         correct_size_hint(it)
857     }
858 }
859 
860 quickcheck! {
861     fn size_put_backn(a: Vec<u8>, b: Vec<u8>) -> bool {
862         let mut it = put_back_n(a.into_iter());
863         for elt in b {
864             it.put_back(elt)
865         }
866         correct_size_hint(it)
867     }
868 }
869 
870 quickcheck! {
871     fn merge_join_by_ordering_vs_bool(a: Vec<u8>, b: Vec<u8>) -> bool {
872         use either::Either;
873         use itertools::free::merge_join_by;
874         let mut has_equal = false;
875         let it_ord = merge_join_by(a.clone(), b.clone(), Ord::cmp).flat_map(|v| match v {
876             EitherOrBoth::Both(l, r) => {
877                 has_equal = true;
878                 vec![Either::Left(l), Either::Right(r)]
879             }
880             EitherOrBoth::Left(l) => vec![Either::Left(l)],
881             EitherOrBoth::Right(r) => vec![Either::Right(r)],
882         });
883         let it_bool = merge_join_by(a, b, PartialOrd::le);
884         itertools::equal(it_ord, it_bool) || has_equal
885     }
886     fn merge_join_by_bool_unwrapped_is_merge_by(a: Vec<u8>, b: Vec<u8>) -> bool {
887         use either::Either;
888         use itertools::free::merge_join_by;
889         let it = a.clone().into_iter().merge_by(b.clone(), PartialOrd::ge);
890         let it_join = merge_join_by(a, b, PartialOrd::ge).map(Either::into_inner);
891         itertools::equal(it, it_join)
892     }
893 }
894 
895 quickcheck! {
896     fn size_tee(a: Vec<u8>) -> bool {
897         let (mut t1, mut t2) = a.iter().tee();
898         t1.next();
899         t1.next();
900         t2.next();
901         exact_size(t1) && exact_size(t2)
902     }
903 }
904 
905 quickcheck! {
906     fn size_tee_2(a: Vec<u8>) -> bool {
907         let (mut t1, mut t2) = a.iter().dedup().tee();
908         t1.next();
909         t1.next();
910         t2.next();
911         correct_size_hint(t1) && correct_size_hint(t2)
912     }
913 }
914 
915 quickcheck! {
916     fn size_take_while_ref(a: Vec<u8>, stop: u8) -> bool {
917         correct_size_hint(a.iter().take_while_ref(|x| **x != stop))
918     }
919 }
920 
921 quickcheck! {
922     fn equal_partition(a: Vec<i32>) -> bool {
923         let mut a = a;
924         let mut ap = a.clone();
925         let split_index = itertools::partition(&mut ap, |x| *x >= 0);
926         let parted = (0..split_index).all(|i| ap[i] >= 0) &&
927             (split_index..a.len()).all(|i| ap[i] < 0);
928 
929         a.sort();
930         ap.sort();
931         parted && (a == ap)
932     }
933 }
934 
935 quickcheck! {
936     fn size_combinations(a: Iter<i16>) -> bool {
937         let it = a.clone().tuple_combinations::<(_, _)>();
938         correct_size_hint(it.clone()) && it.count() == binomial(a.count(), 2)
939     }
940 
941     fn exact_size_combinations_1(a: Vec<u8>) -> bool {
942         let it = a.iter().tuple_combinations::<(_,)>();
943         exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 1)
944     }
945     fn exact_size_combinations_2(a: Vec<u8>) -> bool {
946         let it = a.iter().tuple_combinations::<(_, _)>();
947         exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 2)
948     }
949     fn exact_size_combinations_3(mut a: Vec<u8>) -> bool {
950         a.truncate(15);
951         let it = a.iter().tuple_combinations::<(_, _, _)>();
952         exact_size_for_this(it.clone()) && it.count() == binomial(a.len(), 3)
953     }
954 }
955 
binomial(n: usize, k: usize) -> usize956 fn binomial(n: usize, k: usize) -> usize {
957     if k > n {
958         0
959     } else {
960         (n - k + 1..=n).product::<usize>() / (1..=k).product::<usize>()
961     }
962 }
963 
964 quickcheck! {
965     fn equal_combinations(it: Iter<i16>) -> bool {
966         let values = it.clone().collect_vec();
967         let mut cmb = it.tuple_combinations();
968         for i in 0..values.len() {
969             for j in i+1..values.len() {
970                 let pair = (values[i], values[j]);
971                 if pair != cmb.next().unwrap() {
972                     return false;
973                 }
974             }
975         }
976         cmb.next().is_none()
977     }
978 }
979 
980 quickcheck! {
981     fn size_pad_tail(it: Iter<i8>, pad: u8) -> bool {
982         correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) &&
983             correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0))
984     }
985 }
986 
987 quickcheck! {
988     fn size_pad_tail2(it: Iter<i8, Exact>, pad: u8) -> bool {
989         exact_size(it.pad_using(pad as usize, |_| 0))
990     }
991 }
992 
993 quickcheck! {
994     fn size_powerset(it: Iter<u8, Exact>) -> bool {
995         // Powerset cardinality gets large very quickly, limit input to keep test fast.
996         correct_size_hint(it.take(12).powerset())
997     }
998 }
999 
1000 quickcheck! {
1001     fn size_duplicates(it: Iter<i8>) -> bool {
1002         correct_size_hint(it.duplicates())
1003     }
1004 }
1005 
1006 quickcheck! {
1007     fn size_unique(it: Iter<i8>) -> bool {
1008         correct_size_hint(it.unique())
1009     }
1010 
1011     fn count_unique(it: Vec<i8>, take_first: u8) -> () {
1012         let answer = {
1013             let mut v = it.clone();
1014             v.sort(); v.dedup();
1015             v.len()
1016         };
1017         let mut iter = cloned(&it).unique();
1018         let first_count = (&mut iter).take(take_first as usize).count();
1019         let rest_count = iter.count();
1020         assert_eq!(answer, first_count + rest_count);
1021     }
1022 }
1023 
1024 quickcheck! {
1025     fn fuzz_chunk_by_lazy_1(it: Iter<u8>) -> bool {
1026         let jt = it.clone();
1027         let chunks = it.chunk_by(|k| *k);
1028         itertools::equal(jt, chunks.into_iter().flat_map(|(_, x)| x))
1029     }
1030 }
1031 
1032 quickcheck! {
1033     fn fuzz_chunk_by_lazy_2(data: Vec<u8>) -> bool {
1034         let chunks = data.iter().chunk_by(|k| *k / 10);
1035         let res = itertools::equal(data.iter(), chunks.into_iter().flat_map(|(_, x)| x));
1036         res
1037     }
1038 }
1039 
1040 quickcheck! {
1041     fn fuzz_chunk_by_lazy_3(data: Vec<u8>) -> bool {
1042         let grouper = data.iter().chunk_by(|k| *k / 10);
1043         let chunks = grouper.into_iter().collect_vec();
1044         let res = itertools::equal(data.iter(), chunks.into_iter().flat_map(|(_, x)| x));
1045         res
1046     }
1047 }
1048 
1049 quickcheck! {
1050     fn fuzz_chunk_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool {
1051         let grouper = data.iter().chunk_by(|k| *k / 3);
1052         let mut chunks1 = grouper.into_iter();
1053         let mut chunks2 = grouper.into_iter();
1054         let mut elts = Vec::<&u8>::new();
1055         let mut old_chunks = Vec::new();
1056 
1057         let tup1 = |(_, b)| b;
1058         for &(ord, consume_now) in &order {
1059             let iter = &mut [&mut chunks1, &mut chunks2][ord as usize];
1060             match iter.next() {
1061                 Some((_, gr)) => if consume_now {
1062                     for og in old_chunks.drain(..) {
1063                         elts.extend(og);
1064                     }
1065                     elts.extend(gr);
1066                 } else {
1067                     old_chunks.push(gr);
1068                 },
1069                 None => break,
1070             }
1071         }
1072         for og in old_chunks.drain(..) {
1073             elts.extend(og);
1074         }
1075         for gr in chunks1.map(&tup1) { elts.extend(gr); }
1076         for gr in chunks2.map(&tup1) { elts.extend(gr); }
1077         itertools::assert_equal(&data, elts);
1078         true
1079     }
1080 }
1081 
1082 quickcheck! {
1083     fn chunk_clone_equal(a: Vec<u8>, size: u8) -> () {
1084         let mut size = size;
1085         if size == 0 {
1086             size += 1;
1087         }
1088         let it = a.chunks(size as usize);
1089         itertools::assert_equal(it.clone(), it);
1090     }
1091 }
1092 
1093 quickcheck! {
1094     fn equal_chunks_lazy(a: Vec<u8>, size: u8) -> bool {
1095         let mut size = size;
1096         if size == 0 {
1097             size += 1;
1098         }
1099         let chunks = a.iter().chunks(size as usize);
1100         let it = a.chunks(size as usize);
1101         for (a, b) in chunks.into_iter().zip(it) {
1102             if !itertools::equal(a, b) {
1103                 return false;
1104             }
1105         }
1106         true
1107     }
1108 }
1109 
1110 // tuple iterators
1111 quickcheck! {
1112     fn equal_circular_tuple_windows_1(a: Vec<u8>) -> bool {
1113         let x = a.iter().map(|e| (e,) );
1114         let y = a.iter().circular_tuple_windows::<(_,)>();
1115         itertools::assert_equal(x,y);
1116         true
1117     }
1118 
1119     fn equal_circular_tuple_windows_2(a: Vec<u8>) -> bool {
1120         let x = (0..a.len()).map(|start_idx| (
1121             &a[start_idx],
1122             &a[(start_idx + 1) % a.len()],
1123         ));
1124         let y = a.iter().circular_tuple_windows::<(_, _)>();
1125         itertools::assert_equal(x,y);
1126         true
1127     }
1128 
1129     fn equal_circular_tuple_windows_3(a: Vec<u8>) -> bool {
1130         let x = (0..a.len()).map(|start_idx| (
1131             &a[start_idx],
1132             &a[(start_idx + 1) % a.len()],
1133             &a[(start_idx + 2) % a.len()],
1134         ));
1135         let y = a.iter().circular_tuple_windows::<(_, _, _)>();
1136         itertools::assert_equal(x,y);
1137         true
1138     }
1139 
1140     fn equal_circular_tuple_windows_4(a: Vec<u8>) -> bool {
1141         let x = (0..a.len()).map(|start_idx| (
1142             &a[start_idx],
1143             &a[(start_idx + 1) % a.len()],
1144             &a[(start_idx + 2) % a.len()],
1145             &a[(start_idx + 3) % a.len()],
1146         ));
1147         let y = a.iter().circular_tuple_windows::<(_, _, _, _)>();
1148         itertools::assert_equal(x,y);
1149         true
1150     }
1151 
1152     fn equal_cloned_circular_tuple_windows(a: Vec<u8>) -> bool {
1153         let x = a.iter().circular_tuple_windows::<(_, _, _, _)>();
1154         let y = x.clone();
1155         itertools::assert_equal(x,y);
1156         true
1157     }
1158 
1159     fn equal_cloned_circular_tuple_windows_noninitial(a: Vec<u8>) -> bool {
1160         let mut x = a.iter().circular_tuple_windows::<(_, _, _, _)>();
1161         let _ = x.next();
1162         let y = x.clone();
1163         itertools::assert_equal(x,y);
1164         true
1165     }
1166 
1167     fn equal_cloned_circular_tuple_windows_complete(a: Vec<u8>) -> bool {
1168         let mut x = a.iter().circular_tuple_windows::<(_, _, _, _)>();
1169         for _ in x.by_ref() {}
1170         let y = x.clone();
1171         itertools::assert_equal(x,y);
1172         true
1173     }
1174 
1175     fn circular_tuple_windows_exact_size(a: Vec<u8>) -> bool {
1176         exact_size(a.iter().circular_tuple_windows::<(_, _, _, _)>())
1177     }
1178 
1179     fn equal_tuple_windows_1(a: Vec<u8>) -> bool {
1180         let x = a.windows(1).map(|s| (&s[0], ));
1181         let y = a.iter().tuple_windows::<(_,)>();
1182         itertools::equal(x, y)
1183     }
1184 
1185     fn equal_tuple_windows_2(a: Vec<u8>) -> bool {
1186         let x = a.windows(2).map(|s| (&s[0], &s[1]));
1187         let y = a.iter().tuple_windows::<(_, _)>();
1188         itertools::equal(x, y)
1189     }
1190 
1191     fn equal_tuple_windows_3(a: Vec<u8>) -> bool {
1192         let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2]));
1193         let y = a.iter().tuple_windows::<(_, _, _)>();
1194         itertools::equal(x, y)
1195     }
1196 
1197     fn equal_tuple_windows_4(a: Vec<u8>) -> bool {
1198         let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3]));
1199         let y = a.iter().tuple_windows::<(_, _, _, _)>();
1200         itertools::equal(x, y)
1201     }
1202 
1203     fn tuple_windows_exact_size_1(a: Vec<u8>) -> bool {
1204         exact_size(a.iter().tuple_windows::<(_,)>())
1205     }
1206 
1207     fn tuple_windows_exact_size_4(a: Vec<u8>) -> bool {
1208         exact_size(a.iter().tuple_windows::<(_, _, _, _)>())
1209     }
1210 
1211     fn equal_tuples_1(a: Vec<u8>) -> bool {
1212         let x = a.chunks(1).map(|s| (&s[0], ));
1213         let y = a.iter().tuples::<(_,)>();
1214         itertools::equal(x, y)
1215     }
1216 
1217     fn equal_tuples_2(a: Vec<u8>) -> bool {
1218         let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1]));
1219         let y = a.iter().tuples::<(_, _)>();
1220         itertools::equal(x, y)
1221     }
1222 
1223     fn equal_tuples_3(a: Vec<u8>) -> bool {
1224         let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2]));
1225         let y = a.iter().tuples::<(_, _, _)>();
1226         itertools::equal(x, y)
1227     }
1228 
1229     fn equal_tuples_4(a: Vec<u8>) -> bool {
1230         let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3]));
1231         let y = a.iter().tuples::<(_, _, _, _)>();
1232         itertools::equal(x, y)
1233     }
1234 
1235     fn exact_tuple_buffer(a: Vec<u8>) -> bool {
1236         let mut iter = a.iter().tuples::<(_, _, _, _)>();
1237         (&mut iter).last();
1238         let buffer = iter.into_buffer();
1239         assert_eq!(buffer.len(), a.len() % 4);
1240         exact_size(buffer)
1241     }
1242 
1243     fn tuples_size_hint_inexact(a: Iter<u8>) -> bool {
1244         correct_size_hint(a.clone().tuples::<(_,)>())
1245             && correct_size_hint(a.clone().tuples::<(_, _)>())
1246             && correct_size_hint(a.tuples::<(_, _, _, _)>())
1247     }
1248 
1249     fn tuples_size_hint_exact(a: Iter<u8, Exact>) -> bool {
1250         exact_size(a.clone().tuples::<(_,)>())
1251             && exact_size(a.clone().tuples::<(_, _)>())
1252             && exact_size(a.tuples::<(_, _, _, _)>())
1253     }
1254 }
1255 
1256 // with_position
1257 quickcheck! {
1258     fn with_position_exact_size_1(a: Vec<u8>) -> bool {
1259         exact_size_for_this(a.iter().with_position())
1260     }
1261     fn with_position_exact_size_2(a: Iter<u8, Exact>) -> bool {
1262         exact_size_for_this(a.with_position())
1263     }
1264 }
1265 
1266 quickcheck! {
1267     fn correct_group_map_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1268         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1269         let count = a.len();
1270         let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map();
1271 
1272         assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count);
1273 
1274         for (&key, vals) in lookup.iter() {
1275             assert!(vals.iter().all(|&val| val % modulo == key));
1276         }
1277     }
1278 }
1279 
1280 /// A peculiar type: Equality compares both tuple items, but ordering only the
1281 /// first item.  This is so we can check the stability property easily.
1282 #[derive(Clone, Debug, PartialEq, Eq)]
1283 struct Val(u32, u32);
1284 
1285 impl PartialOrd<Self> for Val {
partial_cmp(&self, other: &Self) -> Option<Ordering>1286     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1287         Some(self.cmp(other))
1288     }
1289 }
1290 
1291 impl Ord for Val {
cmp(&self, other: &Self) -> Ordering1292     fn cmp(&self, other: &Self) -> Ordering {
1293         self.0.cmp(&other.0)
1294     }
1295 }
1296 
1297 impl qc::Arbitrary for Val {
arbitrary<G: qc::Gen>(g: &mut G) -> Self1298     fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
1299         let (x, y) = <(u32, u32)>::arbitrary(g);
1300         Self(x, y)
1301     }
shrink(&self) -> Box<dyn Iterator<Item = Self>>1302     fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
1303         Box::new((self.0, self.1).shrink().map(|(x, y)| Self(x, y)))
1304     }
1305 }
1306 
1307 quickcheck! {
1308     fn minmax(a: Vec<Val>) -> bool {
1309         use itertools::MinMaxResult;
1310 
1311 
1312         let minmax = a.iter().minmax();
1313         let expected = match a.len() {
1314             0 => MinMaxResult::NoElements,
1315             1 => MinMaxResult::OneElement(&a[0]),
1316             _ => MinMaxResult::MinMax(a.iter().min().unwrap(),
1317                                       a.iter().max().unwrap()),
1318         };
1319         minmax == expected
1320     }
1321 }
1322 
1323 quickcheck! {
1324     fn minmax_f64(a: Vec<f64>) -> TestResult {
1325         use itertools::MinMaxResult;
1326 
1327         if a.iter().any(|x| x.is_nan()) {
1328             return TestResult::discard();
1329         }
1330 
1331         let min = cloned(&a).fold1(f64::min);
1332         let max = cloned(&a).fold1(f64::max);
1333 
1334         let minmax = cloned(&a).minmax();
1335         let expected = match a.len() {
1336             0 => MinMaxResult::NoElements,
1337             1 => MinMaxResult::OneElement(min.unwrap()),
1338             _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()),
1339         };
1340         TestResult::from_bool(minmax == expected)
1341     }
1342 }
1343 
1344 quickcheck! {
1345     fn tree_reduce_f64(mut a: Vec<f64>) -> TestResult {
1346         fn collapse_adjacent<F>(x: Vec<f64>, mut f: F) -> Vec<f64>
1347             where F: FnMut(f64, f64) -> f64
1348         {
1349             let mut out = Vec::new();
1350             for i in (0..x.len()).step_by(2) {
1351                 if i == x.len()-1 {
1352                     out.push(x[i])
1353                 } else {
1354                     out.push(f(x[i], x[i+1]));
1355                 }
1356             }
1357             out
1358         }
1359 
1360         if a.iter().any(|x| x.is_nan()) {
1361             return TestResult::discard();
1362         }
1363 
1364         let actual = a.iter().cloned().tree_reduce(f64::atan2);
1365 
1366         while a.len() > 1 {
1367             a = collapse_adjacent(a, f64::atan2);
1368         }
1369         let expected = a.pop();
1370 
1371         TestResult::from_bool(actual == expected)
1372     }
1373 }
1374 
1375 quickcheck! {
1376     fn exactly_one_i32(a: Vec<i32>) -> TestResult {
1377         let ret = a.iter().cloned().exactly_one();
1378         match a.len() {
1379             1 => TestResult::from_bool(ret.unwrap() == a[0]),
1380             _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())),
1381         }
1382     }
1383 }
1384 
1385 quickcheck! {
1386     fn at_most_one_i32(a: Vec<i32>) -> TestResult {
1387         let ret = a.iter().cloned().at_most_one();
1388         match a.len() {
1389             0 => TestResult::from_bool(ret.unwrap().is_none()),
1390             1 => TestResult::from_bool(ret.unwrap() == Some(a[0])),
1391             _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())),
1392         }
1393     }
1394 }
1395 
1396 quickcheck! {
1397     fn consistent_grouping_map_with_by(a: Vec<u8>, modulo: u8) -> () {
1398         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1399 
1400         let lookup_grouping_map = a.iter().copied().map(|i| (i % modulo, i)).into_grouping_map().collect::<Vec<_>>();
1401         let lookup_grouping_map_by = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::<Vec<_>>();
1402 
1403         assert_eq!(lookup_grouping_map, lookup_grouping_map_by);
1404     }
1405 
1406     fn correct_grouping_map_by_aggregate_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1407         let modulo = if modulo < 2 { 2 } else { modulo } as u64; // Avoid `% 0`
1408         let lookup = a.iter()
1409             .map(|&b| b as u64) // Avoid overflows
1410             .into_grouping_map_by(|i| i % modulo)
1411             .aggregate(|acc, &key, val| {
1412                 assert!(val % modulo == key);
1413                 if val % (modulo - 1) == 0 {
1414                     None
1415                 } else {
1416                     Some(acc.unwrap_or(0) + val)
1417                 }
1418             });
1419 
1420         let group_map_lookup = a.iter()
1421             .map(|&b| b as u64)
1422             .map(|i| (i % modulo, i))
1423             .into_group_map()
1424             .into_iter()
1425             .filter_map(|(key, vals)| {
1426                 vals.into_iter().fold(None, |acc, val| {
1427                     if val % (modulo - 1) == 0 {
1428                         None
1429                     } else {
1430                         Some(acc.unwrap_or(0) + val)
1431                     }
1432                 }).map(|new_val| (key, new_val))
1433             })
1434             .collect::<HashMap<_,_>>();
1435         assert_eq!(lookup, group_map_lookup);
1436 
1437         for m in 0..modulo {
1438             assert_eq!(
1439                 lookup.get(&m).copied(),
1440                 a.iter()
1441                     .map(|&b| b as u64)
1442                     .filter(|&val| val % modulo == m)
1443                     .fold(None, |acc, val| {
1444                         if val % (modulo - 1) == 0 {
1445                             None
1446                         } else {
1447                             Some(acc.unwrap_or(0) + val)
1448                         }
1449                     })
1450             );
1451         }
1452     }
1453 
1454     fn correct_grouping_map_by_fold_with_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1455         #[derive(Debug, Default, PartialEq)]
1456         struct Accumulator {
1457             acc: u64,
1458         }
1459 
1460         let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
1461         let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
1462             .into_grouping_map_by(|i| i % modulo)
1463             .fold_with(|_key, _val| Default::default(), |Accumulator { acc }, &key, val| {
1464                 assert!(val % modulo == key);
1465                 let acc = acc + val;
1466                 Accumulator { acc }
1467             });
1468 
1469         let group_map_lookup = a.iter()
1470             .map(|&b| b as u64)
1471             .map(|i| (i % modulo, i))
1472             .into_group_map()
1473             .into_iter()
1474             .map(|(key, vals)| (key, vals.into_iter().sum())).map(|(key, acc)| (key,Accumulator { acc }))
1475             .collect::<HashMap<_,_>>();
1476         assert_eq!(lookup, group_map_lookup);
1477 
1478         for (&key, &Accumulator { acc: sum }) in lookup.iter() {
1479             assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
1480         }
1481     }
1482 
1483     fn correct_grouping_map_by_fold_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1484         let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
1485         let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
1486             .into_grouping_map_by(|i| i % modulo)
1487             .fold(0u64, |acc, &key, val| {
1488                 assert!(val % modulo == key);
1489                 acc + val
1490             });
1491 
1492         let group_map_lookup = a.iter()
1493             .map(|&b| b as u64)
1494             .map(|i| (i % modulo, i))
1495             .into_group_map()
1496             .into_iter()
1497             .map(|(key, vals)| (key, vals.into_iter().sum()))
1498             .collect::<HashMap<_,_>>();
1499         assert_eq!(lookup, group_map_lookup);
1500 
1501         for (&key, &sum) in lookup.iter() {
1502             assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
1503         }
1504     }
1505 
1506     fn correct_grouping_map_by_reduce_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1507         let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
1508         let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
1509             .into_grouping_map_by(|i| i % modulo)
1510             .reduce(|acc, &key, val| {
1511                 assert!(val % modulo == key);
1512                 acc + val
1513             });
1514 
1515         // TODO: Swap `fold1` with stdlib's `reduce` when it's stabilized
1516         let group_map_lookup = a.iter()
1517             .map(|&b| b as u64)
1518             .map(|i| (i % modulo, i))
1519             .into_group_map()
1520             .into_iter()
1521             .map(|(key, vals)| (key, vals.into_iter().fold1(|acc, val| acc + val).unwrap()))
1522             .collect::<HashMap<_,_>>();
1523         assert_eq!(lookup, group_map_lookup);
1524 
1525         for (&key, &sum) in lookup.iter() {
1526             assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
1527         }
1528     }
1529 
1530     fn correct_grouping_map_by_collect_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1531         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1532         let lookup_grouping_map = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::<Vec<_>>();
1533         let lookup_group_map = a.iter().copied().map(|i| (i % modulo, i)).into_group_map();
1534 
1535         assert_eq!(lookup_grouping_map, lookup_group_map);
1536     }
1537 
1538     fn correct_grouping_map_by_max_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1539         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1540         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max();
1541 
1542         let group_map_lookup = a.iter().copied()
1543             .map(|i| (i % modulo, i))
1544             .into_group_map()
1545             .into_iter()
1546             .map(|(key, vals)| (key, vals.into_iter().max().unwrap()))
1547             .collect::<HashMap<_,_>>();
1548         assert_eq!(lookup, group_map_lookup);
1549 
1550         for (&key, &max) in lookup.iter() {
1551             assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max());
1552         }
1553     }
1554 
1555     fn correct_grouping_map_by_max_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1556         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1557         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by(|_, v1, v2| v1.cmp(v2));
1558 
1559         let group_map_lookup = a.iter().copied()
1560             .map(|i| (i % modulo, i))
1561             .into_group_map()
1562             .into_iter()
1563             .map(|(key, vals)| (key, vals.into_iter().max_by(|v1, v2| v1.cmp(v2)).unwrap()))
1564             .collect::<HashMap<_,_>>();
1565         assert_eq!(lookup, group_map_lookup);
1566 
1567         for (&key, &max) in lookup.iter() {
1568             assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by(|v1, v2| v1.cmp(v2)));
1569         }
1570     }
1571 
1572     fn correct_grouping_map_by_max_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1573         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1574         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by_key(|_, &val| val);
1575 
1576         let group_map_lookup = a.iter().copied()
1577             .map(|i| (i % modulo, i))
1578             .into_group_map()
1579             .into_iter()
1580             .map(|(key, vals)| (key, vals.into_iter().max_by_key(|&val| val).unwrap()))
1581             .collect::<HashMap<_,_>>();
1582         assert_eq!(lookup, group_map_lookup);
1583 
1584         for (&key, &max) in lookup.iter() {
1585             assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by_key(|&val| val));
1586         }
1587     }
1588 
1589     fn correct_grouping_map_by_min_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1590         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1591         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min();
1592 
1593         let group_map_lookup = a.iter().copied()
1594             .map(|i| (i % modulo, i))
1595             .into_group_map()
1596             .into_iter()
1597             .map(|(key, vals)| (key, vals.into_iter().min().unwrap()))
1598             .collect::<HashMap<_,_>>();
1599         assert_eq!(lookup, group_map_lookup);
1600 
1601         for (&key, &min) in lookup.iter() {
1602             assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min());
1603         }
1604     }
1605 
1606     fn correct_grouping_map_by_min_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1607         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1608         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by(|_, v1, v2| v1.cmp(v2));
1609 
1610         let group_map_lookup = a.iter().copied()
1611             .map(|i| (i % modulo, i))
1612             .into_group_map()
1613             .into_iter()
1614             .map(|(key, vals)| (key, vals.into_iter().min_by(|v1, v2| v1.cmp(v2)).unwrap()))
1615             .collect::<HashMap<_,_>>();
1616         assert_eq!(lookup, group_map_lookup);
1617 
1618         for (&key, &min) in lookup.iter() {
1619             assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by(|v1, v2| v1.cmp(v2)));
1620         }
1621     }
1622 
1623     fn correct_grouping_map_by_min_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1624         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1625         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by_key(|_, &val| val);
1626 
1627         let group_map_lookup = a.iter().copied()
1628             .map(|i| (i % modulo, i))
1629             .into_group_map()
1630             .into_iter()
1631             .map(|(key, vals)| (key, vals.into_iter().min_by_key(|&val| val).unwrap()))
1632             .collect::<HashMap<_,_>>();
1633         assert_eq!(lookup, group_map_lookup);
1634 
1635         for (&key, &min) in lookup.iter() {
1636             assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by_key(|&val| val));
1637         }
1638     }
1639 
1640     fn correct_grouping_map_by_minmax_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1641         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1642         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax();
1643 
1644         let group_map_lookup = a.iter().copied()
1645             .map(|i| (i % modulo, i))
1646             .into_group_map()
1647             .into_iter()
1648             .map(|(key, vals)| (key, vals.into_iter().minmax()))
1649             .collect::<HashMap<_,_>>();
1650         assert_eq!(lookup, group_map_lookup);
1651 
1652         for (&key, &minmax) in lookup.iter() {
1653             assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax());
1654         }
1655     }
1656 
1657     fn correct_grouping_map_by_minmax_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1658         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1659         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by(|_, v1, v2| v1.cmp(v2));
1660 
1661         let group_map_lookup = a.iter().copied()
1662             .map(|i| (i % modulo, i))
1663             .into_group_map()
1664             .into_iter()
1665             .map(|(key, vals)| (key, vals.into_iter().minmax_by(|v1, v2| v1.cmp(v2))))
1666             .collect::<HashMap<_,_>>();
1667         assert_eq!(lookup, group_map_lookup);
1668 
1669         for (&key, &minmax) in lookup.iter() {
1670             assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by(|v1, v2| v1.cmp(v2)));
1671         }
1672     }
1673 
1674     fn correct_grouping_map_by_minmax_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1675         let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
1676         let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by_key(|_, &val| val);
1677 
1678         let group_map_lookup = a.iter().copied()
1679             .map(|i| (i % modulo, i))
1680             .into_group_map()
1681             .into_iter()
1682             .map(|(key, vals)| (key, vals.into_iter().minmax_by_key(|&val| val)))
1683             .collect::<HashMap<_,_>>();
1684         assert_eq!(lookup, group_map_lookup);
1685 
1686         for (&key, &minmax) in lookup.iter() {
1687             assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by_key(|&val| val));
1688         }
1689     }
1690 
1691     fn correct_grouping_map_by_sum_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1692         let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
1693         let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
1694             .into_grouping_map_by(|i| i % modulo)
1695             .sum();
1696 
1697         let group_map_lookup = a.iter().map(|&b| b as u64)
1698             .map(|i| (i % modulo, i))
1699             .into_group_map()
1700             .into_iter()
1701             .map(|(key, vals)| (key, vals.into_iter().sum()))
1702             .collect::<HashMap<_,_>>();
1703         assert_eq!(lookup, group_map_lookup);
1704 
1705         for (&key, &sum) in lookup.iter() {
1706             assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
1707         }
1708     }
1709 
1710     fn correct_grouping_map_by_product_modulo_key(a: Vec<u8>, modulo: u8) -> () {
1711         let modulo = Wrapping(if modulo == 0 { 1 } else { modulo } as u64); // Avoid `% 0`
1712         let lookup = a.iter().map(|&b| Wrapping(b as u64)) // Avoid overflows
1713             .into_grouping_map_by(|i| i % modulo)
1714             .product();
1715 
1716         let group_map_lookup = a.iter().map(|&b| Wrapping(b as u64))
1717             .map(|i| (i % modulo, i))
1718             .into_group_map()
1719             .into_iter()
1720             .map(|(key, vals)| (key, vals.into_iter().product::<Wrapping<u64>>()))
1721             .collect::<HashMap<_,_>>();
1722         assert_eq!(lookup, group_map_lookup);
1723 
1724         for (&key, &prod) in lookup.iter() {
1725             assert_eq!(
1726                 prod,
1727                 a.iter()
1728                     .map(|&b| Wrapping(b as u64))
1729                     .filter(|&val| val % modulo == key)
1730                     .product::<Wrapping<u64>>()
1731             );
1732         }
1733     }
1734 
1735     // This should check that if multiple elements are equally minimum or maximum
1736     // then `max`, `min` and `minmax` pick the first minimum and the last maximum.
1737     // This is to be consistent with `std::iter::max` and `std::iter::min`.
1738     fn correct_grouping_map_by_min_max_minmax_order_modulo_key() -> () {
1739         use itertools::MinMaxResult;
1740 
1741         let lookup = (0..=10)
1742             .into_grouping_map_by(|_| 0)
1743             .max_by(|_, _, _| Ordering::Equal);
1744 
1745         assert_eq!(lookup[&0], 10);
1746 
1747         let lookup = (0..=10)
1748             .into_grouping_map_by(|_| 0)
1749             .min_by(|_, _, _| Ordering::Equal);
1750 
1751         assert_eq!(lookup[&0], 0);
1752 
1753         let lookup = (0..=10)
1754             .into_grouping_map_by(|_| 0)
1755             .minmax_by(|_, _, _| Ordering::Equal);
1756 
1757         assert_eq!(lookup[&0], MinMaxResult::MinMax(0, 10));
1758     }
1759 }
1760 
1761 quickcheck! {
1762     fn counts(nums: Vec<isize>) -> TestResult {
1763         let counts = nums.iter().counts();
1764         for (&item, &count) in counts.iter() {
1765             #[allow(clippy::absurd_extreme_comparisons)]
1766             if count <= 0 {
1767                 return TestResult::failed();
1768             }
1769             if count != nums.iter().filter(|&x| x == item).count() {
1770                 return TestResult::failed();
1771             }
1772         }
1773         for item in nums.iter() {
1774             if !counts.contains_key(item) {
1775                 return TestResult::failed();
1776             }
1777         }
1778         TestResult::passed()
1779     }
1780 }
1781 
1782 quickcheck! {
1783     fn test_double_ended_zip_2(a: Vec<u8>, b: Vec<u8>) -> TestResult {
1784         let mut x =
1785           multizip((a.clone().into_iter(), b.clone().into_iter()))
1786             .collect_vec();
1787         x.reverse();
1788 
1789         let y =
1790           multizip((a.into_iter(), b.into_iter()))
1791           .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec });
1792 
1793         TestResult::from_bool(itertools::equal(x, y))
1794     }
1795 
1796     fn test_double_ended_zip_3(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> TestResult {
1797         let mut x =
1798           multizip((a.clone().into_iter(), b.clone().into_iter(), c.clone().into_iter()))
1799             .collect_vec();
1800         x.reverse();
1801 
1802         let y =
1803           multizip((a.into_iter(), b.into_iter(), c.into_iter()))
1804           .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec });
1805 
1806         TestResult::from_bool(itertools::equal(x, y))
1807     }
1808 }
1809 
is_fused<I: Iterator>(mut it: I) -> bool1810 fn is_fused<I: Iterator>(mut it: I) -> bool {
1811     for _ in it.by_ref() {}
1812     for _ in 0..10 {
1813         if it.next().is_some() {
1814             return false;
1815         }
1816     }
1817     true
1818 }
1819 
1820 quickcheck! {
1821     fn fused_combination(a: Iter<i16>) -> bool
1822     {
1823         is_fused(a.clone().combinations(1)) &&
1824         is_fused(a.combinations(3))
1825     }
1826 
1827     fn fused_combination_with_replacement(a: Iter<i16>) -> bool
1828     {
1829         is_fused(a.clone().combinations_with_replacement(1)) &&
1830         is_fused(a.combinations_with_replacement(3))
1831     }
1832 
1833     fn fused_tuple_combination(a: Iter<i16>) -> bool
1834     {
1835         is_fused(a.clone().fuse().tuple_combinations::<(_,)>()) &&
1836         is_fused(a.fuse().tuple_combinations::<(_,_,_)>())
1837     }
1838 
1839     fn fused_unique(a: Iter<i16>) -> bool
1840     {
1841         is_fused(a.fuse().unique())
1842     }
1843 
1844     fn fused_unique_by(a: Iter<i16>) -> bool
1845     {
1846         is_fused(a.fuse().unique_by(|x| x % 100))
1847     }
1848 
1849     fn fused_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool
1850     {
1851         !is_fused(a.clone().interleave_shortest(b.clone())) &&
1852         is_fused(a.fuse().interleave_shortest(b.fuse()))
1853     }
1854 
1855     fn fused_product(a: Iter<i16>, b: Iter<i16>) -> bool
1856     {
1857         is_fused(a.fuse().cartesian_product(b.fuse()))
1858     }
1859 
1860     fn fused_merge(a: Iter<i16>, b: Iter<i16>) -> bool
1861     {
1862         is_fused(a.fuse().merge(b.fuse()))
1863     }
1864 
1865     fn fused_filter_ok(a: Iter<i16>) -> bool
1866     {
1867         is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1868                  .filter_ok(|x| x % 3 == 0)
1869                  .fuse())
1870     }
1871 
1872     fn fused_filter_map_ok(a: Iter<i16>) -> bool
1873     {
1874         is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1875                  .filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None})
1876                  .fuse())
1877     }
1878 
1879     fn fused_positions(a: Iter<i16>) -> bool
1880     {
1881         !is_fused(a.clone().positions(|x|x%2==0)) &&
1882         is_fused(a.fuse().positions(|x|x%2==0))
1883     }
1884 
1885     fn fused_update(a: Iter<i16>) -> bool
1886     {
1887         !is_fused(a.clone().update(|x|*x+=1)) &&
1888         is_fused(a.fuse().update(|x|*x+=1))
1889     }
1890 
1891     fn fused_tuple_windows(a: Iter<i16>) -> bool
1892     {
1893         is_fused(a.fuse().tuple_windows::<(_,_)>())
1894     }
1895 
1896     fn fused_pad_using(a: Iter<i16>) -> bool
1897     {
1898         is_fused(a.fuse().pad_using(100,|_|0))
1899     }
1900 }
1901 
1902 quickcheck! {
1903     fn min_set_contains_min(a: Vec<(usize, char)>) -> bool {
1904         let result_set = a.iter().min_set();
1905         if let Some(result_element) = a.iter().min() {
1906             result_set.contains(&result_element)
1907         } else {
1908             result_set.is_empty()
1909         }
1910     }
1911 
1912     fn min_set_by_contains_min(a: Vec<(usize, char)>) -> bool {
1913         let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1);
1914         let result_set = a.iter().min_set_by(compare);
1915         if let Some(result_element) = a.iter().min_by(compare) {
1916             result_set.contains(&result_element)
1917         } else {
1918             result_set.is_empty()
1919         }
1920     }
1921 
1922     fn min_set_by_key_contains_min(a: Vec<(usize, char)>) -> bool {
1923         let key = |x: &&(usize, char)| x.1;
1924         let result_set = a.iter().min_set_by_key(&key);
1925         if let Some(result_element) = a.iter().min_by_key(&key) {
1926             result_set.contains(&result_element)
1927         } else {
1928             result_set.is_empty()
1929         }
1930     }
1931 
1932     fn max_set_contains_max(a: Vec<(usize, char)>) -> bool {
1933         let result_set = a.iter().max_set();
1934         if let Some(result_element) = a.iter().max() {
1935             result_set.contains(&result_element)
1936         } else {
1937             result_set.is_empty()
1938         }
1939     }
1940 
1941     fn max_set_by_contains_max(a: Vec<(usize, char)>) -> bool {
1942         let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1);
1943         let result_set = a.iter().max_set_by(compare);
1944         if let Some(result_element) = a.iter().max_by(compare) {
1945             result_set.contains(&result_element)
1946         } else {
1947             result_set.is_empty()
1948         }
1949     }
1950 
1951     fn max_set_by_key_contains_max(a: Vec<(usize, char)>) -> bool {
1952         let key = |x: &&(usize, char)| x.1;
1953         let result_set = a.iter().max_set_by_key(&key);
1954         if let Some(result_element) = a.iter().max_by_key(&key) {
1955             result_set.contains(&result_element)
1956         } else {
1957             result_set.is_empty()
1958         }
1959     }
1960 
1961     fn tail(v: Vec<i32>, n: u8) -> bool {
1962         let n = n as usize;
1963         let result = &v[v.len().saturating_sub(n)..];
1964         itertools::equal(v.iter().tail(n), result)
1965             && itertools::equal(v.iter().filter(|_| true).tail(n), result)
1966     }
1967 }
1968