1 //! The purpose of these tests is to cover corner cases of iterators
4 //! In particular we test the tedious size_hint and exact size correctness.
6 #[macro_use] extern crate itertools;
8 extern crate quickcheck
;
10 use std
::default::Default
;
14 use std
::cmp
::Ordering
;
15 use itertools
::Itertools
;
20 use itertools
::flatten
;
21 use itertools
::free
::{
32 use quickcheck
::TestResult
;
34 /// Trait for size hint modifier types
35 trait HintKind
: Copy
+ Send
+ qc
::Arbitrary
{
36 fn loosen_bounds(&self, org_hint
: (usize, Option
<usize>)) -> (usize, Option
<usize>);
39 /// Exact size hint variant that leaves hints unchanged
40 #[derive(Clone, Copy, Debug)]
43 impl HintKind
for Exact
{
44 fn loosen_bounds(&self, org_hint
: (usize, Option
<usize>)) -> (usize, Option
<usize>) {
49 impl qc
::Arbitrary
for Exact
{
50 fn arbitrary
<G
: qc
::Gen
>(_
: &mut G
) -> Self {
55 /// Inexact size hint variant to simulate imprecise (but valid) size hints
57 /// Will always decrease the lower bound and increase the upper bound
58 /// of the size hint by set amounts.
59 #[derive(Clone, Copy, Debug)]
65 impl HintKind
for Inexact
{
66 fn loosen_bounds(&self, org_hint
: (usize, Option
<usize>)) -> (usize, Option
<usize>) {
67 let (org_lower
, org_upper
) = org_hint
;
68 (org_lower
.saturating_sub(self.underestimate
),
69 org_upper
.and_then(move |x
| x
.checked_add(self.overestimate
)))
73 impl qc
::Arbitrary
for Inexact
{
74 fn arbitrary
<G
: qc
::Gen
>(g
: &mut G
) -> Self {
75 let ue_value
= usize::arbitrary(g
);
76 let oe_value
= usize::arbitrary(g
);
77 // Compensate for quickcheck using extreme values too rarely
78 let ue_choices
= &[0, ue_value
, usize::max_value()];
79 let oe_choices
= &[0, oe_value
, usize::max_value()];
81 underestimate
: *g
.choose(ue_choices
).unwrap(),
82 overestimate
: *g
.choose(oe_choices
).unwrap(),
86 fn shrink(&self) -> Box
<Iterator
<Item
=Self>> {
87 let underestimate_value
= self.underestimate
;
88 let overestimate_value
= self.overestimate
;
90 underestimate_value
.shrink().flat_map(move |ue_value
|
91 overestimate_value
.shrink().map(move |oe_value
|
93 underestimate
: ue_value
,
94 overestimate
: oe_value
,
102 /// Our base iterator that we can impl Arbitrary for
104 /// By default we'll return inexact bounds estimates for size_hint
105 /// to make tests harder to pass.
107 /// NOTE: Iter is tricky and is not fused, to help catch bugs.
108 /// At the end it will return None once, then return Some(0),
109 /// then return None again.
110 #[derive(Clone, Debug)]
111 struct Iter
<T
, SK
: HintKind
= Inexact
> {
118 impl<T
, HK
> Iter
<T
, HK
> where HK
: HintKind
120 fn new(it
: Range
<T
>, hint_kind
: HK
) -> Self {
129 impl<T
, HK
> Iterator
for Iter
<T
, HK
>
130 where Range
<T
>: Iterator
,
131 <Range
<T
> as Iterator
>::Item
: Default
,
134 type Item
= <Range
<T
> as Iterator
>::Item
;
136 fn next(&mut self) -> Option
<Self::Item
>
138 let elt
= self.iterator
.next();
142 if self.fuse_flag
== 2 {
143 return Some(Default
::default())
149 fn size_hint(&self) -> (usize, Option
<usize>)
151 let org_hint
= self.iterator
.size_hint();
152 self.hint_kind
.loosen_bounds(org_hint
)
156 impl<T
, HK
> DoubleEndedIterator
for Iter
<T
, HK
>
157 where Range
<T
>: DoubleEndedIterator
,
158 <Range
<T
> as Iterator
>::Item
: Default
,
161 fn next_back(&mut self) -> Option
<Self::Item
> { self.iterator.next_back() }
164 impl<T
> ExactSizeIterator
for Iter
<T
, Exact
> where Range
<T
>: ExactSizeIterator
,
165 <Range
<T
> as Iterator
>::Item
: Default
,
168 impl<T
, HK
> qc
::Arbitrary
for Iter
<T
, HK
>
169 where T
: qc
::Arbitrary
,
172 fn arbitrary
<G
: qc
::Gen
>(g
: &mut G
) -> Self
174 Iter
::new(T
::arbitrary(g
)..T
::arbitrary(g
), HK
::arbitrary(g
))
177 fn shrink(&self) -> Box
<Iterator
<Item
=Iter
<T
, HK
>>>
179 let r
= self.iterator
.clone();
180 let hint_kind
= self.hint_kind
;
182 r
.start
.shrink().flat_map(move |a
|
183 r
.end
.shrink().map(move |b
|
184 Iter
::new(a
.clone()..b
, hint_kind
)
191 /// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are
192 /// increased or decreased linearly on each iteration.
193 #[derive(Clone, Debug)]
194 struct ShiftRange
<HK
= Inexact
> {
203 impl<HK
> Iterator
for ShiftRange
<HK
> where HK
: HintKind
{
204 type Item
= Iter
<i32, HK
>;
206 fn next(&mut self) -> Option
<Self::Item
> {
207 if self.iter_count
== 0 {
211 let iter
= Iter
::new(self.range_start
..self.range_end
, self.hint_kind
);
213 self.range_start
+= self.start_step
;
214 self.range_end
+= self.end_step
;
215 self.iter_count
-= 1;
221 impl ExactSizeIterator
for ShiftRange
<Exact
> { }
223 impl<HK
> qc
::Arbitrary
for ShiftRange
<HK
>
226 fn arbitrary
<G
: qc
::Gen
>(g
: &mut G
) -> Self {
227 const MAX_STARTING_RANGE_DIFF
: i32 = 32;
228 const MAX_STEP_MODULO
: i32 = 8;
229 const MAX_ITER_COUNT
: u32 = 3;
231 let range_start
= qc
::Arbitrary
::arbitrary(g
);
232 let range_end
= range_start
+ g
.gen_range(0, MAX_STARTING_RANGE_DIFF
+ 1);
233 let start_step
= g
.gen_range(-MAX_STEP_MODULO
, MAX_STEP_MODULO
+ 1);
234 let end_step
= g
.gen_range(-MAX_STEP_MODULO
, MAX_STEP_MODULO
+ 1);
235 let iter_count
= g
.gen_range(0, MAX_ITER_COUNT
+ 1);
236 let hint_kind
= qc
::Arbitrary
::arbitrary(g
);
239 range_start
: range_start
,
240 range_end
: range_end
,
241 start_step
: start_step
,
243 iter_count
: iter_count
,
249 fn correct_size_hint
<I
: Iterator
>(mut it
: I
) -> bool
{
250 // record size hint at each iteration
251 let initial_hint
= it
.size_hint();
252 let mut hints
= Vec
::with_capacity(initial_hint
.0 + 1);
253 hints
.push(initial_hint
);
254 while let Some(_
) = it
.next() {
255 hints
.push(it
.size_hint())
258 let mut true_count
= hints
.len(); // start off +1 too much
260 // check all the size hints
261 for &(low
, hi
) in &hints
{
263 if low
> true_count
||
264 (hi
.is_some() && hi
.unwrap() < true_count
)
266 println
!("True size: {:?}, size hint: {:?}", true_count
, (low
, hi
));
267 //println!("All hints: {:?}", hints);
274 fn exact_size
<I
: ExactSizeIterator
>(mut it
: I
) -> bool
{
275 // check every iteration
276 let (mut low
, mut hi
) = it
.size_hint();
277 if Some(low
) != hi { return false; }
278 while let Some(_
) = it
.next() {
279 let (xlow
, xhi
) = it
.size_hint();
280 if low
!= xlow
+ 1 { return false; }
283 if Some(low
) != hi { return false; }
285 let (low
, hi
) = it
.size_hint();
286 low
== 0 && hi
== Some(0)
289 // Exact size for this case, without ExactSizeIterator
290 fn exact_size_for_this
<I
: Iterator
>(mut it
: I
) -> bool
{
291 // check every iteration
292 let (mut low
, mut hi
) = it
.size_hint();
293 if Some(low
) != hi { return false; }
294 while let Some(_
) = it
.next() {
295 let (xlow
, xhi
) = it
.size_hint();
296 if low
!= xlow
+ 1 { return false; }
299 if Some(low
) != hi { return false; }
301 let (low
, hi
) = it
.size_hint();
302 low
== 0 && hi
== Some(0)
306 * NOTE: Range<i8> is broken!
307 * (all signed ranges are)
309 fn size_range_i8(a: Iter<i8>) -> bool {
314 fn size_range_i16(a: Iter<i16>) -> bool {
319 fn size_range_u8(a: Iter<u8>) -> bool {
324 macro_rules
! quickcheck
{
325 // accept several property function definitions
326 // The property functions can use pattern matching and `mut` as usual
327 // in the function arguments, but the functions can not be generic.
328 {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* }
)*} => (
333 fn prop($
($arg
)*) -> $ret
{
336 ::quickcheck
::quickcheck(quickcheck
!(@
fn prop
[] $
($arg
)*));
340 // parse argument list (with patterns allowed) into prop as fn(_, _) -> _
341 (@
fn $f
:ident
[$
($t
:tt
)*]) => {
342 $f
as fn($
($t
),*) -> _
344 (@
fn $f
:ident
[$
($p
:tt
)*] : $
($tail
:tt
)*) => {
345 quickcheck
!(@
fn $f
[$
($p
)* _
] $
($tail
)*)
347 (@
fn $f
:ident
[$
($p
:tt
)*] $t
:tt $
($tail
:tt
)*) => {
348 quickcheck
!(@
fn $f
[$
($p
)*] $
($tail
)*)
354 fn size_product(a
: Iter
<u16>, b
: Iter
<u16>) -> bool
{
355 correct_size_hint(a
.cartesian_product(b
))
357 fn size_product3(a
: Iter
<u16>, b
: Iter
<u16>, c
: Iter
<u16>) -> bool
{
358 correct_size_hint(iproduct
!(a
, b
, c
))
361 fn correct_cartesian_product3(a
: Iter
<u16>, b
: Iter
<u16>, c
: Iter
<u16>,
362 take_manual
: usize) -> ()
364 // test correctness of iproduct through regular iteration (take)
369 let answer
: Vec
<_
> = ac
.flat_map(move |ea
| br
.clone().flat_map(move |eb
| cr
.clone().map(move |ec
| (ea
, eb
, ec
)))).collect();
370 let mut product_iter
= iproduct
!(a
, b
, c
);
371 let mut actual
= Vec
::new();
373 actual
.extend((&mut product_iter
).take(take_manual
));
374 if actual
.len() == take_manual
{
375 product_iter
.fold((), |(), elt
| actual
.push(elt
));
377 assert_eq
!(answer
, actual
);
380 fn size_multi_product(a
: ShiftRange
) -> bool
{
381 correct_size_hint(a
.multi_cartesian_product())
383 fn correct_multi_product3(a
: ShiftRange
, take_manual
: usize) -> () {
384 // Fix no. of iterators at 3
385 let a
= ShiftRange { iter_count: 3, ..a }
;
387 // test correctness of MultiProduct through regular iteration (take)
389 let mut iters
= a
.clone();
390 let i0
= iters
.next().unwrap();
391 let i1r
= &iters
.next().unwrap();
392 let i2r
= &iters
.next().unwrap();
393 let answer
: Vec
<_
> = i0
.flat_map(move |ei0
| i1r
.clone().flat_map(move |ei1
| i2r
.clone().map(move |ei2
| vec
![ei0
, ei1
, ei2
]))).collect();
394 let mut multi_product
= a
.clone().multi_cartesian_product();
395 let mut actual
= Vec
::new();
397 actual
.extend((&mut multi_product
).take(take_manual
));
398 if actual
.len() == take_manual
{
399 multi_product
.fold((), |(), elt
| actual
.push(elt
));
401 assert_eq
!(answer
, actual
);
403 assert_eq
!(answer
.into_iter().last(), a
.clone().multi_cartesian_product().last());
406 fn size_step(a
: Iter
<i16, Exact
>, s
: usize) -> bool
{
409 s
+= 1; // never zero
411 let filt
= a
.clone().dedup();
412 correct_size_hint(filt
.step(s
)) &&
413 exact_size(a
.step(s
))
415 fn equal_step(a
: Iter
<i16>, s
: usize) -> bool
{
418 s
+= 1; // never zero
421 itertools
::equal(a
.clone().step(s
), a
.filter(|_
| {
422 let keep
= i
% s
== 0;
427 fn equal_step_vec(a
: Vec
<i16>, s
: usize) -> bool
{
430 s
+= 1; // never zero
433 itertools
::equal(a
.iter().step(s
), a
.iter().filter(|_
| {
434 let keep
= i
% s
== 0;
440 fn size_multipeek(a
: Iter
<u16, Exact
>, s
: u8) -> bool
{
441 let mut it
= multipeek(a
);
449 fn equal_merge(a
: Vec
<i16>, b
: Vec
<i16>) -> bool
{
450 let mut sa
= a
.clone();
451 let mut sb
= b
.clone();
454 let mut merged
= sa
.clone();
455 merged
.extend(sb
.iter().cloned());
457 itertools
::equal(&merged
, sa
.iter().merge(&sb
))
459 fn size_merge(a
: Iter
<u16>, b
: Iter
<u16>) -> bool
{
460 correct_size_hint(a
.merge(b
))
462 fn size_zip(a
: Iter
<i16, Exact
>, b
: Iter
<i16, Exact
>, c
: Iter
<i16, Exact
>) -> bool
{
463 let filt
= a
.clone().dedup();
464 correct_size_hint(multizip((filt
, b
.clone(), c
.clone()))) &&
465 exact_size(multizip((a
, b
, c
)))
467 fn size_zip_rc(a
: Iter
<i16>, b
: Iter
<i16>) -> bool
{
468 let rc
= rciter(a
.clone());
469 correct_size_hint(multizip((&rc
, &rc
, b
)))
472 fn size_zip_macro(a
: Iter
<i16, Exact
>, b
: Iter
<i16, Exact
>, c
: Iter
<i16, Exact
>) -> bool
{
473 let filt
= a
.clone().dedup();
474 correct_size_hint(izip
!(filt
, b
.clone(), c
.clone())) &&
475 exact_size(izip
!(a
, b
, c
))
477 fn equal_kmerge(a
: Vec
<i16>, b
: Vec
<i16>, c
: Vec
<i16>) -> bool
{
478 use itertools
::free
::kmerge
;
479 let mut sa
= a
.clone();
480 let mut sb
= b
.clone();
481 let mut sc
= c
.clone();
485 let mut merged
= sa
.clone();
486 merged
.extend(sb
.iter().cloned());
487 merged
.extend(sc
.iter().cloned());
489 itertools
::equal(merged
.into_iter(), kmerge(vec
![sa
, sb
, sc
]))
492 // Any number of input iterators
493 fn equal_kmerge_2(mut inputs
: Vec
<Vec
<i16>>) -> bool
{
494 use itertools
::free
::kmerge
;
496 for input
in &mut inputs
{
499 let mut merged
= inputs
.concat();
501 itertools
::equal(merged
.into_iter(), kmerge(inputs
))
504 // Any number of input iterators
505 fn equal_kmerge_by_ge(mut inputs
: Vec
<Vec
<i16>>) -> bool
{
507 for input
in &mut inputs
{
511 let mut merged
= inputs
.concat();
514 itertools
::equal(merged
.into_iter(),
515 inputs
.into_iter().kmerge_by(|x
, y
| x
>= y
))
518 // Any number of input iterators
519 fn equal_kmerge_by_lt(mut inputs
: Vec
<Vec
<i16>>) -> bool
{
521 for input
in &mut inputs
{
524 let mut merged
= inputs
.concat();
526 itertools
::equal(merged
.into_iter(),
527 inputs
.into_iter().kmerge_by(|x
, y
| x
< y
))
530 // Any number of input iterators
531 fn equal_kmerge_by_le(mut inputs
: Vec
<Vec
<i16>>) -> bool
{
533 for input
in &mut inputs
{
536 let mut merged
= inputs
.concat();
538 itertools
::equal(merged
.into_iter(),
539 inputs
.into_iter().kmerge_by(|x
, y
| x
<= y
))
541 fn size_kmerge(a
: Iter
<i16>, b
: Iter
<i16>, c
: Iter
<i16>) -> bool
{
542 use itertools
::free
::kmerge
;
543 correct_size_hint(kmerge(vec
![a
, b
, c
]))
545 fn equal_zip_eq(a
: Vec
<i32>, b
: Vec
<i32>) -> bool
{
546 let len
= std
::cmp
::min(a
.len(), b
.len());
549 itertools
::equal(zip_eq(a
, b
), zip(a
, b
))
551 fn size_zip_longest(a
: Iter
<i16, Exact
>, b
: Iter
<i16, Exact
>) -> bool
{
552 let filt
= a
.clone().dedup();
553 let filt2
= b
.clone().dedup();
554 correct_size_hint(filt
.zip_longest(b
.clone())) &&
555 correct_size_hint(a
.clone().zip_longest(filt2
)) &&
556 exact_size(a
.zip_longest(b
))
558 fn size_2_zip_longest(a
: Iter
<i16>, b
: Iter
<i16>) -> bool
{
559 let it
= a
.clone().zip_longest(b
.clone());
560 let jt
= a
.clone().zip_longest(b
.clone());
561 itertools
::equal(a
.clone(),
562 it
.filter_map(|elt
| match elt
{
563 EitherOrBoth
::Both(x
, _
) => Some(x
),
564 EitherOrBoth
::Left(x
) => Some(x
),
569 itertools
::equal(b
.clone(),
570 jt
.filter_map(|elt
| match elt
{
571 EitherOrBoth
::Both(_
, y
) => Some(y
),
572 EitherOrBoth
::Right(y
) => Some(y
),
577 fn size_interleave(a
: Iter
<i16>, b
: Iter
<i16>) -> bool
{
578 correct_size_hint(a
.interleave(b
))
580 fn exact_interleave(a
: Iter
<i16, Exact
>, b
: Iter
<i16, Exact
>) -> bool
{
581 exact_size_for_this(a
.interleave(b
))
583 fn size_interleave_shortest(a
: Iter
<i16>, b
: Iter
<i16>) -> bool
{
584 correct_size_hint(a
.interleave_shortest(b
))
586 fn exact_interleave_shortest(a
: Vec
<()>, b
: Vec
<()>) -> bool
{
587 exact_size_for_this(a
.iter().interleave_shortest(&b
))
589 fn size_intersperse(a
: Iter
<i16>, x
: i16) -> bool
{
590 correct_size_hint(a
.intersperse(x
))
592 fn equal_intersperse(a
: Vec
<i32>, x
: i32) -> bool
{
593 let mut inter
= false;
595 for elt
in a
.iter().cloned().intersperse(x
) {
597 if elt
!= x { return false }
599 if elt
!= a
[i
] { return false }
607 fn equal_flatten(a
: Vec
<Option
<i32>>) -> bool
{
608 itertools
::equal(flatten(&a
),
609 a
.iter().filter_map(|x
| x
.as_ref()))
612 fn equal_flatten_vec(a
: Vec
<Vec
<u8>>) -> bool
{
613 itertools
::equal(flatten(&a
),
614 a
.iter().flat_map(|x
| x
))
617 fn equal_combinations_2(a
: Vec
<u8>) -> bool
{
618 let mut v
= Vec
::new();
619 for (i
, x
) in enumerate(&a
) {
620 for y
in &a
[i
+ 1..] {
624 itertools
::equal(a
.iter().tuple_combinations
::<(_
, _
)>(), v
)
627 fn collect_tuple_matches_size(a
: Iter
<i16>) -> bool
{
628 let size
= a
.clone().count();
629 a
.collect_tuple
::<(_
, _
, _
)>().is_some() == (size
== 3)
634 fn equal_dedup(a
: Vec
<i32>) -> bool
{
635 let mut b
= a
.clone();
637 itertools
::equal(&b
, a
.iter().dedup())
642 fn size_dedup(a
: Vec
<i32>) -> bool
{
643 correct_size_hint(a
.iter().dedup())
648 fn exact_repeatn((n
, x
): (usize, i32)) -> bool
{
649 let it
= itertools
::repeat_n(x
, n
);
655 fn size_put_back(a
: Vec
<u8>, x
: Option
<u8>) -> bool
{
656 let mut it
= put_back(a
.into_iter());
658 Some(t
) => it
.put_back(t
),
661 correct_size_hint(it
)
666 fn size_put_backn(a
: Vec
<u8>, b
: Vec
<u8>) -> bool
{
667 let mut it
= put_back_n(a
.into_iter());
671 correct_size_hint(it
)
676 fn size_tee(a
: Vec
<u8>) -> bool
{
677 let (mut t1
, mut t2
) = a
.iter().tee();
681 exact_size(t1
) && exact_size(t2
)
686 fn size_tee_2(a
: Vec
<u8>) -> bool
{
687 let (mut t1
, mut t2
) = a
.iter().dedup().tee();
691 correct_size_hint(t1
) && correct_size_hint(t2
)
696 fn size_take_while_ref(a
: Vec
<u8>, stop
: u8) -> bool
{
697 correct_size_hint(a
.iter().take_while_ref(|x
| **x
!= stop
))
702 fn equal_partition(a
: Vec
<i32>) -> bool
{
704 let mut ap
= a
.clone();
705 let split_index
= itertools
::partition(&mut ap
, |x
| *x
>= 0);
706 let parted
= (0..split_index
).all(|i
| ap
[i
] >= 0) &&
707 (split_index
..a
.len()).all(|i
| ap
[i
] < 0);
716 fn size_combinations(it
: Iter
<i16>) -> bool
{
717 correct_size_hint(it
.tuple_combinations
::<(_
, _
)>())
722 fn equal_combinations(it
: Iter
<i16>) -> bool
{
723 let values
= it
.clone().collect_vec();
724 let mut cmb
= it
.tuple_combinations();
725 for i
in 0..values
.len() {
726 for j
in i
+1..values
.len() {
727 let pair
= (values
[i
], values
[j
]);
728 if pair
!= cmb
.next().unwrap() {
738 fn size_pad_tail(it
: Iter
<i8>, pad
: u8) -> bool
{
739 correct_size_hint(it
.clone().pad_using(pad
as usize, |_
| 0)) &&
740 correct_size_hint(it
.dropping(1).rev().pad_using(pad
as usize, |_
| 0))
745 fn size_pad_tail2(it
: Iter
<i8, Exact
>, pad
: u8) -> bool
{
746 exact_size(it
.pad_using(pad
as usize, |_
| 0))
751 fn size_unique(it
: Iter
<i8>) -> bool
{
752 correct_size_hint(it
.unique())
755 fn count_unique(it
: Vec
<i8>, take_first
: u8) -> () {
757 let mut v
= it
.clone();
761 let mut iter
= cloned(&it
).unique();
762 let first_count
= (&mut iter
).take(take_first
as usize).count();
763 let rest_count
= iter
.count();
764 assert_eq
!(answer
, first_count
+ rest_count
);
769 fn fuzz_group_by_lazy_1(it
: Iter
<u8>) -> bool
{
771 let groups
= it
.group_by(|k
| *k
);
772 let res
= itertools
::equal(jt
, groups
.into_iter().flat_map(|(_
, x
)| x
));
778 fn fuzz_group_by_lazy_2(data
: Vec
<u8>) -> bool
{
779 let groups
= data
.iter().group_by(|k
| *k
/ 10);
780 let res
= itertools
::equal(data
.iter(), groups
.into_iter().flat_map(|(_
, x
)| x
));
786 fn fuzz_group_by_lazy_3(data
: Vec
<u8>) -> bool
{
787 let grouper
= data
.iter().group_by(|k
| *k
/ 10);
788 let groups
= grouper
.into_iter().collect_vec();
789 let res
= itertools
::equal(data
.iter(), groups
.into_iter().flat_map(|(_
, x
)| x
));
795 fn fuzz_group_by_lazy_duo(data
: Vec
<u8>, order
: Vec
<(bool
, bool
)>) -> bool
{
796 let grouper
= data
.iter().group_by(|k
| *k
/ 3);
797 let mut groups1
= grouper
.into_iter();
798 let mut groups2
= grouper
.into_iter();
799 let mut elts
= Vec
::<&u8>::new();
800 let mut old_groups
= Vec
::new();
802 let tup1
= |(_
, b
)| b
;
803 for &(ord
, consume_now
) in &order
{
804 let iter
= &mut [&mut groups1
, &mut groups2
][ord
as usize];
806 Some((_
, gr
)) => if consume_now
{
807 for og
in old_groups
.drain(..) {
817 for og
in old_groups
.drain(..) {
820 for gr
in groups1
.map(&tup1
) { elts.extend(gr); }
821 for gr
in groups2
.map(&tup1
) { elts.extend(gr); }
822 itertools
::assert_equal(&data
, elts
);
828 fn equal_chunks_lazy(a
: Vec
<u8>, size
: u8) -> bool
{
833 let chunks
= a
.iter().chunks(size
as usize);
834 let it
= a
.chunks(size
as usize);
835 for (a
, b
) in chunks
.into_iter().zip(it
) {
836 if !itertools
::equal(a
, b
) {
845 fn equal_tuple_windows_1(a
: Vec
<u8>) -> bool
{
846 let x
= a
.windows(1).map(|s
| (&s
[0], ));
847 let y
= a
.iter().tuple_windows
::<(_
,)>();
848 itertools
::equal(x
, y
)
851 fn equal_tuple_windows_2(a
: Vec
<u8>) -> bool
{
852 let x
= a
.windows(2).map(|s
| (&s
[0], &s
[1]));
853 let y
= a
.iter().tuple_windows
::<(_
, _
)>();
854 itertools
::equal(x
, y
)
857 fn equal_tuple_windows_3(a
: Vec
<u8>) -> bool
{
858 let x
= a
.windows(3).map(|s
| (&s
[0], &s
[1], &s
[2]));
859 let y
= a
.iter().tuple_windows
::<(_
, _
, _
)>();
860 itertools
::equal(x
, y
)
863 fn equal_tuple_windows_4(a
: Vec
<u8>) -> bool
{
864 let x
= a
.windows(4).map(|s
| (&s
[0], &s
[1], &s
[2], &s
[3]));
865 let y
= a
.iter().tuple_windows
::<(_
, _
, _
, _
)>();
866 itertools
::equal(x
, y
)
869 fn equal_tuples_1(a
: Vec
<u8>) -> bool
{
870 let x
= a
.chunks(1).map(|s
| (&s
[0], ));
871 let y
= a
.iter().tuples
::<(_
,)>();
872 itertools
::equal(x
, y
)
875 fn equal_tuples_2(a
: Vec
<u8>) -> bool
{
876 let x
= a
.chunks(2).filter(|s
| s
.len() == 2).map(|s
| (&s
[0], &s
[1]));
877 let y
= a
.iter().tuples
::<(_
, _
)>();
878 itertools
::equal(x
, y
)
881 fn equal_tuples_3(a
: Vec
<u8>) -> bool
{
882 let x
= a
.chunks(3).filter(|s
| s
.len() == 3).map(|s
| (&s
[0], &s
[1], &s
[2]));
883 let y
= a
.iter().tuples
::<(_
, _
, _
)>();
884 itertools
::equal(x
, y
)
887 fn equal_tuples_4(a
: Vec
<u8>) -> bool
{
888 let x
= a
.chunks(4).filter(|s
| s
.len() == 4).map(|s
| (&s
[0], &s
[1], &s
[2], &s
[3]));
889 let y
= a
.iter().tuples
::<(_
, _
, _
, _
)>();
890 itertools
::equal(x
, y
)
893 fn exact_tuple_buffer(a
: Vec
<u8>) -> bool
{
894 let mut iter
= a
.iter().tuples
::<(_
, _
, _
, _
)>();
896 let buffer
= iter
.into_buffer();
897 assert_eq
!(buffer
.len(), a
.len() % 4);
904 fn with_position_exact_size_1(a
: Vec
<u8>) -> bool
{
905 exact_size_for_this(a
.iter().with_position())
907 fn with_position_exact_size_2(a
: Iter
<u8, Exact
>) -> bool
{
908 exact_size_for_this(a
.with_position())
913 fn correct_group_map_modulo_key(a
: Vec
<u8>, modulo
: u8) -> () {
914 let modulo
= if modulo
== 0 { 1 }
else { modulo }
; // Avoid `% 0`
916 let lookup
= a
.into_iter().map(|i
| (i
% modulo
, i
)).into_group_map();
918 assert_eq
!(lookup
.values().flat_map(|vals
| vals
.iter()).count(), count
);
920 for (&key
, vals
) in lookup
.iter() {
921 assert
!(vals
.iter().all(|&val
| val
% modulo
== key
));
926 /// A peculiar type: Equality compares both tuple items, but ordering only the
927 /// first item. This is so we can check the stability property easily.
928 #[derive(Clone, Debug, PartialEq, Eq)]
929 struct Val(u32, u32);
931 impl PartialOrd
<Val
> for Val
{
932 fn partial_cmp(&self, other
: &Val
) -> Option
<Ordering
> {
933 self.0.partial_cmp(&other
.0)
938 fn cmp(&self, other
: &Val
) -> Ordering
{
943 impl qc
::Arbitrary
for Val
{
944 fn arbitrary
<G
: qc
::Gen
>(g
: &mut G
) -> Self {
945 let (x
, y
) = <(u32, u32)>::arbitrary(g
);
948 fn shrink(&self) -> Box
<Iterator
<Item
= Self>> {
949 Box
::new((self.0, self.1).shrink().map(|(x
, y
)| Val(x
, y
)))
954 fn minmax(a
: Vec
<Val
>) -> bool
{
955 use itertools
::MinMaxResult
;
958 let minmax
= a
.iter().minmax();
959 let expected
= match a
.len() {
960 0 => MinMaxResult
::NoElements
,
961 1 => MinMaxResult
::OneElement(&a
[0]),
962 _
=> MinMaxResult
::MinMax(a
.iter().min().unwrap(),
963 a
.iter().max().unwrap()),
970 fn minmax_f64(a
: Vec
<f64>) -> TestResult
{
971 use itertools
::MinMaxResult
;
973 if a
.iter().any(|x
| x
.is_nan()) {
974 return TestResult
::discard();
977 let min
= cloned(&a
).fold1(f64::min
);
978 let max
= cloned(&a
).fold1(f64::max
);
980 let minmax
= cloned(&a
).minmax();
981 let expected
= match a
.len() {
982 0 => MinMaxResult
::NoElements
,
983 1 => MinMaxResult
::OneElement(min
.unwrap()),
984 _
=> MinMaxResult
::MinMax(min
.unwrap(), max
.unwrap()),
986 TestResult
::from_bool(minmax
== expected
)
991 fn tree_fold1_f64(mut a
: Vec
<f64>) -> TestResult
{
992 fn collapse_adjacent
<F
>(x
: Vec
<f64>, mut f
: F
) -> Vec
<f64>
993 where F
: FnMut(f64, f64) -> f64
995 let mut out
= Vec
::new();
996 for i
in (0..x
.len()).step(2) {
1000 out
.push(f(x
[i
], x
[i
+1]));
1006 if a
.iter().any(|x
| x
.is_nan()) {
1007 return TestResult
::discard();
1010 let actual
= a
.iter().cloned().tree_fold1(f64::atan2
);
1013 a
= collapse_adjacent(a
, f64::atan2
);
1015 let expected
= a
.pop();
1017 TestResult
::from_bool(actual
== expected
)