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