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, MatcherResult};
16 use googletest::prelude::*;
17 
18 #[derive(Debug)]
19 struct SomeStruct {
20     a_property: u32,
21 }
22 
23 impl SomeStruct {
get_property(&self) -> u3224     fn get_property(&self) -> u32 {
25         self.a_property
26     }
27 
get_property_ref(&self) -> &u3228     fn get_property_ref(&self) -> &u32 {
29         &self.a_property
30     }
31 
add_product_to_field(&self, a: u32, b: u32) -> u3232     fn add_product_to_field(&self, a: u32, b: u32) -> u32 {
33         self.a_property + a * b
34     }
35 
get_property_ref_with_params(&self, _a: u32, _b: u32) -> &u3236     fn get_property_ref_with_params(&self, _a: u32, _b: u32) -> &u32 {
37         &self.a_property
38     }
39 }
40 
41 #[test]
matches_struct_with_matching_property() -> Result<()>42 fn matches_struct_with_matching_property() -> Result<()> {
43     let value = SomeStruct { a_property: 10 };
44     verify_that!(value, property!(SomeStruct.get_property(), eq(10)))
45 }
46 
47 #[test]
matches_struct_with_matching_property_with_parameters() -> Result<()>48 fn matches_struct_with_matching_property_with_parameters() -> Result<()> {
49     let value = SomeStruct { a_property: 10 };
50     verify_that!(value, property!(SomeStruct.add_product_to_field(2, 3), eq(16)))
51 }
52 
53 #[test]
matches_struct_with_matching_property_with_captured_arguments() -> Result<()>54 fn matches_struct_with_matching_property_with_captured_arguments() -> Result<()> {
55     let value = SomeStruct { a_property: 10 };
56     let arg1 = 2;
57     let arg2 = 3;
58     verify_that!(value, property!(SomeStruct.add_product_to_field(arg1, arg2), eq(16)))
59 }
60 
61 #[test]
matches_struct_with_matching_property_with_parameters_with_trailing_comma() -> Result<()>62 fn matches_struct_with_matching_property_with_parameters_with_trailing_comma() -> Result<()> {
63     let value = SomeStruct { a_property: 10 };
64     verify_that!(value, property!(SomeStruct.add_product_to_field(2, 3,), eq(16)))
65 }
66 
67 #[test]
matches_struct_with_matching_property_ref() -> Result<()>68 fn matches_struct_with_matching_property_ref() -> Result<()> {
69     let value = SomeStruct { a_property: 10 };
70     verify_that!(value, property!(*SomeStruct.get_property_ref(), eq(10)))
71 }
72 
73 #[test]
matches_struct_with_matching_string_reference_property() -> Result<()>74 fn matches_struct_with_matching_string_reference_property() -> Result<()> {
75     #[derive(Debug)]
76     struct StructWithString {
77         property: String,
78     }
79     impl StructWithString {
80         fn get_property_ref(&self) -> &String {
81             &self.property
82         }
83     }
84     let value = StructWithString { property: "Something".into() };
85     verify_that!(value, property!(*StructWithString.get_property_ref(), eq("Something")))
86 }
87 
88 #[test]
matches_struct_with_matching_slice_property() -> Result<()>89 fn matches_struct_with_matching_slice_property() -> Result<()> {
90     #[derive(Debug)]
91     struct StructWithVec {
92         property: Vec<u32>,
93     }
94     impl StructWithVec {
95         fn get_property_ref(&self) -> &[u32] {
96             &self.property
97         }
98     }
99     let value = StructWithVec { property: vec![1, 2, 3] };
100     verify_that!(value, property!(*StructWithVec.get_property_ref(), eq([1, 2, 3])))
101 }
102 
103 #[test]
matches_struct_with_matching_property_ref_with_parameters() -> Result<()>104 fn matches_struct_with_matching_property_ref_with_parameters() -> Result<()> {
105     let value = SomeStruct { a_property: 10 };
106     verify_that!(value, property!(*SomeStruct.get_property_ref_with_params(2, 3), eq(10)))
107 }
108 
109 #[test]
matches_struct_with_matching_property_ref_with_parameters_and_trailing_comma() -> Result<()>110 fn matches_struct_with_matching_property_ref_with_parameters_and_trailing_comma() -> Result<()> {
111     let value = SomeStruct { a_property: 10 };
112     verify_that!(value, property!(*SomeStruct.get_property_ref_with_params(2, 3,), eq(10)))
113 }
114 
115 #[test]
does_not_match_struct_with_non_matching_property() -> Result<()>116 fn does_not_match_struct_with_non_matching_property() -> Result<()> {
117     let value = SomeStruct { a_property: 2 };
118     verify_that!(value, not(property!(SomeStruct.get_property(), eq(1))))
119 }
120 
121 #[test]
describes_itself_in_matching_case() -> Result<()>122 fn describes_itself_in_matching_case() -> Result<()> {
123     verify_that!(
124         property!(SomeStruct.get_property(), eq(1)).describe(MatcherResult::Match),
125         displays_as(eq("has property `get_property()`, which is equal to 1"))
126     )
127 }
128 
129 #[test]
describes_itself_in_not_matching_case() -> Result<()>130 fn describes_itself_in_not_matching_case() -> Result<()> {
131     verify_that!(
132         property!(SomeStruct.get_property(), eq(1)).describe(MatcherResult::NoMatch),
133         displays_as(eq("has property `get_property()`, which isn't equal to 1"))
134     )
135 }
136 
137 #[test]
explains_mismatch_referencing_explanation_of_inner_matcher() -> Result<()>138 fn explains_mismatch_referencing_explanation_of_inner_matcher() -> Result<()> {
139     impl SomeStruct {
140         fn get_a_collection(&self) -> Vec<u32> {
141             vec![]
142         }
143     }
144     let value = SomeStruct { a_property: 2 };
145     let result = verify_that!(value, property!(SomeStruct.get_a_collection(), container_eq([1])));
146 
147     verify_that!(
148         result,
149         err(displays_as(contains_substring(
150             "whose property `get_a_collection()` is `[]`, which is missing the element 1"
151         )))
152     )
153 }
154 
155 #[test]
describes_itself_in_matching_case_for_ref() -> Result<()>156 fn describes_itself_in_matching_case_for_ref() -> Result<()> {
157     verify_that!(
158         property!(*SomeStruct.get_property_ref(), eq(1)).describe(MatcherResult::Match),
159         displays_as(eq("has property `get_property_ref()`, which is equal to 1"))
160     )
161 }
162 
163 #[test]
describes_itself_in_not_matching_case_for_ref() -> Result<()>164 fn describes_itself_in_not_matching_case_for_ref() -> Result<()> {
165     verify_that!(
166         property!(*SomeStruct.get_property_ref(), eq(1)).describe(MatcherResult::NoMatch),
167         displays_as(eq("has property `get_property_ref()`, which isn't equal to 1"))
168     )
169 }
170 
171 #[test]
explains_mismatch_referencing_explanation_of_inner_matcher_for_ref() -> Result<()>172 fn explains_mismatch_referencing_explanation_of_inner_matcher_for_ref() -> Result<()> {
173     static EMPTY_COLLECTION: Vec<u32> = vec![];
174     impl SomeStruct {
175         fn get_a_collection_ref(&self) -> &[u32] {
176             &EMPTY_COLLECTION
177         }
178     }
179     let value = SomeStruct { a_property: 2 };
180     let result =
181         verify_that!(value, property!(*SomeStruct.get_a_collection_ref(), container_eq([1])));
182 
183     verify_that!(
184         result,
185         err(displays_as(contains_substring(
186             "whose property `get_a_collection_ref()` is `[]`, which is missing the element 1"
187         )))
188     )
189 }
190