1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use googletest::matcher::Matcher;
16 use googletest::prelude::*;
17 use indoc::indoc;
18 use std::collections::HashMap;
19 
20 #[test]
unordered_elements_are_matches_empty_vector() -> Result<()>21 fn unordered_elements_are_matches_empty_vector() -> Result<()> {
22     let value: Vec<u32> = vec![];
23     verify_that!(value, unordered_elements_are![])
24 }
25 
26 #[test]
unordered_elements_are_matches_empty_vector_with_trailing_comma() -> Result<()>27 fn unordered_elements_are_matches_empty_vector_with_trailing_comma() -> Result<()> {
28     let value: Vec<u32> = vec![];
29     verify_that!(value, unordered_elements_are![,])
30 }
31 
32 #[test]
unordered_elements_are_matches_vector() -> Result<()>33 fn unordered_elements_are_matches_vector() -> Result<()> {
34     let value = vec![1, 2, 3];
35     verify_that!(value, unordered_elements_are![eq(1), eq(2), eq(3)])
36 }
37 
38 #[test]
unordered_elements_are_omitted() -> Result<()>39 fn unordered_elements_are_omitted() -> Result<()> {
40     let value = vec![1, 2, 3];
41     verify_that!(value, {eq(3), eq(2), eq(1)})
42 }
43 
44 #[test]
unordered_elements_are_matches_slice() -> Result<()>45 fn unordered_elements_are_matches_slice() -> Result<()> {
46     let value = vec![1, 2, 3];
47     let slice = value.as_slice();
48     verify_that!(*slice, unordered_elements_are![eq(1), eq(2), eq(3)])
49 }
50 
51 #[test]
unordered_elements_are_matches_hash_map() -> Result<()>52 fn unordered_elements_are_matches_hash_map() -> Result<()> {
53     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
54     verify_that!(
55         value,
56         unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))]
57     )
58 }
59 
60 #[test]
unordered_elements_are_matches_hash_map_with_trailing_comma() -> Result<()>61 fn unordered_elements_are_matches_hash_map_with_trailing_comma() -> Result<()> {
62     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
63     verify_that!(
64         value,
65         unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three")),]
66     )
67 }
68 
69 #[test]
unordered_elements_are_does_not_match_hash_map_with_wrong_key() -> Result<()>70 fn unordered_elements_are_does_not_match_hash_map_with_wrong_key() -> Result<()> {
71     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (4, "Three")]);
72     verify_that!(
73         value,
74         not(unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))])
75     )
76 }
77 
78 #[test]
unordered_elements_are_does_not_match_hash_map_with_wrong_value() -> Result<()>79 fn unordered_elements_are_does_not_match_hash_map_with_wrong_value() -> Result<()> {
80     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Four")]);
81     verify_that!(
82         value,
83         not(unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))])
84     )
85 }
86 
87 #[test]
unordered_elements_are_does_not_match_hash_map_missing_element() -> Result<()>88 fn unordered_elements_are_does_not_match_hash_map_missing_element() -> Result<()> {
89     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
90     verify_that!(
91         value,
92         not(unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))])
93     )
94 }
95 
96 #[test]
unordered_elements_are_does_not_match_hash_map_with_extra_element() -> Result<()>97 fn unordered_elements_are_does_not_match_hash_map_with_extra_element() -> Result<()> {
98     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
99     verify_that!(value, not(unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One"))]))
100 }
101 
102 #[test]
unordered_elements_are_does_not_match_hash_map_with_mismatched_key_and_value() -> Result<()>103 fn unordered_elements_are_does_not_match_hash_map_with_mismatched_key_and_value() -> Result<()> {
104     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Three"), (3, "Two")]);
105     verify_that!(
106         value,
107         not(unordered_elements_are![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))])
108     )
109 }
110 
111 #[test]
unordered_elements_are_matches_vector_with_trailing_comma() -> Result<()>112 fn unordered_elements_are_matches_vector_with_trailing_comma() -> Result<()> {
113     let value = vec![1, 2, 3];
114     verify_that!(value, unordered_elements_are![eq(1), eq(2), eq(3),])
115 }
116 
117 #[test]
unordered_elements_are_matches_size() -> Result<()>118 fn unordered_elements_are_matches_size() -> Result<()> {
119     let value = vec![1, 2];
120     verify_that!(value, not(unordered_elements_are![eq(1), eq(2), eq(3)]))
121 }
122 
123 #[test]
unordered_elements_are_admits_matchers_without_static_lifetime() -> Result<()>124 fn unordered_elements_are_admits_matchers_without_static_lifetime() -> Result<()> {
125     #[derive(Debug, PartialEq)]
126     struct AStruct(i32);
127     let expected_value = AStruct(123);
128     verify_that!(vec![AStruct(123)], unordered_elements_are![eq_deref_of(&expected_value)])
129 }
130 
131 #[test]
unordered_elements_are_with_map_admits_matchers_without_static_lifetime() -> Result<()>132 fn unordered_elements_are_with_map_admits_matchers_without_static_lifetime() -> Result<()> {
133     #[derive(Debug, PartialEq)]
134     struct AStruct(i32);
135     let expected_value = AStruct(123);
136     verify_that!(
137         HashMap::from([(1, AStruct(123))]),
138         unordered_elements_are![(eq(1), eq_deref_of(&expected_value))]
139     )
140 }
141 
142 #[test]
unordered_elements_are_description_mismatch() -> Result<()>143 fn unordered_elements_are_description_mismatch() -> Result<()> {
144     let result = verify_that!(vec![1, 4, 3], unordered_elements_are![eq(1), eq(2), eq(3)]);
145     verify_that!(
146         result,
147         err(displays_as(contains_substring(indoc!(
148             "
149             Value of: vec![1, 4, 3]
150             Expected: contains elements matching in any order:
151               0. is equal to 1
152               1. is equal to 2
153               2. is equal to 3
154             Actual: [1, 4, 3],
155               whose element #1 does not match any expected elements and no elements match the expected element #1"
156             ))))
157     )
158 }
159 
160 #[test]
unordered_elements_are_matches_unordered() -> Result<()>161 fn unordered_elements_are_matches_unordered() -> Result<()> {
162     let value = vec![1, 2];
163     verify_that!(value, unordered_elements_are![eq(2), eq(1)])
164 }
165 
166 #[test]
unordered_elements_are_matches_unordered_with_repetition() -> Result<()>167 fn unordered_elements_are_matches_unordered_with_repetition() -> Result<()> {
168     let value = vec![1, 2, 1, 2, 1];
169     verify_that!(value, unordered_elements_are![eq(1), eq(1), eq(1), eq(2), eq(2)])
170 }
171 
172 #[test]
unordered_elements_are_explains_mismatch_due_to_wrong_size() -> Result<()>173 fn unordered_elements_are_explains_mismatch_due_to_wrong_size() -> Result<()> {
174     verify_that!(
175         unordered_elements_are![eq(2), eq(3), eq(4)].explain_match(&vec![2, 3]),
176         displays_as(eq("which has size 2 (expected 3)"))
177     )
178 }
179 
180 #[test]
unordered_elements_are_description_no_full_match() -> Result<()>181 fn unordered_elements_are_description_no_full_match() -> Result<()> {
182     verify_that!(
183         unordered_elements_are![eq(1), eq(2), eq(2)].explain_match(&vec![1, 1, 2]),
184         displays_as(eq(indoc!(
185             "
186             which does not have a perfect match with the expected elements. The best match found was:
187               Actual element 1 at index 0 matched expected element `is equal to 1` at index 0.
188               Actual element 2 at index 2 matched expected element `is equal to 2` at index 1.
189               Actual element 1 at index 1 did not match any remaining expected element.
190               Expected element `is equal to 2` at index 2 did not match any remaining actual element."
191         )))
192     )
193 }
194 
195 #[test]
unordered_elements_are_unmatchable_expected_description_mismatch() -> Result<()>196 fn unordered_elements_are_unmatchable_expected_description_mismatch() -> Result<()> {
197     verify_that!(
198         unordered_elements_are![eq(1), eq(2), eq(3)].explain_match(&vec![1, 1, 3]),
199         displays_as(eq("which has no element matching the expected element #1"))
200     )
201 }
202 
203 #[test]
unordered_elements_are_unmatchable_actual_description_mismatch() -> Result<()>204 fn unordered_elements_are_unmatchable_actual_description_mismatch() -> Result<()> {
205     verify_that!(
206         unordered_elements_are![eq(1), eq(1), eq(3)].explain_match(&vec![1, 2, 3]),
207         displays_as(eq("whose element #1 does not match any expected elements"))
208     )
209 }
210 
create_matcher() -> impl Matcher<ActualT = Vec<i32>>211 fn create_matcher() -> impl Matcher<ActualT = Vec<i32>> {
212     unordered_elements_are![eq(1)]
213 }
214 
215 #[test]
unordered_elements_are_works_when_matcher_is_created_in_subroutine() -> Result<()>216 fn unordered_elements_are_works_when_matcher_is_created_in_subroutine() -> Result<()> {
217     verify_that!(vec![1], create_matcher())
218 }
219 
create_matcher_for_map() -> impl Matcher<ActualT = HashMap<i32, i32>>220 fn create_matcher_for_map() -> impl Matcher<ActualT = HashMap<i32, i32>> {
221     unordered_elements_are![(eq(1), eq(1))]
222 }
223 
224 #[test]
unordered_elements_are_works_when_matcher_for_maps_is_created_in_subroutine() -> Result<()>225 fn unordered_elements_are_works_when_matcher_for_maps_is_created_in_subroutine() -> Result<()> {
226     verify_that!(HashMap::from([(1, 1)]), create_matcher_for_map())
227 }
228 
229 #[test]
contains_each_matches_when_one_to_one_correspondence_present() -> Result<()>230 fn contains_each_matches_when_one_to_one_correspondence_present() -> Result<()> {
231     verify_that!(vec![2, 3, 4], contains_each!(eq(2), eq(3), eq(4)))
232 }
233 
234 #[test]
contains_each_supports_trailing_comma() -> Result<()>235 fn contains_each_supports_trailing_comma() -> Result<()> {
236     verify_that!(vec![2, 3, 4], contains_each!(eq(2), eq(3), eq(4),))
237 }
238 
239 #[test]
contains_each_matches_hash_map() -> Result<()>240 fn contains_each_matches_hash_map() -> Result<()> {
241     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
242     verify_that!(value, contains_each![(eq(2), eq("Two")), (eq(1), eq("One"))])
243 }
244 
245 #[test]
contains_each_matches_hash_map_with_trailing_comma() -> Result<()>246 fn contains_each_matches_hash_map_with_trailing_comma() -> Result<()> {
247     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
248     verify_that!(value, contains_each![(eq(2), eq("Two")), (eq(1), eq("One")),])
249 }
250 
251 #[test]
contains_each_matches_when_no_matchers_present() -> Result<()>252 fn contains_each_matches_when_no_matchers_present() -> Result<()> {
253     verify_that!(vec![2, 3, 4], contains_each!())
254 }
255 
256 #[test]
contains_each_matches_when_no_matchers_present_and_trailing_comma() -> Result<()>257 fn contains_each_matches_when_no_matchers_present_and_trailing_comma() -> Result<()> {
258     verify_that!(vec![2, 3, 4], contains_each!(,))
259 }
260 
261 #[test]
contains_each_matches_when_list_is_empty_and_no_matchers_present() -> Result<()>262 fn contains_each_matches_when_list_is_empty_and_no_matchers_present() -> Result<()> {
263     verify_that!(Vec::<u32>::new(), contains_each!())
264 }
265 
266 #[test]
contains_each_matches_when_excess_elements_present() -> Result<()>267 fn contains_each_matches_when_excess_elements_present() -> Result<()> {
268     verify_that!(vec![1, 2, 3, 4], contains_each!(eq(2), eq(3), eq(4)))
269 }
270 
271 #[test]
contains_each_does_not_match_when_matchers_are_unmatched() -> Result<()>272 fn contains_each_does_not_match_when_matchers_are_unmatched() -> Result<()> {
273     verify_that!(vec![1, 2, 3], not(contains_each!(eq(2), eq(3), eq(4))))
274 }
275 
276 #[test]
contains_each_explains_mismatch_due_to_wrong_size() -> Result<()>277 fn contains_each_explains_mismatch_due_to_wrong_size() -> Result<()> {
278     verify_that!(
279         contains_each![eq(2), eq(3), eq(4)].explain_match(&vec![2, 3]),
280         displays_as(eq("which has size 2 (expected at least 3)"))
281     )
282 }
283 
284 #[test]
contains_each_explains_missing_element_in_mismatch() -> Result<()>285 fn contains_each_explains_missing_element_in_mismatch() -> Result<()> {
286     verify_that!(
287         contains_each![eq(2), eq(3), eq(4)].explain_match(&vec![1, 2, 3]),
288         displays_as(eq("which has no element matching the expected element #2"))
289     )
290 }
291 
292 #[test]
contains_each_explains_missing_elements_in_mismatch() -> Result<()>293 fn contains_each_explains_missing_elements_in_mismatch() -> Result<()> {
294     verify_that!(
295         contains_each![eq(2), eq(3), eq(4), eq(5)].explain_match(&vec![0, 1, 2, 3]),
296         displays_as(eq("which has no elements matching the expected elements #2, #3"))
297     )
298 }
299 
300 #[test]
contains_each_explains_mismatch_due_to_no_graph_matching_found() -> Result<()>301 fn contains_each_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> {
302     verify_that!(
303         contains_each![ge(2), ge(2)].explain_match(&vec![1, 2]),
304         displays_as(eq(indoc!(
305             "
306             which does not have a superset match with the expected elements. The best match found was:
307               Actual element 2 at index 1 matched expected element `is greater than or equal to 2` at index 0.
308               Actual element 1 at index 0 did not match any remaining expected element.
309               Expected element `is greater than or equal to 2` at index 1 did not match any remaining actual element."))
310     ))
311 }
312 
313 #[test]
is_contained_in_matches_with_empty_vector() -> Result<()>314 fn is_contained_in_matches_with_empty_vector() -> Result<()> {
315     let value: Vec<u32> = vec![];
316     verify_that!(value, is_contained_in!())
317 }
318 
319 #[test]
is_contained_in_matches_with_empty_vector_and_trailing_comma() -> Result<()>320 fn is_contained_in_matches_with_empty_vector_and_trailing_comma() -> Result<()> {
321     let value: Vec<u32> = vec![];
322     verify_that!(value, is_contained_in!(,))
323 }
324 
325 #[test]
is_contained_in_matches_when_one_to_one_correspondence_present() -> Result<()>326 fn is_contained_in_matches_when_one_to_one_correspondence_present() -> Result<()> {
327     verify_that!(vec![2, 3, 4], is_contained_in!(eq(2), eq(3), eq(4)))
328 }
329 
330 #[test]
is_contained_supports_trailing_comma() -> Result<()>331 fn is_contained_supports_trailing_comma() -> Result<()> {
332     verify_that!(vec![2, 3, 4], is_contained_in!(eq(2), eq(3), eq(4),))
333 }
334 
335 #[test]
is_contained_in_matches_hash_map() -> Result<()>336 fn is_contained_in_matches_hash_map() -> Result<()> {
337     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
338     verify_that!(
339         value,
340         is_contained_in![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three"))]
341     )
342 }
343 
344 #[test]
is_contained_in_matches_hash_map_with_trailing_comma() -> Result<()>345 fn is_contained_in_matches_hash_map_with_trailing_comma() -> Result<()> {
346     let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
347     verify_that!(
348         value,
349         is_contained_in![(eq(2), eq("Two")), (eq(1), eq("One")), (eq(3), eq("Three")),]
350     )
351 }
352 
353 #[test]
is_contained_in_matches_when_container_is_empty() -> Result<()>354 fn is_contained_in_matches_when_container_is_empty() -> Result<()> {
355     verify_that!(vec![], is_contained_in!(eq::<i32, _>(2), eq(3), eq(4)))
356 }
357 
358 #[test]
is_contained_in_matches_when_excess_matchers_present() -> Result<()>359 fn is_contained_in_matches_when_excess_matchers_present() -> Result<()> {
360     verify_that!(vec![3, 4], is_contained_in!(eq(2), eq(3), eq(4)))
361 }
362 
363 #[test]
is_contained_in_does_not_match_when_elements_are_unmatched() -> Result<()>364 fn is_contained_in_does_not_match_when_elements_are_unmatched() -> Result<()> {
365     verify_that!(vec![1, 2, 3], not(is_contained_in!(eq(2), eq(3), eq(4))))
366 }
367 
368 #[test]
is_contained_in_explains_mismatch_due_to_wrong_size() -> Result<()>369 fn is_contained_in_explains_mismatch_due_to_wrong_size() -> Result<()> {
370     verify_that!(
371         is_contained_in![eq(2), eq(3)].explain_match(&vec![2, 3, 4]),
372         displays_as(eq("which has size 3 (expected at most 2)"))
373     )
374 }
375 
376 #[test]
is_contained_in_explains_missing_element_in_mismatch() -> Result<()>377 fn is_contained_in_explains_missing_element_in_mismatch() -> Result<()> {
378     verify_that!(
379         is_contained_in![eq(2), eq(3), eq(4)].explain_match(&vec![1, 2, 3]),
380         displays_as(eq("whose element #0 does not match any expected elements"))
381     )
382 }
383 
384 #[test]
is_contained_in_explains_missing_elements_in_mismatch() -> Result<()>385 fn is_contained_in_explains_missing_elements_in_mismatch() -> Result<()> {
386     verify_that!(
387         is_contained_in![eq(2), eq(3), eq(4), eq(5)].explain_match(&vec![0, 1, 2, 3]),
388         displays_as(eq("whose elements #0, #1 do not match any expected elements"))
389     )
390 }
391 
392 #[test]
is_contained_in_explains_mismatch_due_to_no_graph_matching_found() -> Result<()>393 fn is_contained_in_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> {
394     verify_that!(
395         is_contained_in![ge(1), ge(3)].explain_match(&vec![1, 2]),
396         displays_as(eq(indoc!(
397             "
398             which does not have a subset match with the expected elements. The best match found was:
399               Actual element 1 at index 0 matched expected element `is greater than or equal to 1` at index 0.
400               Actual element 2 at index 1 did not match any remaining expected element.
401               Expected element `is greater than or equal to 3` at index 1 did not match any remaining actual element."))
402     ))
403 }
404