asserting/iterator/
mod.rs

1//! Implementations of assertions for `Iterator` values.
2
3use crate::assertions::{
4    AssertIteratorContains, AssertIteratorContainsInAnyOrder, AssertIteratorContainsInOrder,
5};
6use crate::expectations::{
7    IterContains, IterContainsAllInOrder, IterContainsAllOf, IterContainsAnyOf,
8    IterContainsExactly, IterContainsExactlyInAnyOrder, IterContainsOnly, IterContainsOnlyOnce,
9    IterContainsSequence, IterEndsWith, IterStartsWith,
10};
11use crate::properties::DefinedOrderProperty;
12use crate::spec::{Expectation, Expression, FailingStrategy, Spec};
13use crate::std::cmp::Ordering;
14use crate::std::fmt::Debug;
15use crate::std::mem;
16#[cfg(not(feature = "std"))]
17use alloc::{format, string::String, vec, vec::Vec};
18use hashbrown::HashSet;
19
20impl<'a, S, T, E, R> AssertIteratorContains<'a, Vec<T>, E, R> for Spec<'a, S, R>
21where
22    S: IntoIterator<Item = T>,
23    T: PartialEq<E> + Debug,
24    E: Debug,
25    R: FailingStrategy,
26{
27    fn contains(self, expected: E) -> Spec<'a, Vec<T>, R> {
28        self.mapping(Vec::from_iter)
29            .expecting(IterContains { expected })
30    }
31}
32
33impl<T, E> Expectation<Vec<T>> for IterContains<E>
34where
35    T: PartialEq<E> + Debug,
36    E: Debug,
37{
38    fn test(&mut self, subject: &Vec<T>) -> bool {
39        subject.iter().any(|e| e == &self.expected)
40    }
41
42    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
43        format!(
44            "expected {expression} to contain {:?}\n   but was: {actual:?}\n  expected: {:?}",
45            &self.expected, &self.expected
46        )
47    }
48}
49
50impl<'a, S, T, E, R> AssertIteratorContainsInAnyOrder<'a, Vec<T>, E, R> for Spec<'a, S, R>
51where
52    S: IntoIterator<Item = T>,
53    T: PartialEq<<E as IntoIterator>::Item> + Debug,
54    E: IntoIterator,
55    <E as IntoIterator>::Item: Debug,
56    R: FailingStrategy,
57{
58    fn contains_exactly_in_any_order(self, expected: E) -> Spec<'a, Vec<T>, R> {
59        self.mapping(Vec::from_iter)
60            .expecting(IterContainsExactlyInAnyOrder::new(Vec::from_iter(expected)))
61    }
62
63    fn contains_any_of(self, expected: E) -> Spec<'a, Vec<T>, R> {
64        self.mapping(Vec::from_iter).expecting(IterContainsAnyOf {
65            expected: Vec::from_iter(expected),
66        })
67    }
68
69    fn contains_all_of(self, expected: E) -> Spec<'a, Vec<T>, R> {
70        self.mapping(Vec::from_iter)
71            .expecting(IterContainsAllOf::new(Vec::from_iter(expected)))
72    }
73
74    fn contains_only(self, expected: E) -> Spec<'a, Vec<T>, R> {
75        self.mapping(Vec::from_iter)
76            .expecting(IterContainsOnly::new(Vec::from_iter(expected)))
77    }
78
79    fn contains_only_once(self, expected: E) -> Spec<'a, Vec<T>, R> {
80        self.mapping(Vec::from_iter)
81            .expecting(IterContainsOnlyOnce::new(Vec::from_iter(expected)))
82    }
83}
84
85impl<T, E> Expectation<Vec<T>> for IterContainsExactlyInAnyOrder<E>
86where
87    T: PartialEq<E> + Debug,
88    E: Debug,
89{
90    fn test(&mut self, subject: &Vec<T>) -> bool {
91        let missing = &mut self.missing;
92        let extra = &mut self.extra;
93        *extra = (0..subject.len()).collect();
94
95        let mut subject_values = subject.iter().enumerate().collect::<Vec<_>>();
96        for (expected_index, expected) in self.expected.iter().enumerate() {
97            if let Some(index) = subject_values
98                .iter()
99                .position(|(_, value)| *value == expected)
100            {
101                let (subject_index, _) = subject_values.remove(index);
102                extra.remove(&subject_index);
103            } else {
104                missing.insert(expected_index);
105            }
106        }
107
108        extra.is_empty() && missing.is_empty()
109    }
110
111    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
112        let missing = collect_values(&self.missing, &self.expected);
113        let extra = collect_values(&self.extra, actual);
114
115        format!(
116            r"expected {expression} contains exactly in any order {:?}
117   but was: {actual:?}
118  expected: {:?}
119   missing: {missing:?}
120     extra: {extra:?}",
121            &self.expected, &self.expected
122        )
123    }
124}
125
126impl<T, E> Expectation<Vec<T>> for IterContainsAnyOf<E>
127where
128    T: PartialEq<E> + Debug,
129    E: Debug,
130{
131    fn test(&mut self, subject: &Vec<T>) -> bool {
132        for expected in &self.expected {
133            if subject.iter().any(|value| value == expected) {
134                return true;
135            }
136        }
137        false
138    }
139
140    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
141        format!(
142            r"expected {expression} contains any of {:?}, but contained none of them
143   but was: {actual:?}
144  expected: {:?}",
145            &self.expected, &self.expected
146        )
147    }
148}
149
150impl<T, E> Expectation<Vec<T>> for IterContainsAllOf<E>
151where
152    T: PartialEq<E> + Debug,
153    E: Debug,
154{
155    fn test(&mut self, subject: &Vec<T>) -> bool {
156        let missing = &mut self.missing;
157
158        for (expected_index, expected) in self.expected.iter().enumerate() {
159            if !subject.iter().any(|value| value == expected) {
160                missing.insert(expected_index);
161            }
162        }
163
164        missing.is_empty()
165    }
166
167    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
168        let missing = collect_values(&self.missing, &self.expected);
169
170        format!(
171            r"expected {expression} contains all of {:?}
172   but was: {actual:?}
173  expected: {:?}
174   missing: {missing:?}",
175            &self.expected, &self.expected
176        )
177    }
178}
179
180impl<T, E> Expectation<Vec<T>> for IterContainsOnly<E>
181where
182    T: PartialEq<E> + Debug,
183    E: Debug,
184{
185    fn test(&mut self, subject: &Vec<T>) -> bool {
186        let extra = &mut self.extra;
187
188        for (actual_index, value) in subject.iter().enumerate() {
189            if !self.expected.iter().any(|expected| value == expected) {
190                extra.insert(actual_index);
191            }
192        }
193
194        extra.is_empty()
195    }
196
197    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
198        let extra = collect_values(&self.extra, actual);
199
200        format!(
201            r"expected {expression} contains only {:?}
202   but was: {actual:?}
203  expected: {:?}
204     extra: {extra:?}",
205            &self.expected, &self.expected
206        )
207    }
208}
209
210impl<T, E> Expectation<Vec<T>> for IterContainsOnlyOnce<E>
211where
212    T: PartialEq<E> + Debug,
213    E: Debug,
214{
215    fn test(&mut self, subject: &Vec<T>) -> bool {
216        let extra = &mut self.extra;
217        let duplicates = &mut self.duplicates;
218
219        for (actual_index, value) in subject.iter().enumerate() {
220            if let Some(expected) = self.expected.iter().find(|expected| value == *expected) {
221                if subject.iter().filter(|actual| *actual == expected).count() > 1 {
222                    duplicates.insert(actual_index);
223                }
224            } else {
225                extra.insert(actual_index);
226            }
227        }
228
229        duplicates.is_empty() && extra.is_empty()
230    }
231
232    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
233        let extra = collect_values(&self.extra, actual);
234        let duplicates = collect_values(&self.duplicates, actual);
235
236        format!(
237            r"expected {expression} contains only once {:?}
238     but was: {actual:?}
239    expected: {:?}
240       extra: {extra:?}
241  duplicates: {duplicates:?}",
242            &self.expected, &self.expected
243        )
244    }
245}
246
247impl<'a, S, T, E, R> AssertIteratorContainsInOrder<'a, Vec<T>, E, R> for Spec<'a, S, R>
248where
249    S: IntoIterator<Item = T>,
250    <S as IntoIterator>::IntoIter: DefinedOrderProperty,
251    E: IntoIterator,
252    <E as IntoIterator>::IntoIter: DefinedOrderProperty,
253    <E as IntoIterator>::Item: Debug,
254    T: PartialEq<<E as IntoIterator>::Item> + Debug,
255    R: FailingStrategy,
256{
257    fn contains_exactly(self, expected: E) -> Spec<'a, Vec<T>, R> {
258        self.mapping(Vec::from_iter)
259            .expecting(IterContainsExactly::new(Vec::from_iter(expected)))
260    }
261
262    fn contains_sequence(self, expected: E) -> Spec<'a, Vec<T>, R> {
263        self.mapping(Vec::from_iter)
264            .expecting(IterContainsSequence::new(Vec::from_iter(expected)))
265    }
266
267    fn contains_all_in_order(self, expected: E) -> Spec<'a, Vec<T>, R> {
268        self.mapping(Vec::from_iter)
269            .expecting(IterContainsAllInOrder::new(Vec::from_iter(expected)))
270    }
271
272    fn starts_with(self, expected: E) -> Spec<'a, Vec<T>, R> {
273        self.mapping(Vec::from_iter)
274            .expecting(IterStartsWith::new(Vec::from_iter(expected)))
275    }
276
277    fn ends_with(self, expected: E) -> Spec<'a, Vec<T>, R> {
278        self.mapping(Vec::from_iter)
279            .expecting(IterEndsWith::new(Vec::from_iter(expected)))
280    }
281}
282
283impl<T, E> Expectation<Vec<T>> for IterContainsExactly<E>
284where
285    T: PartialEq<E> + Debug,
286    E: Debug,
287{
288    fn test(&mut self, subject: &Vec<T>) -> bool {
289        let mut maybe_extras = Vec::new();
290        let mut maybe_missing = Vec::new();
291        let mut expected_iter = self.expected.iter().enumerate();
292        let mut subject_iter = subject.iter().enumerate();
293        loop {
294            match (expected_iter.next(), subject_iter.next()) {
295                (Some((expected_index, expected_value)), Some((subject_index, actual_value))) => {
296                    if actual_value == expected_value {
297                        continue;
298                    }
299                    maybe_missing.push((expected_index, expected_value));
300                    maybe_extras.push((subject_index, actual_value));
301                },
302                (Some(expected), None) => maybe_missing.push(expected),
303                (None, Some(actual)) => maybe_extras.push(actual),
304                (None, None) => break,
305            }
306        }
307
308        let missing = &mut self.missing;
309        let extra = &mut self.extra;
310        let out_of_order = &mut self.out_of_order;
311
312        for (expected_index, expected_value) in maybe_missing {
313            if let Some(index) = maybe_extras
314                .iter()
315                .position(|(_, value)| *value == expected_value)
316            {
317                let (subject_index, _) = maybe_extras.remove(index);
318                out_of_order.insert(subject_index);
319            } else {
320                missing.insert(expected_index);
321            }
322        }
323        for (subject_index, _) in maybe_extras {
324            extra.insert(subject_index);
325        }
326
327        out_of_order.is_empty() && extra.is_empty() && missing.is_empty()
328    }
329
330    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
331        let missing = collect_values(&self.missing, &self.expected);
332        let extra = collect_values(&self.extra, actual);
333        let out_of_order = collect_values(&self.out_of_order, actual);
334
335        format!(
336            r"expected {expression} contains exactly in order {:?}
337       but was: {actual:?}
338      expected: {:?}
339       missing: {missing:?}
340         extra: {extra:?}
341  out-of-order: {out_of_order:?}",
342            &self.expected, &self.expected
343        )
344    }
345}
346
347impl<T, E> Expectation<Vec<T>> for IterContainsSequence<E>
348where
349    T: PartialEq<E> + Debug,
350    E: Debug,
351{
352    fn test(&mut self, subject: &Vec<T>) -> bool {
353        let subject_length = subject.len();
354        let sequence_length = self.expected.len();
355        let possible_sequence_starts = if sequence_length >= subject_length {
356            vec![0]
357        } else {
358            (0..=subject_length - sequence_length).collect()
359        };
360        let best_missing = &mut self.missing;
361        let best_extra = &mut self.extra;
362        let mut best_match_count = 0;
363        let mut missing = HashSet::new();
364        let mut extra = HashSet::new();
365        let mut match_count = 0;
366        for start_index in possible_sequence_starts {
367            let mut expected_iter = self.expected.iter().enumerate();
368            let mut subject_iter = subject.iter().enumerate().skip(start_index);
369            loop {
370                match (expected_iter.next(), subject_iter.next()) {
371                    (
372                        Some((expected_index, expected_value)),
373                        Some((subject_index, actual_value)),
374                    ) => {
375                        if actual_value == expected_value {
376                            match_count += 1;
377                            continue;
378                        }
379                        missing.insert(expected_index);
380                        extra.insert(subject_index);
381                    },
382                    (Some((expected_index, _)), None) => {
383                        missing.insert(expected_index);
384                    },
385                    (None, _) => break,
386                }
387            }
388            if missing.is_empty() && extra.is_empty() {
389                *best_missing = HashSet::new();
390                *best_extra = HashSet::new();
391                return true;
392            }
393            match match_count.cmp(&best_match_count) {
394                Ordering::Less => {
395                    missing.clear();
396                    extra.clear();
397                },
398                Ordering::Equal => {
399                    best_missing.extend(mem::replace(&mut missing, HashSet::new()));
400                    best_extra.extend(mem::replace(&mut extra, HashSet::new()));
401                },
402                Ordering::Greater => {
403                    best_match_count = match_count;
404                    *best_missing = mem::replace(&mut missing, HashSet::new());
405                    *best_extra = mem::replace(&mut extra, HashSet::new());
406                },
407            }
408            match_count = 0;
409        }
410        false
411    }
412
413    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
414        let missing = collect_values(&self.missing, &self.expected);
415        let extra = collect_values(&self.extra, actual);
416
417        format!(
418            r"expected {expression} contains sequence {:?}
419       but was: {actual:?}
420      expected: {:?}
421       missing: {missing:?}
422         extra: {extra:?}",
423            &self.expected, &self.expected
424        )
425    }
426}
427
428impl<T, E> Expectation<Vec<T>> for IterContainsAllInOrder<E>
429where
430    T: PartialEq<E> + Debug,
431    E: Debug,
432{
433    fn test(&mut self, subject: &Vec<T>) -> bool {
434        let missing = &mut self.missing;
435        let mut last_match_index = 0;
436        for (expected_index, expected) in self.expected.iter().enumerate() {
437            if let Some((subject_index, _)) = subject
438                .iter()
439                .enumerate()
440                .skip(last_match_index)
441                .find(|(_, actual)| *actual == expected)
442            {
443                last_match_index = subject_index + 1;
444            } else {
445                missing.insert(expected_index);
446            }
447        }
448        missing.is_empty()
449    }
450
451    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
452        let missing = collect_values(&self.missing, &self.expected);
453
454        format!(
455            r"expected {expression} contains all of {:?} in order
456       but was: {actual:?}
457      expected: {:?}
458       missing: {missing:?}",
459            &self.expected, &self.expected
460        )
461    }
462}
463
464impl<T, E> Expectation<Vec<T>> for IterStartsWith<E>
465where
466    T: PartialEq<E> + Debug,
467    E: Debug,
468{
469    fn test(&mut self, subject: &Vec<T>) -> bool {
470        let missing = &mut self.missing;
471        let extra = &mut self.extra;
472        let mut expected_iter = self.expected.iter().enumerate();
473        let mut subject_iter = subject.iter().enumerate();
474        loop {
475            match (expected_iter.next(), subject_iter.next()) {
476                (Some((expected_index, expected)), Some((subject_index, actual))) => {
477                    if actual == expected {
478                        continue;
479                    }
480                    missing.insert(expected_index);
481                    extra.insert(subject_index);
482                },
483                (Some((expected_index, _)), None) => {
484                    missing.insert(expected_index);
485                },
486                (None, _) => break,
487            }
488        }
489        extra.is_empty() && missing.is_empty()
490    }
491
492    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
493        let missing = collect_values(&self.missing, &self.expected);
494        let extra = collect_values(&self.extra, actual);
495
496        format!(
497            r"expected {expression} starts with {:?}
498   but was: {actual:?}
499  expected: {:?}
500   missing: {missing:?}
501     extra: {extra:?}",
502            &self.expected, &self.expected
503        )
504    }
505}
506
507impl<T, E> Expectation<Vec<T>> for IterEndsWith<E>
508where
509    T: PartialEq<E> + Debug,
510    E: Debug,
511{
512    fn test(&mut self, subject: &Vec<T>) -> bool {
513        let missing = &mut self.missing;
514        let extra = &mut self.extra;
515        let mut expected_iter = self.expected.iter().enumerate().rev();
516        let mut subject_iter = subject.iter().enumerate().rev();
517        loop {
518            match (expected_iter.next(), subject_iter.next()) {
519                (Some((expected_index, expected)), Some((subject_index, actual))) => {
520                    if actual == expected {
521                        continue;
522                    }
523                    missing.insert(expected_index);
524                    extra.insert(subject_index);
525                },
526                (Some((expected_index, _)), None) => {
527                    missing.insert(expected_index);
528                },
529                (None, _) => break,
530            }
531        }
532        extra.is_empty() && missing.is_empty()
533    }
534
535    fn message(&self, expression: Expression<'_>, actual: &Vec<T>) -> String {
536        let missing = collect_values(&self.missing, &self.expected);
537        let extra = collect_values(&self.extra, actual);
538
539        format!(
540            r"expected {expression} ends with {:?}
541   but was: {actual:?}
542  expected: {:?}
543   missing: {missing:?}
544     extra: {extra:?}",
545            &self.expected, &self.expected
546        )
547    }
548}
549
550fn collect_values<'a, T>(indices: &HashSet<usize>, collection: &'a [T]) -> Vec<&'a T> {
551    collection
552        .iter()
553        .enumerate()
554        .filter_map(|(idx, value)| {
555            if indices.contains(&idx) {
556                Some(value)
557            } else {
558                None
559            }
560        })
561        .collect()
562}
563
564#[cfg(test)]
565mod tests;