123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695 |
- //! The purpose of these tests is to cover corner cases of iterators
- //! and adaptors.
- //!
- //! In particular we test the tedious size_hint and exact size correctness.
- use quickcheck as qc;
- use std::default::Default;
- use std::num::Wrapping;
- use std::ops::Range;
- use std::cmp::{max, min, Ordering};
- use std::collections::{HashMap, HashSet};
- use itertools::Itertools;
- use itertools::{
- multizip,
- EitherOrBoth,
- iproduct,
- izip,
- };
- use itertools::free::{
- cloned,
- enumerate,
- multipeek,
- peek_nth,
- put_back,
- put_back_n,
- rciter,
- zip,
- zip_eq,
- };
- use rand::Rng;
- use rand::seq::SliceRandom;
- use quickcheck::TestResult;
- /// Trait for size hint modifier types
- trait HintKind: Copy + Send + qc::Arbitrary {
- fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>);
- }
- /// Exact size hint variant that leaves hints unchanged
- #[derive(Clone, Copy, Debug)]
- struct Exact {}
- impl HintKind for Exact {
- fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) {
- org_hint
- }
- }
- impl qc::Arbitrary for Exact {
- fn arbitrary<G: qc::Gen>(_: &mut G) -> Self {
- Exact {}
- }
- }
- /// Inexact size hint variant to simulate imprecise (but valid) size hints
- ///
- /// Will always decrease the lower bound and increase the upper bound
- /// of the size hint by set amounts.
- #[derive(Clone, Copy, Debug)]
- struct Inexact {
- underestimate: usize,
- overestimate: usize,
- }
- impl HintKind for Inexact {
- fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) {
- let (org_lower, org_upper) = org_hint;
- (org_lower.saturating_sub(self.underestimate),
- org_upper.and_then(move |x| x.checked_add(self.overestimate)))
- }
- }
- impl qc::Arbitrary for Inexact {
- fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
- let ue_value = usize::arbitrary(g);
- let oe_value = usize::arbitrary(g);
- // Compensate for quickcheck using extreme values too rarely
- let ue_choices = &[0, ue_value, usize::max_value()];
- let oe_choices = &[0, oe_value, usize::max_value()];
- Inexact {
- underestimate: *ue_choices.choose(g).unwrap(),
- overestimate: *oe_choices.choose(g).unwrap(),
- }
- }
- fn shrink(&self) -> Box<dyn Iterator<Item=Self>> {
- let underestimate_value = self.underestimate;
- let overestimate_value = self.overestimate;
- Box::new(
- underestimate_value.shrink().flat_map(move |ue_value|
- overestimate_value.shrink().map(move |oe_value|
- Inexact {
- underestimate: ue_value,
- overestimate: oe_value,
- }
- )
- )
- )
- }
- }
- /// Our base iterator that we can impl Arbitrary for
- ///
- /// By default we'll return inexact bounds estimates for size_hint
- /// to make tests harder to pass.
- ///
- /// NOTE: Iter is tricky and is not fused, to help catch bugs.
- /// At the end it will return None once, then return Some(0),
- /// then return None again.
- #[derive(Clone, Debug)]
- struct Iter<T, SK: HintKind = Inexact> {
- iterator: Range<T>,
- // fuse/done flag
- fuse_flag: i32,
- hint_kind: SK,
- }
- impl<T, HK> Iter<T, HK> where HK: HintKind
- {
- fn new(it: Range<T>, hint_kind: HK) -> Self {
- Iter {
- iterator: it,
- fuse_flag: 0,
- hint_kind,
- }
- }
- }
- impl<T, HK> Iterator for Iter<T, HK>
- where Range<T>: Iterator,
- <Range<T> as Iterator>::Item: Default,
- HK: HintKind,
- {
- type Item = <Range<T> as Iterator>::Item;
- fn next(&mut self) -> Option<Self::Item>
- {
- let elt = self.iterator.next();
- if elt.is_none() {
- self.fuse_flag += 1;
- // check fuse flag
- if self.fuse_flag == 2 {
- return Some(Default::default())
- }
- }
- elt
- }
- fn size_hint(&self) -> (usize, Option<usize>)
- {
- let org_hint = self.iterator.size_hint();
- self.hint_kind.loosen_bounds(org_hint)
- }
- }
- impl<T, HK> DoubleEndedIterator for Iter<T, HK>
- where Range<T>: DoubleEndedIterator,
- <Range<T> as Iterator>::Item: Default,
- HK: HintKind
- {
- fn next_back(&mut self) -> Option<Self::Item> { self.iterator.next_back() }
- }
- impl<T> ExactSizeIterator for Iter<T, Exact> where Range<T>: ExactSizeIterator,
- <Range<T> as Iterator>::Item: Default,
- { }
- impl<T, HK> qc::Arbitrary for Iter<T, HK>
- where T: qc::Arbitrary,
- HK: HintKind,
- {
- fn arbitrary<G: qc::Gen>(g: &mut G) -> Self
- {
- Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g))
- }
- fn shrink(&self) -> Box<dyn Iterator<Item=Iter<T, HK>>>
- {
- let r = self.iterator.clone();
- let hint_kind = self.hint_kind;
- Box::new(
- r.start.shrink().flat_map(move |a|
- r.end.shrink().map(move |b|
- Iter::new(a.clone()..b, hint_kind)
- )
- )
- )
- }
- }
- /// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are
- /// increased or decreased linearly on each iteration.
- #[derive(Clone, Debug)]
- struct ShiftRange<HK = Inexact> {
- range_start: i32,
- range_end: i32,
- start_step: i32,
- end_step: i32,
- iter_count: u32,
- hint_kind: HK,
- }
- impl<HK> Iterator for ShiftRange<HK> where HK: HintKind {
- type Item = Iter<i32, HK>;
- fn next(&mut self) -> Option<Self::Item> {
- if self.iter_count == 0 {
- return None;
- }
- let iter = Iter::new(self.range_start..self.range_end, self.hint_kind);
- self.range_start += self.start_step;
- self.range_end += self.end_step;
- self.iter_count -= 1;
- Some(iter)
- }
- }
- impl ExactSizeIterator for ShiftRange<Exact> { }
- impl<HK> qc::Arbitrary for ShiftRange<HK>
- where HK: HintKind
- {
- fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
- const MAX_STARTING_RANGE_DIFF: i32 = 32;
- const MAX_STEP_MODULO: i32 = 8;
- const MAX_ITER_COUNT: u32 = 3;
- let range_start = qc::Arbitrary::arbitrary(g);
- let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1);
- let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1);
- let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1);
- let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1);
- let hint_kind = qc::Arbitrary::arbitrary(g);
- ShiftRange {
- range_start,
- range_end,
- start_step,
- end_step,
- iter_count,
- hint_kind,
- }
- }
- }
- fn correct_count<I, F>(get_it: F) -> bool
- where
- I: Iterator,
- F: Fn() -> I
- {
- let mut counts = vec![get_it().count()];
- 'outer: loop {
- let mut it = get_it();
- for _ in 0..(counts.len() - 1) {
- if let None = it.next() {
- panic!("Iterator shouldn't be finished, may not be deterministic");
- }
- }
- if let None = it.next() {
- break 'outer;
- }
- counts.push(it.count());
- }
- let total_actual_count = counts.len() - 1;
- for (i, returned_count) in counts.into_iter().enumerate() {
- let actual_count = total_actual_count - i;
- if actual_count != returned_count {
- println!("Total iterations: {} True count: {} returned count: {}", i, actual_count, returned_count);
- return false;
- }
- }
- true
- }
- fn correct_size_hint<I: Iterator>(mut it: I) -> bool {
- // record size hint at each iteration
- let initial_hint = it.size_hint();
- let mut hints = Vec::with_capacity(initial_hint.0 + 1);
- hints.push(initial_hint);
- while let Some(_) = it.next() {
- hints.push(it.size_hint())
- }
- let mut true_count = hints.len(); // start off +1 too much
- // check all the size hints
- for &(low, hi) in &hints {
- true_count -= 1;
- if low > true_count ||
- (hi.is_some() && hi.unwrap() < true_count)
- {
- println!("True size: {:?}, size hint: {:?}", true_count, (low, hi));
- //println!("All hints: {:?}", hints);
- return false
- }
- }
- true
- }
- fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
- // check every iteration
- let (mut low, mut hi) = it.size_hint();
- if Some(low) != hi { return false; }
- while let Some(_) = it.next() {
- let (xlow, xhi) = it.size_hint();
- if low != xlow + 1 { return false; }
- low = xlow;
- hi = xhi;
- if Some(low) != hi { return false; }
- }
- let (low, hi) = it.size_hint();
- low == 0 && hi == Some(0)
- }
- // Exact size for this case, without ExactSizeIterator
- fn exact_size_for_this<I: Iterator>(mut it: I) -> bool {
- // check every iteration
- let (mut low, mut hi) = it.size_hint();
- if Some(low) != hi { return false; }
- while let Some(_) = it.next() {
- let (xlow, xhi) = it.size_hint();
- if low != xlow + 1 { return false; }
- low = xlow;
- hi = xhi;
- if Some(low) != hi { return false; }
- }
- let (low, hi) = it.size_hint();
- low == 0 && hi == Some(0)
- }
- /*
- * NOTE: Range<i8> is broken!
- * (all signed ranges are)
- #[quickcheck]
- fn size_range_i8(a: Iter<i8>) -> bool {
- exact_size(a)
- }
- #[quickcheck]
- fn size_range_i16(a: Iter<i16>) -> bool {
- exact_size(a)
- }
- #[quickcheck]
- fn size_range_u8(a: Iter<u8>) -> bool {
- exact_size(a)
- }
- */
- macro_rules! quickcheck {
- // accept several property function definitions
- // The property functions can use pattern matching and `mut` as usual
- // in the function arguments, but the functions can not be generic.
- {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => (
- $(
- #[test]
- $(#$attr)*
- fn $fn_name() {
- fn prop($($arg)*) -> $ret {
- $($code)*
- }
- ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*));
- }
- )*
- );
- // parse argument list (with patterns allowed) into prop as fn(_, _) -> _
- (@fn $f:ident [$($t:tt)*]) => {
- $f as fn($($t),*) -> _
- };
- (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => {
- quickcheck!(@fn $f [$($p)* _] $($tail)*)
- };
- (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => {
- quickcheck!(@fn $f [$($p)*] $($tail)*)
- };
- }
- quickcheck! {
- fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
- correct_size_hint(a.cartesian_product(b))
- }
- fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
- correct_size_hint(iproduct!(a, b, c))
- }
- fn correct_cartesian_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>,
- take_manual: usize) -> ()
- {
- // test correctness of iproduct through regular iteration (take)
- // and through fold.
- let ac = a.clone();
- let br = &b.clone();
- let cr = &c.clone();
- let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect();
- let mut product_iter = iproduct!(a, b, c);
- let mut actual = Vec::new();
- actual.extend((&mut product_iter).take(take_manual));
- if actual.len() == take_manual {
- product_iter.fold((), |(), elt| actual.push(elt));
- }
- assert_eq!(answer, actual);
- }
- fn size_multi_product(a: ShiftRange) -> bool {
- correct_size_hint(a.multi_cartesian_product())
- }
- fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () {
- // Fix no. of iterators at 3
- let a = ShiftRange { iter_count: 3, ..a };
- // test correctness of MultiProduct through regular iteration (take)
- // and through fold.
- let mut iters = a.clone();
- let i0 = iters.next().unwrap();
- let i1r = &iters.next().unwrap();
- let i2r = &iters.next().unwrap();
- let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect();
- let mut multi_product = a.clone().multi_cartesian_product();
- let mut actual = Vec::new();
- actual.extend((&mut multi_product).take(take_manual));
- if actual.len() == take_manual {
- multi_product.fold((), |(), elt| actual.push(elt));
- }
- assert_eq!(answer, actual);
- assert_eq!(answer.into_iter().last(), a.clone().multi_cartesian_product().last());
- }
- #[allow(deprecated)]
- fn size_step(a: Iter<i16, Exact>, s: usize) -> bool {
- let mut s = s;
- if s == 0 {
- s += 1; // never zero
- }
- let filt = a.clone().dedup();
- correct_size_hint(filt.step(s)) &&
- exact_size(a.step(s))
- }
- #[allow(deprecated)]
- fn equal_step(a: Iter<i16>, s: usize) -> bool {
- let mut s = s;
- if s == 0 {
- s += 1; // never zero
- }
- let mut i = 0;
- itertools::equal(a.clone().step(s), a.filter(|_| {
- let keep = i % s == 0;
- i += 1;
- keep
- }))
- }
- #[allow(deprecated)]
- fn equal_step_vec(a: Vec<i16>, s: usize) -> bool {
- let mut s = s;
- if s == 0 {
- s += 1; // never zero
- }
- let mut i = 0;
- itertools::equal(a.iter().step(s), a.iter().filter(|_| {
- let keep = i % s == 0;
- i += 1;
- keep
- }))
- }
- fn size_multipeek(a: Iter<u16, Exact>, s: u8) -> bool {
- let mut it = multipeek(a);
- // peek a few times
- for _ in 0..s {
- it.peek();
- }
- exact_size(it)
- }
- fn size_peek_nth(a: Iter<u16, Exact>, s: u8) -> bool {
- let mut it = peek_nth(a);
- // peek a few times
- for n in 0..s {
- it.peek_nth(n as usize);
- }
- exact_size(it)
- }
- fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
- let mut sa = a.clone();
- let mut sb = b.clone();
- sa.sort();
- sb.sort();
- let mut merged = sa.clone();
- merged.extend(sb.iter().cloned());
- merged.sort();
- itertools::equal(&merged, sa.iter().merge(&sb))
- }
- fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
- correct_size_hint(a.merge(b))
- }
- fn size_zip(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool {
- let filt = a.clone().dedup();
- correct_size_hint(multizip((filt, b.clone(), c.clone()))) &&
- exact_size(multizip((a, b, c)))
- }
- fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool {
- let rc = rciter(a.clone());
- correct_size_hint(multizip((&rc, &rc, b)))
- }
- fn size_zip_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool {
- let filt = a.clone().dedup();
- correct_size_hint(izip!(filt, b.clone(), c.clone())) &&
- exact_size(izip!(a, b, c))
- }
- fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool {
- use itertools::free::kmerge;
- let mut sa = a.clone();
- let mut sb = b.clone();
- let mut sc = c.clone();
- sa.sort();
- sb.sort();
- sc.sort();
- let mut merged = sa.clone();
- merged.extend(sb.iter().cloned());
- merged.extend(sc.iter().cloned());
- merged.sort();
- itertools::equal(merged.into_iter(), kmerge(vec![sa, sb, sc]))
- }
- // Any number of input iterators
- fn equal_kmerge_2(mut inputs: Vec<Vec<i16>>) -> bool {
- use itertools::free::kmerge;
- // sort the inputs
- for input in &mut inputs {
- input.sort();
- }
- let mut merged = inputs.concat();
- merged.sort();
- itertools::equal(merged.into_iter(), kmerge(inputs))
- }
- // Any number of input iterators
- fn equal_kmerge_by_ge(mut inputs: Vec<Vec<i16>>) -> bool {
- // sort the inputs
- for input in &mut inputs {
- input.sort();
- input.reverse();
- }
- let mut merged = inputs.concat();
- merged.sort();
- merged.reverse();
- itertools::equal(merged.into_iter(),
- inputs.into_iter().kmerge_by(|x, y| x >= y))
- }
- // Any number of input iterators
- fn equal_kmerge_by_lt(mut inputs: Vec<Vec<i16>>) -> bool {
- // sort the inputs
- for input in &mut inputs {
- input.sort();
- }
- let mut merged = inputs.concat();
- merged.sort();
- itertools::equal(merged.into_iter(),
- inputs.into_iter().kmerge_by(|x, y| x < y))
- }
- // Any number of input iterators
- fn equal_kmerge_by_le(mut inputs: Vec<Vec<i16>>) -> bool {
- // sort the inputs
- for input in &mut inputs {
- input.sort();
- }
- let mut merged = inputs.concat();
- merged.sort();
- itertools::equal(merged.into_iter(),
- inputs.into_iter().kmerge_by(|x, y| x <= y))
- }
- fn size_kmerge(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
- use itertools::free::kmerge;
- correct_size_hint(kmerge(vec![a, b, c]))
- }
- fn equal_zip_eq(a: Vec<i32>, b: Vec<i32>) -> bool {
- let len = std::cmp::min(a.len(), b.len());
- let a = &a[..len];
- let b = &b[..len];
- itertools::equal(zip_eq(a, b), zip(a, b))
- }
- fn size_zip_longest(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool {
- let filt = a.clone().dedup();
- let filt2 = b.clone().dedup();
- correct_size_hint(filt.zip_longest(b.clone())) &&
- correct_size_hint(a.clone().zip_longest(filt2)) &&
- exact_size(a.zip_longest(b))
- }
- fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
- let it = a.clone().zip_longest(b.clone());
- let jt = a.clone().zip_longest(b.clone());
- itertools::equal(a.clone(),
- it.filter_map(|elt| match elt {
- EitherOrBoth::Both(x, _) => Some(x),
- EitherOrBoth::Left(x) => Some(x),
- _ => None,
- }
- ))
- &&
- itertools::equal(b.clone(),
- jt.filter_map(|elt| match elt {
- EitherOrBoth::Both(_, y) => Some(y),
- EitherOrBoth::Right(y) => Some(y),
- _ => None,
- }
- ))
- }
- fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
- correct_size_hint(a.interleave(b))
- }
- fn exact_interleave(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool {
- exact_size_for_this(a.interleave(b))
- }
- fn size_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool {
- correct_size_hint(a.interleave_shortest(b))
- }
- fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool {
- exact_size_for_this(a.iter().interleave_shortest(&b))
- }
- fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
- correct_size_hint(a.intersperse(x))
- }
- fn equal_intersperse(a: Vec<i32>, x: i32) -> bool {
- let mut inter = false;
- let mut i = 0;
- for elt in a.iter().cloned().intersperse(x) {
- if inter {
- if elt != x { return false }
- } else {
- if elt != a[i] { return false }
- i += 1;
- }
- inter = !inter;
- }
- true
- }
- fn equal_combinations_2(a: Vec<u8>) -> bool {
- let mut v = Vec::new();
- for (i, x) in enumerate(&a) {
- for y in &a[i + 1..] {
- v.push((x, y));
- }
- }
- itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v)
- }
- fn collect_tuple_matches_size(a: Iter<i16>) -> bool {
- let size = a.clone().count();
- a.collect_tuple::<(_, _, _)>().is_some() == (size == 3)
- }
- fn correct_permutations(vals: HashSet<i32>, k: usize) -> () {
- // Test permutations only on iterators of distinct integers, to prevent
- // false positives.
- const MAX_N: usize = 5;
- let n = min(vals.len(), MAX_N);
- let vals: HashSet<i32> = vals.into_iter().take(n).collect();
- let perms = vals.iter().permutations(k);
- let mut actual = HashSet::new();
- for perm in perms {
- assert_eq!(perm.len(), k);
- let all_items_valid = perm.iter().all(|p| vals.contains(p));
- assert!(all_items_valid, "perm contains value not from input: {:?}", perm);
- // Check that all perm items are distinct
- let distinct_len = {
- let perm_set: HashSet<_> = perm.iter().collect();
- perm_set.len()
- };
- assert_eq!(perm.len(), distinct_len);
- // Check that the perm is new
- assert!(actual.insert(perm.clone()), "perm already encountered: {:?}", perm);
- }
- }
- fn permutations_lexic_order(a: usize, b: usize) -> () {
- let a = a % 6;
- let b = b % 6;
- let n = max(a, b);
- let k = min (a, b);
- let expected_first: Vec<usize> = (0..k).collect();
- let expected_last: Vec<usize> = ((n - k)..n).rev().collect();
- let mut perms = (0..n).permutations(k);
- let mut curr_perm = match perms.next() {
- Some(p) => p,
- None => { return; }
- };
- assert_eq!(expected_first, curr_perm);
- while let Some(next_perm) = perms.next() {
- assert!(
- next_perm > curr_perm,
- "next perm isn't greater-than current; next_perm={:?} curr_perm={:?} n={}",
- next_perm, curr_perm, n
- );
- curr_perm = next_perm;
- }
- assert_eq!(expected_last, curr_perm);
- }
- fn permutations_count(n: usize, k: usize) -> bool {
- let n = n % 6;
- correct_count(|| (0..n).permutations(k))
- }
- fn permutations_size(a: Iter<i32>, k: usize) -> bool {
- correct_size_hint(a.take(5).permutations(k))
- }
- fn permutations_k0_yields_once(n: usize) -> () {
- let k = 0;
- let expected: Vec<Vec<usize>> = vec![vec![]];
- let actual = (0..n).permutations(k).collect_vec();
- assert_eq!(expected, actual);
- }
- }
- quickcheck! {
- fn dedup_via_coalesce(a: Vec<i32>) -> bool {
- let mut b = a.clone();
- b.dedup();
- itertools::equal(
- &b,
- a
- .iter()
- .coalesce(|x, y| {
- if x==y {
- Ok(x)
- } else {
- Err((x, y))
- }
- })
- .fold(vec![], |mut v, n| {
- v.push(n);
- v
- })
- )
- }
- }
- quickcheck! {
- fn equal_dedup(a: Vec<i32>) -> bool {
- let mut b = a.clone();
- b.dedup();
- itertools::equal(&b, a.iter().dedup())
- }
- }
- quickcheck! {
- fn equal_dedup_by(a: Vec<(i32, i32)>) -> bool {
- let mut b = a.clone();
- b.dedup_by(|x, y| x.0==y.0);
- itertools::equal(&b, a.iter().dedup_by(|x, y| x.0==y.0))
- }
- }
- quickcheck! {
- fn size_dedup(a: Vec<i32>) -> bool {
- correct_size_hint(a.iter().dedup())
- }
- }
- quickcheck! {
- fn size_dedup_by(a: Vec<(i32, i32)>) -> bool {
- correct_size_hint(a.iter().dedup_by(|x, y| x.0==y.0))
- }
- }
- quickcheck! {
- fn exact_repeatn((n, x): (usize, i32)) -> bool {
- let it = itertools::repeat_n(x, n);
- exact_size(it)
- }
- }
- quickcheck! {
- fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool {
- let mut it = put_back(a.into_iter());
- match x {
- Some(t) => it.put_back(t),
- None => {}
- }
- correct_size_hint(it)
- }
- }
- quickcheck! {
- fn size_put_backn(a: Vec<u8>, b: Vec<u8>) -> bool {
- let mut it = put_back_n(a.into_iter());
- for elt in b {
- it.put_back(elt)
- }
- correct_size_hint(it)
- }
- }
- quickcheck! {
- fn size_tee(a: Vec<u8>) -> bool {
- let (mut t1, mut t2) = a.iter().tee();
- t1.next();
- t1.next();
- t2.next();
- exact_size(t1) && exact_size(t2)
- }
- }
- quickcheck! {
- fn size_tee_2(a: Vec<u8>) -> bool {
- let (mut t1, mut t2) = a.iter().dedup().tee();
- t1.next();
- t1.next();
- t2.next();
- correct_size_hint(t1) && correct_size_hint(t2)
- }
- }
- quickcheck! {
- fn size_take_while_ref(a: Vec<u8>, stop: u8) -> bool {
- correct_size_hint(a.iter().take_while_ref(|x| **x != stop))
- }
- }
- quickcheck! {
- fn equal_partition(a: Vec<i32>) -> bool {
- let mut a = a;
- let mut ap = a.clone();
- let split_index = itertools::partition(&mut ap, |x| *x >= 0);
- let parted = (0..split_index).all(|i| ap[i] >= 0) &&
- (split_index..a.len()).all(|i| ap[i] < 0);
- a.sort();
- ap.sort();
- parted && (a == ap)
- }
- }
- quickcheck! {
- fn size_combinations(it: Iter<i16>) -> bool {
- correct_size_hint(it.tuple_combinations::<(_, _)>())
- }
- }
- quickcheck! {
- fn equal_combinations(it: Iter<i16>) -> bool {
- let values = it.clone().collect_vec();
- let mut cmb = it.tuple_combinations();
- for i in 0..values.len() {
- for j in i+1..values.len() {
- let pair = (values[i], values[j]);
- if pair != cmb.next().unwrap() {
- return false;
- }
- }
- }
- cmb.next() == None
- }
- }
- quickcheck! {
- fn size_pad_tail(it: Iter<i8>, pad: u8) -> bool {
- correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) &&
- correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0))
- }
- }
- quickcheck! {
- fn size_pad_tail2(it: Iter<i8, Exact>, pad: u8) -> bool {
- exact_size(it.pad_using(pad as usize, |_| 0))
- }
- }
- quickcheck! {
- fn size_powerset(it: Iter<u8, Exact>) -> bool {
- // Powerset cardinality gets large very quickly, limit input to keep test fast.
- correct_size_hint(it.take(12).powerset())
- }
- }
- quickcheck! {
- fn size_duplicates(it: Iter<i8>) -> bool {
- correct_size_hint(it.duplicates())
- }
- }
- quickcheck! {
- fn size_unique(it: Iter<i8>) -> bool {
- correct_size_hint(it.unique())
- }
- fn count_unique(it: Vec<i8>, take_first: u8) -> () {
- let answer = {
- let mut v = it.clone();
- v.sort(); v.dedup();
- v.len()
- };
- let mut iter = cloned(&it).unique();
- let first_count = (&mut iter).take(take_first as usize).count();
- let rest_count = iter.count();
- assert_eq!(answer, first_count + rest_count);
- }
- }
- quickcheck! {
- fn fuzz_group_by_lazy_1(it: Iter<u8>) -> bool {
- let jt = it.clone();
- let groups = it.group_by(|k| *k);
- let res = itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x));
- res
- }
- }
- quickcheck! {
- fn fuzz_group_by_lazy_2(data: Vec<u8>) -> bool {
- let groups = data.iter().group_by(|k| *k / 10);
- let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x));
- res
- }
- }
- quickcheck! {
- fn fuzz_group_by_lazy_3(data: Vec<u8>) -> bool {
- let grouper = data.iter().group_by(|k| *k / 10);
- let groups = grouper.into_iter().collect_vec();
- let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x));
- res
- }
- }
- quickcheck! {
- fn fuzz_group_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool {
- let grouper = data.iter().group_by(|k| *k / 3);
- let mut groups1 = grouper.into_iter();
- let mut groups2 = grouper.into_iter();
- let mut elts = Vec::<&u8>::new();
- let mut old_groups = Vec::new();
- let tup1 = |(_, b)| b;
- for &(ord, consume_now) in &order {
- let iter = &mut [&mut groups1, &mut groups2][ord as usize];
- match iter.next() {
- Some((_, gr)) => if consume_now {
- for og in old_groups.drain(..) {
- elts.extend(og);
- }
- elts.extend(gr);
- } else {
- old_groups.push(gr);
- },
- None => break,
- }
- }
- for og in old_groups.drain(..) {
- elts.extend(og);
- }
- for gr in groups1.map(&tup1) { elts.extend(gr); }
- for gr in groups2.map(&tup1) { elts.extend(gr); }
- itertools::assert_equal(&data, elts);
- true
- }
- }
- quickcheck! {
- fn equal_chunks_lazy(a: Vec<u8>, size: u8) -> bool {
- let mut size = size;
- if size == 0 {
- size += 1;
- }
- let chunks = a.iter().chunks(size as usize);
- let it = a.chunks(size as usize);
- for (a, b) in chunks.into_iter().zip(it) {
- if !itertools::equal(a, b) {
- return false;
- }
- }
- true
- }
- }
- quickcheck! {
- fn equal_tuple_windows_1(a: Vec<u8>) -> bool {
- let x = a.windows(1).map(|s| (&s[0], ));
- let y = a.iter().tuple_windows::<(_,)>();
- itertools::equal(x, y)
- }
- fn equal_tuple_windows_2(a: Vec<u8>) -> bool {
- let x = a.windows(2).map(|s| (&s[0], &s[1]));
- let y = a.iter().tuple_windows::<(_, _)>();
- itertools::equal(x, y)
- }
- fn equal_tuple_windows_3(a: Vec<u8>) -> bool {
- let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2]));
- let y = a.iter().tuple_windows::<(_, _, _)>();
- itertools::equal(x, y)
- }
- fn equal_tuple_windows_4(a: Vec<u8>) -> bool {
- let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3]));
- let y = a.iter().tuple_windows::<(_, _, _, _)>();
- itertools::equal(x, y)
- }
- fn equal_tuples_1(a: Vec<u8>) -> bool {
- let x = a.chunks(1).map(|s| (&s[0], ));
- let y = a.iter().tuples::<(_,)>();
- itertools::equal(x, y)
- }
- fn equal_tuples_2(a: Vec<u8>) -> bool {
- let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1]));
- let y = a.iter().tuples::<(_, _)>();
- itertools::equal(x, y)
- }
- fn equal_tuples_3(a: Vec<u8>) -> bool {
- let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2]));
- let y = a.iter().tuples::<(_, _, _)>();
- itertools::equal(x, y)
- }
- fn equal_tuples_4(a: Vec<u8>) -> bool {
- let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3]));
- let y = a.iter().tuples::<(_, _, _, _)>();
- itertools::equal(x, y)
- }
- fn exact_tuple_buffer(a: Vec<u8>) -> bool {
- let mut iter = a.iter().tuples::<(_, _, _, _)>();
- (&mut iter).last();
- let buffer = iter.into_buffer();
- assert_eq!(buffer.len(), a.len() % 4);
- exact_size(buffer)
- }
- }
- // with_position
- quickcheck! {
- fn with_position_exact_size_1(a: Vec<u8>) -> bool {
- exact_size_for_this(a.iter().with_position())
- }
- fn with_position_exact_size_2(a: Iter<u8, Exact>) -> bool {
- exact_size_for_this(a.with_position())
- }
- }
- quickcheck! {
- fn correct_group_map_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let count = a.len();
- let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map();
- assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count);
- for (&key, vals) in lookup.iter() {
- assert!(vals.iter().all(|&val| val % modulo == key));
- }
- }
- }
- /// A peculiar type: Equality compares both tuple items, but ordering only the
- /// first item. This is so we can check the stability property easily.
- #[derive(Clone, Debug, PartialEq, Eq)]
- struct Val(u32, u32);
- impl PartialOrd<Val> for Val {
- fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
- self.0.partial_cmp(&other.0)
- }
- }
- impl Ord for Val {
- fn cmp(&self, other: &Val) -> Ordering {
- self.0.cmp(&other.0)
- }
- }
- impl qc::Arbitrary for Val {
- fn arbitrary<G: qc::Gen>(g: &mut G) -> Self {
- let (x, y) = <(u32, u32)>::arbitrary(g);
- Val(x, y)
- }
- fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
- Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y)))
- }
- }
- quickcheck! {
- fn minmax(a: Vec<Val>) -> bool {
- use itertools::MinMaxResult;
- let minmax = a.iter().minmax();
- let expected = match a.len() {
- 0 => MinMaxResult::NoElements,
- 1 => MinMaxResult::OneElement(&a[0]),
- _ => MinMaxResult::MinMax(a.iter().min().unwrap(),
- a.iter().max().unwrap()),
- };
- minmax == expected
- }
- }
- quickcheck! {
- fn minmax_f64(a: Vec<f64>) -> TestResult {
- use itertools::MinMaxResult;
- if a.iter().any(|x| x.is_nan()) {
- return TestResult::discard();
- }
- let min = cloned(&a).fold1(f64::min);
- let max = cloned(&a).fold1(f64::max);
- let minmax = cloned(&a).minmax();
- let expected = match a.len() {
- 0 => MinMaxResult::NoElements,
- 1 => MinMaxResult::OneElement(min.unwrap()),
- _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()),
- };
- TestResult::from_bool(minmax == expected)
- }
- }
- quickcheck! {
- #[allow(deprecated)]
- fn tree_fold1_f64(mut a: Vec<f64>) -> TestResult {
- fn collapse_adjacent<F>(x: Vec<f64>, mut f: F) -> Vec<f64>
- where F: FnMut(f64, f64) -> f64
- {
- let mut out = Vec::new();
- for i in (0..x.len()).step(2) {
- if i == x.len()-1 {
- out.push(x[i])
- } else {
- out.push(f(x[i], x[i+1]));
- }
- }
- out
- }
- if a.iter().any(|x| x.is_nan()) {
- return TestResult::discard();
- }
- let actual = a.iter().cloned().tree_fold1(f64::atan2);
- while a.len() > 1 {
- a = collapse_adjacent(a, f64::atan2);
- }
- let expected = a.pop();
- TestResult::from_bool(actual == expected)
- }
- }
- quickcheck! {
- fn exactly_one_i32(a: Vec<i32>) -> TestResult {
- let ret = a.iter().cloned().exactly_one();
- match a.len() {
- 1 => TestResult::from_bool(ret.unwrap() == a[0]),
- _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())),
- }
- }
- }
- quickcheck! {
- fn at_most_one_i32(a: Vec<i32>) -> TestResult {
- let ret = a.iter().cloned().at_most_one();
- match a.len() {
- 0 => TestResult::from_bool(ret.unwrap() == None),
- 1 => TestResult::from_bool(ret.unwrap() == Some(a[0])),
- _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())),
- }
- }
- }
- quickcheck! {
- fn consistent_grouping_map_with_by(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup_grouping_map = a.iter().copied().map(|i| (i % modulo, i)).into_grouping_map().collect::<Vec<_>>();
- let lookup_grouping_map_by = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::<Vec<_>>();
- assert_eq!(lookup_grouping_map, lookup_grouping_map_by);
- }
- fn correct_grouping_map_by_aggregate_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo < 2 { 2 } else { modulo } as u64; // Avoid `% 0`
- let lookup = a.iter()
- .map(|&b| b as u64) // Avoid overflows
- .into_grouping_map_by(|i| i % modulo)
- .aggregate(|acc, &key, val| {
- assert!(val % modulo == key);
- if val % (modulo - 1) == 0 {
- None
- } else {
- Some(acc.unwrap_or(0) + val)
- }
- });
-
- let group_map_lookup = a.iter()
- .map(|&b| b as u64)
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .filter_map(|(key, vals)| {
- vals.into_iter().fold(None, |acc, val| {
- if val % (modulo - 1) == 0 {
- None
- } else {
- Some(acc.unwrap_or(0) + val)
- }
- }).map(|new_val| (key, new_val))
- })
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for m in 0..modulo {
- assert_eq!(
- lookup.get(&m).copied(),
- a.iter()
- .map(|&b| b as u64)
- .filter(|&val| val % modulo == m)
- .fold(None, |acc, val| {
- if val % (modulo - 1) == 0 {
- None
- } else {
- Some(acc.unwrap_or(0) + val)
- }
- })
- );
- }
- }
- fn correct_grouping_map_by_fold_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
- let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
- .into_grouping_map_by(|i| i % modulo)
- .fold(0u64, |acc, &key, val| {
- assert!(val % modulo == key);
- acc + val
- });
- let group_map_lookup = a.iter()
- .map(|&b| b as u64)
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().fold(0u64, |acc, val| acc + val)))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &sum) in lookup.iter() {
- assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
- }
- }
- fn correct_grouping_map_by_fold_first_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
- let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
- .into_grouping_map_by(|i| i % modulo)
- .fold_first(|acc, &key, val| {
- assert!(val % modulo == key);
- acc + val
- });
- // TODO: Swap `fold1` with stdlib's `fold_first` when it's stabilized
- let group_map_lookup = a.iter()
- .map(|&b| b as u64)
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().fold1(|acc, val| acc + val).unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &sum) in lookup.iter() {
- assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
- }
- }
- fn correct_grouping_map_by_collect_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup_grouping_map = a.iter().copied().into_grouping_map_by(|i| i % modulo).collect::<Vec<_>>();
- let lookup_group_map = a.iter().copied().map(|i| (i % modulo, i)).into_group_map();
- assert_eq!(lookup_grouping_map, lookup_group_map);
- }
- fn correct_grouping_map_by_max_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max();
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().max().unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &max) in lookup.iter() {
- assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max());
- }
- }
- fn correct_grouping_map_by_max_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by(|_, v1, v2| v1.cmp(v2));
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().max_by(|v1, v2| v1.cmp(v2)).unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &max) in lookup.iter() {
- assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by(|v1, v2| v1.cmp(v2)));
- }
- }
- fn correct_grouping_map_by_max_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).max_by_key(|_, &val| val);
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().max_by_key(|&val| val).unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &max) in lookup.iter() {
- assert_eq!(Some(max), a.iter().copied().filter(|&val| val % modulo == key).max_by_key(|&val| val));
- }
- }
-
- fn correct_grouping_map_by_min_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min();
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().min().unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &min) in lookup.iter() {
- assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min());
- }
- }
- fn correct_grouping_map_by_min_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by(|_, v1, v2| v1.cmp(v2));
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().min_by(|v1, v2| v1.cmp(v2)).unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &min) in lookup.iter() {
- assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by(|v1, v2| v1.cmp(v2)));
- }
- }
- fn correct_grouping_map_by_min_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).min_by_key(|_, &val| val);
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().min_by_key(|&val| val).unwrap()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &min) in lookup.iter() {
- assert_eq!(Some(min), a.iter().copied().filter(|&val| val % modulo == key).min_by_key(|&val| val));
- }
- }
-
- fn correct_grouping_map_by_minmax_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax();
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().minmax()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &minmax) in lookup.iter() {
- assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax());
- }
- }
- fn correct_grouping_map_by_minmax_by_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by(|_, v1, v2| v1.cmp(v2));
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().minmax_by(|v1, v2| v1.cmp(v2))))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &minmax) in lookup.iter() {
- assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by(|v1, v2| v1.cmp(v2)));
- }
- }
- fn correct_grouping_map_by_minmax_by_key_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0`
- let lookup = a.iter().copied().into_grouping_map_by(|i| i % modulo).minmax_by_key(|_, &val| val);
- let group_map_lookup = a.iter().copied()
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().minmax_by_key(|&val| val)))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &minmax) in lookup.iter() {
- assert_eq!(minmax, a.iter().copied().filter(|&val| val % modulo == key).minmax_by_key(|&val| val));
- }
- }
- fn correct_grouping_map_by_sum_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = if modulo == 0 { 1 } else { modulo } as u64; // Avoid `% 0`
- let lookup = a.iter().map(|&b| b as u64) // Avoid overflows
- .into_grouping_map_by(|i| i % modulo)
- .sum();
- let group_map_lookup = a.iter().map(|&b| b as u64)
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().sum()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &sum) in lookup.iter() {
- assert_eq!(sum, a.iter().map(|&b| b as u64).filter(|&val| val % modulo == key).sum::<u64>());
- }
- }
- fn correct_grouping_map_by_product_modulo_key(a: Vec<u8>, modulo: u8) -> () {
- let modulo = Wrapping(if modulo == 0 { 1 } else { modulo } as u64); // Avoid `% 0`
- let lookup = a.iter().map(|&b| Wrapping(b as u64)) // Avoid overflows
- .into_grouping_map_by(|i| i % modulo)
- .product();
- let group_map_lookup = a.iter().map(|&b| Wrapping(b as u64))
- .map(|i| (i % modulo, i))
- .into_group_map()
- .into_iter()
- .map(|(key, vals)| (key, vals.into_iter().product::<Wrapping<u64>>()))
- .collect::<HashMap<_,_>>();
- assert_eq!(lookup, group_map_lookup);
- for (&key, &prod) in lookup.iter() {
- assert_eq!(
- prod,
- a.iter()
- .map(|&b| Wrapping(b as u64))
- .filter(|&val| val % modulo == key)
- .product::<Wrapping<u64>>()
- );
- }
- }
- // This should check that if multiple elements are equally minimum or maximum
- // then `max`, `min` and `minmax` pick the first minimum and the last maximum.
- // This is to be consistent with `std::iter::max` and `std::iter::min`.
- fn correct_grouping_map_by_min_max_minmax_order_modulo_key() -> () {
- use itertools::MinMaxResult;
- let lookup = (0..=10)
- .into_grouping_map_by(|_| 0)
- .max_by(|_, _, _| Ordering::Equal);
- assert_eq!(lookup[&0], 10);
- let lookup = (0..=10)
- .into_grouping_map_by(|_| 0)
- .min_by(|_, _, _| Ordering::Equal);
- assert_eq!(lookup[&0], 0);
-
- let lookup = (0..=10)
- .into_grouping_map_by(|_| 0)
- .minmax_by(|_, _, _| Ordering::Equal);
- assert_eq!(lookup[&0], MinMaxResult::MinMax(0, 10));
- }
- }
- quickcheck! {
- #[test]
- fn counts(nums: Vec<isize>) -> TestResult {
- let counts = nums.iter().counts();
- for (&item, &count) in counts.iter() {
- if count <= 0 {
- return TestResult::failed();
- }
- if count != nums.iter().filter(|&x| x == item).count() {
- return TestResult::failed();
- }
- }
- for item in nums.iter() {
- if !counts.contains_key(item) {
- return TestResult::failed();
- }
- }
- TestResult::passed()
- }
- }
- quickcheck! {
- fn test_double_ended_zip_2(a: Vec<u8>, b: Vec<u8>) -> TestResult {
- let mut x =
- multizip((a.clone().into_iter(), b.clone().into_iter()))
- .collect_vec();
- x.reverse();
- let y =
- multizip((a.into_iter(), b.into_iter()))
- .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec });
- TestResult::from_bool(itertools::equal(x, y))
- }
- fn test_double_ended_zip_3(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> TestResult {
- let mut x =
- multizip((a.clone().into_iter(), b.clone().into_iter(), c.clone().into_iter()))
- .collect_vec();
- x.reverse();
- let y =
- multizip((a.into_iter(), b.into_iter(), c.into_iter()))
- .rfold(Vec::new(), |mut vec, e| { vec.push(e); vec });
- TestResult::from_bool(itertools::equal(x, y))
- }
- }
- fn is_fused<I: Iterator>(mut it: I) -> bool
- {
- while let Some(_) = it.next() {}
- for _ in 0..10{
- if it.next().is_some(){
- return false;
- }
- }
- true
- }
- quickcheck! {
- fn fused_combination(a: Iter<i16>) -> bool
- {
- is_fused(a.clone().combinations(1)) &&
- is_fused(a.combinations(3))
- }
- fn fused_combination_with_replacement(a: Iter<i16>) -> bool
- {
- is_fused(a.clone().combinations_with_replacement(1)) &&
- is_fused(a.combinations_with_replacement(3))
- }
- fn fused_tuple_combination(a: Iter<i16>) -> bool
- {
- is_fused(a.clone().fuse().tuple_combinations::<(_,)>()) &&
- is_fused(a.fuse().tuple_combinations::<(_,_,_)>())
- }
- fn fused_unique(a: Iter<i16>) -> bool
- {
- is_fused(a.fuse().unique())
- }
- fn fused_unique_by(a: Iter<i16>) -> bool
- {
- is_fused(a.fuse().unique_by(|x| x % 100))
- }
- fn fused_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool
- {
- !is_fused(a.clone().interleave_shortest(b.clone())) &&
- is_fused(a.fuse().interleave_shortest(b.fuse()))
- }
-
- fn fused_product(a: Iter<i16>, b: Iter<i16>) -> bool
- {
- is_fused(a.fuse().cartesian_product(b.fuse()))
- }
- fn fused_merge(a: Iter<i16>, b: Iter<i16>) -> bool
- {
- is_fused(a.fuse().merge(b.fuse()))
- }
- fn fused_filter_ok(a: Iter<i16>) -> bool
- {
- is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
- .filter_ok(|x| x % 3 == 0)
- .fuse())
- }
- fn fused_filter_map_ok(a: Iter<i16>) -> bool
- {
- is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
- .filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None})
- .fuse())
- }
- fn fused_positions(a: Iter<i16>) -> bool
- {
- !is_fused(a.clone().positions(|x|x%2==0)) &&
- is_fused(a.fuse().positions(|x|x%2==0))
- }
- fn fused_update(a: Iter<i16>) -> bool
- {
- !is_fused(a.clone().update(|x|*x+=1)) &&
- is_fused(a.fuse().update(|x|*x+=1))
- }
- fn fused_tuple_windows(a: Iter<i16>) -> bool
- {
- is_fused(a.fuse().tuple_windows::<(_,_)>())
- }
- fn fused_pad_using(a: Iter<i16>) -> bool
- {
- is_fused(a.fuse().pad_using(100,|_|0))
- }
- }
|