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