1use 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;