asserting/iterator/
mod.rs

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