// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use googletest::prelude::*; use indoc::indoc; use std::collections::HashMap; #[test] fn unordered_elements_are_matches_empty_vector() -> Result<()> { let value: Vec = vec![]; verify_that!(value, unordered_elements_are![]) } #[test] fn unordered_elements_are_matches_empty_vector_with_trailing_comma() -> Result<()> { let value: Vec = vec![]; verify_that!(value, unordered_elements_are![,]) } #[test] fn unordered_elements_are_matches_vector() -> Result<()> { let value = vec![1, 2, 3]; verify_that!(value, unordered_elements_are![eq(&1), eq(&2), eq(&3)]) } #[test] fn unordered_elements_are_matches_iterator_returning_by_value() -> Result<()> { #[derive(Debug, Copy, Clone)] struct Countdown(i32); impl Iterator for Countdown { type Item = i32; fn next(&mut self) -> Option { match self.0 { 0 => None, x => { self.0 -= 1; Some(x) } } } } verify_that!(Countdown(3), unordered_elements_are![eq(1), eq(2), eq(3)]) } #[test] fn unordered_elements_are_omitted() -> Result<()> { let value = vec![1, 2, 3]; verify_that!(value, {eq(&3), eq(&2), eq(&1)}) } #[test] fn unordered_elements_are_matches_slice() -> Result<()> { let value = vec![1, 2, 3]; let slice = value.as_slice(); verify_that!(slice, unordered_elements_are![eq(&1), eq(&2), eq(&3)]) } #[test] fn unordered_elements_are_matches_hash_map() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]); verify_that!( value, unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three"))] ) } #[test] fn unordered_elements_are_matches_hash_map_with_trailing_comma() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]); verify_that!( value, unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")),] ) } #[test] fn unordered_elements_are_does_not_match_hash_map_with_wrong_key() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (4, "Three")]); verify_that!( value, not(unordered_elements_are![ (eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")) ]) ) } #[test] fn unordered_elements_are_does_not_match_hash_map_with_wrong_value() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Four")]); verify_that!( value, not(unordered_elements_are![ (eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")) ]) ) } #[test] fn unordered_elements_are_does_not_match_hash_map_missing_element() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two")]); verify_that!( value, not(unordered_elements_are![ (eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")) ]) ) } #[test] fn unordered_elements_are_does_not_match_hash_map_with_extra_element() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]); verify_that!(value, not(unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One"))])) } #[test] fn unordered_elements_are_does_not_match_hash_map_with_mismatched_key_and_value() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Three"), (3, "Two")]); verify_that!( value, not(unordered_elements_are![ (eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")) ]) ) } #[test] fn unordered_elements_are_matches_vector_with_trailing_comma() -> Result<()> { let value = vec![1, 2, 3]; verify_that!(value, unordered_elements_are![eq(&1), eq(&2), eq(&3),]) } #[test] fn unordered_elements_are_matches_size() -> Result<()> { let value = vec![1, 2]; verify_that!(value, not(unordered_elements_are![eq(&1), eq(&2), eq(&3)])) } #[test] fn unordered_elements_are_admits_matchers_without_static_lifetime() -> Result<()> { #[derive(Debug, PartialEq)] struct AStruct(i32); let expected_value = AStruct(123); verify_that!(vec![AStruct(123)], unordered_elements_are![eq(&expected_value)]) } #[test] fn unordered_elements_are_with_map_admits_matchers_without_static_lifetime() -> Result<()> { #[derive(Debug, PartialEq)] struct AStruct(i32); let expected_value = AStruct(123); verify_that!( HashMap::from([(1, AStruct(123))]), unordered_elements_are![(eq(&1), eq(&expected_value))] ) } #[test] fn unordered_elements_are_description_mismatch() -> Result<()> { let result = verify_that!(vec![1, 4, 3], unordered_elements_are![eq(&1), eq(&2), eq(&3)]); verify_that!( result, err(displays_as(contains_substring(indoc!( " Value of: vec![1, 4, 3] Expected: contains elements matching in any order: 0. is equal to 1 1. is equal to 2 2. is equal to 3 Actual: [1, 4, 3], whose element #1 does not match any expected elements and no elements match the expected element #1" )))) ) } #[test] fn unordered_elements_are_matches_unordered() -> Result<()> { let value = vec![1, 2]; verify_that!(value, unordered_elements_are![eq(&2), eq(&1)]) } #[test] fn unordered_elements_are_matches_unordered_with_repetition() -> Result<()> { let value = vec![1, 2, 1, 2, 1]; verify_that!(value, unordered_elements_are![eq(&1), eq(&1), eq(&1), eq(&2), eq(&2)]) } #[test] fn unordered_elements_are_explains_mismatch_due_to_wrong_size() -> Result<()> { let matcher = unordered_elements_are![eq(&2), eq(&3), eq(&4)]; verify_that!( matcher.explain_match(&vec![2, 3]), displays_as(eq("which has size 2 (expected 3)")) ) } #[test] fn unordered_elements_are_description_no_full_match() -> Result<()> { let matcher = unordered_elements_are![eq(&1), eq(&2), eq(&2)]; verify_that!( matcher.explain_match(&vec![1, 1, 2]), displays_as(eq(indoc!( " which does not have a perfect match with the expected elements. The best match found was: Actual element 1 at index 0 matched expected element `is equal to 1` at index 0. Actual element 2 at index 2 matched expected element `is equal to 2` at index 1. Actual element 1 at index 1 did not match any remaining expected element. Expected element `is equal to 2` at index 2 did not match any remaining actual element." ))) ) } #[test] fn unordered_elements_are_unmatchable_expected_description_mismatch() -> Result<()> { let matcher = unordered_elements_are![eq(&1), eq(&2), eq(&3)]; verify_that!( matcher.explain_match(&vec![1, 1, 3]), displays_as(eq("which has no element matching the expected element #1")) ) } #[test] fn unordered_elements_are_unmatchable_actual_description_mismatch() -> Result<()> { let matcher = unordered_elements_are![eq(&1), eq(&1), eq(&3)]; verify_that!( matcher.explain_match(&vec![1, 2, 3]), displays_as(eq("whose element #1 does not match any expected elements")) ) } fn create_matcher<'a>() -> impl Matcher<&'a Vec> { unordered_elements_are![eq(&1)] } #[test] fn unordered_elements_are_works_when_matcher_is_created_in_subroutine() -> Result<()> { verify_that!(vec![1], create_matcher()) } fn create_matcher_for_map<'a>() -> impl Matcher<&'a HashMap> { unordered_elements_are![(eq(&1), eq(&1))] } #[test] fn unordered_elements_are_works_when_matcher_for_maps_is_created_in_subroutine() -> Result<()> { verify_that!(HashMap::from([(1, 1)]), create_matcher_for_map()) } #[test] fn contains_each_matches_when_one_to_one_correspondence_present() -> Result<()> { verify_that!(vec![2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4))) } #[test] fn contains_each_supports_trailing_comma() -> Result<()> { verify_that!(vec![2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4),)) } #[test] fn contains_each_matches_hash_map() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]); verify_that!(value, contains_each![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One"))]) } #[test] fn contains_each_matches_hash_map_with_trailing_comma() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]); verify_that!(value, contains_each![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")),]) } #[test] fn contains_each_matches_when_no_matchers_present() -> Result<()> { verify_that!(vec![2, 3, 4], contains_each!()) } #[test] fn contains_each_matches_when_no_matchers_present_and_trailing_comma() -> Result<()> { verify_that!(vec![2, 3, 4], contains_each!(,)) } #[test] fn contains_each_matches_when_list_is_empty_and_no_matchers_present() -> Result<()> { verify_that!(Vec::::new(), contains_each!()) } #[test] fn contains_each_matches_when_excess_elements_present() -> Result<()> { verify_that!(vec![1, 2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4))) } #[test] fn contains_each_does_not_match_when_matchers_are_unmatched() -> Result<()> { verify_that!(vec![1, 2, 3], not(contains_each!(eq(&2), eq(&3), eq(&4)))) } #[test] fn contains_each_explains_mismatch_due_to_wrong_size() -> Result<()> { let matcher = contains_each![eq(&2), eq(&3), eq(&4)]; verify_that!( matcher.explain_match(&vec![2, 3]), displays_as(eq("which has size 2 (expected at least 3)")) ) } #[test] fn contains_each_explains_missing_element_in_mismatch() -> Result<()> { let matcher = contains_each![eq(&2), eq(&3), eq(&4)]; verify_that!( matcher.explain_match(&vec![1, 2, 3]), displays_as(eq("which has no element matching the expected element #2")) ) } #[test] fn contains_each_explains_missing_elements_in_mismatch() -> Result<()> { let matcher = contains_each![eq(&2), eq(&3), eq(&4), eq(&5)]; verify_that!( matcher.explain_match(&vec![0, 1, 2, 3]), displays_as(eq("which has no elements matching the expected elements #2, #3")) ) } #[test] fn contains_each_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> { let matcher = contains_each![ge(&2), ge(&2)]; verify_that!( matcher .explain_match(&vec![1, 2]), displays_as(eq(indoc!( " which does not have a superset match with the expected elements. The best match found was: Actual element 2 at index 1 matched expected element `is greater than or equal to 2` at index 0. Actual element 1 at index 0 did not match any remaining expected element. Expected element `is greater than or equal to 2` at index 1 did not match any remaining actual element.")) )) } #[test] fn is_contained_in_matches_with_empty_vector() -> Result<()> { let value: Vec = vec![]; verify_that!(value, is_contained_in!()) } #[test] fn is_contained_in_matches_with_empty_vector_and_trailing_comma() -> Result<()> { let value: Vec = vec![]; verify_that!(value, is_contained_in!(,)) } #[test] fn is_contained_in_matches_when_one_to_one_correspondence_present() -> Result<()> { verify_that!(vec![2, 3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4))) } #[test] fn is_contained_supports_trailing_comma() -> Result<()> { verify_that!(vec![2, 3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4),)) } #[test] fn is_contained_in_matches_hash_map() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two")]); verify_that!( value, is_contained_in![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three"))] ) } #[test] fn is_contained_in_matches_hash_map_with_trailing_comma() -> Result<()> { let value: HashMap = HashMap::from([(1, "One"), (2, "Two")]); verify_that!( value, is_contained_in![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")),] ) } #[test] fn is_contained_in_matches_when_container_is_empty() -> Result<()> { verify_that!(vec![1; 0], is_contained_in!(eq(&2), eq(&3), eq(&4))) } #[test] fn is_contained_in_matches_when_excess_matchers_present() -> Result<()> { verify_that!(vec![3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4))) } #[test] fn is_contained_in_does_not_match_when_elements_are_unmatched() -> Result<()> { verify_that!(vec![1, 2, 3], not(is_contained_in!(eq(&2), eq(&3), eq(&4)))) } #[test] fn is_contained_in_explains_mismatch_due_to_wrong_size() -> Result<()> { let matcher = is_contained_in![eq(&2), eq(&3)]; verify_that!( matcher.explain_match(&vec![2, 3, 4]), displays_as(eq("which has size 3 (expected at most 2)")) ) } #[test] fn is_contained_in_explains_missing_element_in_mismatch() -> Result<()> { let matcher = is_contained_in![eq(&2), eq(&3), eq(&4)]; verify_that!( matcher.explain_match(&vec![1, 2, 3]), displays_as(eq("whose element #0 does not match any expected elements")) ) } #[test] fn is_contained_in_explains_missing_elements_in_mismatch() -> Result<()> { let matcher = is_contained_in![eq(&2), eq(&3), eq(&4), eq(&5)]; verify_that!( matcher.explain_match(&vec![0, 1, 2, 3]), displays_as(eq("whose elements #0, #1 do not match any expected elements")) ) } #[test] fn is_contained_in_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> { let matcher = is_contained_in![ge(&1), ge(&3)]; verify_that!( matcher.explain_match(&vec![1, 2]), displays_as(eq(indoc!( " which does not have a subset match with the expected elements. The best match found was: Actual element 1 at index 0 matched expected element `is greater than or equal to 1` at index 0. Actual element 2 at index 1 did not match any remaining expected element. Expected element `is greater than or equal to 3` at index 1 did not match any remaining actual element.")) )) } #[test] fn unordered_elements_are_with_auto_eq() -> Result<()> { verify_that!(vec![3, 4, 2], unordered_elements_are![&2, &3, &4]) } #[test] fn contains_each_with_auto_eq() -> Result<()> { verify_that!(vec![3, 4, 2], contains_each![&2, &4]) } #[test] fn is_contained_in_with_auto_eq() -> Result<()> { verify_that!(vec![3, 4, 2], is_contained_in![&1, &2, &3, &4]) }