1 // Copyright 2022 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 //! The components required to implement matchers.
16
17 use crate::description::Description;
18 use crate::internal::source_location::SourceLocation;
19 use crate::internal::test_outcome::TestAssertionFailure;
20 use crate::matchers::__internal_unstable_do_not_depend_on_these::ConjunctionMatcher;
21 use crate::matchers::__internal_unstable_do_not_depend_on_these::DisjunctionMatcher;
22 use std::fmt::Debug;
23
24 /// An interface for checking an arbitrary condition on a datum.
25 pub trait Matcher {
26 /// The type against which this matcher matches.
27 type ActualT: Debug + ?Sized;
28
29 /// Returns whether the condition matches the datum `actual`.
30 ///
31 /// The trait implementation defines what it means to "match". Often the
32 /// matching condition is based on data stored in the matcher. For example,
33 /// `eq` matches when its stored expected value is equal (in the sense of
34 /// the `==` operator) to the value `actual`.
matches(&self, actual: &Self::ActualT) -> MatcherResult35 fn matches(&self, actual: &Self::ActualT) -> MatcherResult;
36
37 /// Returns a description of `self` or a negative description if
38 /// `matcher_result` is `DoesNotMatch`.
39 ///
40 /// The function should print a verb phrase that describes the property a
41 /// value matching, respectively not matching, this matcher should have.
42 /// The subject of the verb phrase is the value being matched.
43 ///
44 /// The output appears next to `Expected` in an assertion failure message.
45 /// For example:
46 ///
47 /// ```text
48 /// Value of: ...
49 /// Expected: is equal to 7
50 /// ^^^^^^^^^^^^^
51 /// Actual: ...
52 /// ```
53 ///
54 /// When the matcher contains one or more inner matchers, the implementation
55 /// should invoke [`Self::describe`] on the inner matchers to complete the
56 /// description. It should place the inner description at a point where a
57 /// verb phrase would fit. For example, the matcher
58 /// [`some`][crate::matchers::some] implements `describe` as follows:
59 ///
60 /// ```ignore
61 /// fn describe(&self, matcher_result: MatcherResult) -> Description {
62 /// match matcher_result {
63 /// MatcherResult::Matches => {
64 /// Description::new()
65 /// .text("has a value which")
66 /// .nested(self.inner.describe(MatcherResult::Matches))
67 /// // Inner matcher: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68 /// }
69 /// MatcherResult::DoesNotMatch => {...} // Similar to the above
70 /// }
71 /// }
72 /// ```
73 ///
74 /// The output expectation differs from that of
75 /// [`explain_match`][Self::explain_match] in that it is a verb phrase
76 /// (beginning with a verb like "is") rather than a relative clause
77 /// (beginning with "which" or "whose"). This difference is because the
78 /// output of `explain_match` is always used adjectivally to describe the
79 /// actual value, while `describe` is used in contexts where a relative
80 /// clause would not make sense.
describe(&self, matcher_result: MatcherResult) -> Description81 fn describe(&self, matcher_result: MatcherResult) -> Description;
82
83 /// Prepares a [`String`] describing how the expected value
84 /// encoded in this instance matches or does not match the given value
85 /// `actual`.
86 ///
87 /// This should be in the form of a relative clause, i.e. something starting
88 /// with a relative pronoun such as "which" or "whose". It will appear next
89 /// to the actual value in an assertion failure. For example:
90 ///
91 /// ```text
92 /// Value of: ...
93 /// Expected: ...
94 /// Actual: ["Something"], which does not contain "Something else"
95 /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96 /// ```
97 ///
98 /// The default implementation relies on [`describe`][Self::describe]. Thus
99 /// it does not make any use of the actual value itself, but rather only
100 /// whether the value is matched.
101 ///
102 /// Override the default implementation to provide additional context on why
103 /// a particular value matched or did not match. For example, the
104 /// [`container_eq`][crate::matchers::container_eq] matcher displays
105 /// information on which elements of the actual value were not present in
106 /// the expected value and vice versa.
107 ///
108 /// This implementation should be overridden in any matcher which contains
109 /// one or more inner matchers. The implementation should invoke
110 /// `explain_match` on the inner matchers, so that the generated match
111 /// explanation also reflects their implementation. Without this, the match
112 /// explanation of the inner matchers will not be able to make use of the
113 /// actual value at all.
114 ///
115 /// For example, the `explain_match` implementation of the matcher
116 /// [`points_to`][crate::matchers::points_to] defers immediately to the
117 /// inner matcher and appears as follows:
118 ///
119 /// ```ignore
120 /// fn explain_match(&self, actual: &Self::ActualT) -> Description {
121 /// self.expected.explain_match(actual.deref())
122 /// }
123 /// ```
124 ///
125 /// The matcher can also provide some additional context before deferring to
126 /// an inner matcher. In that case it should invoke `explain_match` on the
127 /// inner matcher at a point where a relative clause would fit. For example:
128 ///
129 /// ```ignore
130 /// fn explain_match(&self, actual: &Self::ActualT) -> Description {
131 /// Description::new()
132 /// .text("which points to a value")
133 /// .nested(self.expected.explain_match(actual.deref()))
134 /// }
135 /// ```
explain_match(&self, actual: &Self::ActualT) -> Description136 fn explain_match(&self, actual: &Self::ActualT) -> Description {
137 format!("which {}", self.describe(self.matches(actual))).into()
138 }
139
140 /// Constructs a matcher that matches both `self` and `right`.
141 ///
142 /// ```
143 /// # use googletest::prelude::*;
144 /// # fn should_pass() -> Result<()> {
145 /// verify_that!("A string", starts_with("A").and(ends_with("string")))?; // Passes
146 /// # Ok(())
147 /// # }
148 /// # fn should_fail_1() -> Result<()> {
149 /// verify_that!("A string", starts_with("Another").and(ends_with("string")))?; // Fails
150 /// # Ok(())
151 /// # }
152 /// # fn should_fail_2() -> Result<()> {
153 /// verify_that!("A string", starts_with("A").and(ends_with("non-string")))?; // Fails
154 /// # Ok(())
155 /// # }
156 /// # should_pass().unwrap();
157 /// # should_fail_1().unwrap_err();
158 /// # should_fail_2().unwrap_err();
159 /// ```
160 // TODO(b/264518763): Replace the return type with impl Matcher and reduce
161 // visibility of ConjunctionMatcher once impl in return position in trait
162 // methods is stable.
and<Right: Matcher<ActualT = Self::ActualT>>( self, right: Right, ) -> ConjunctionMatcher<Self, Right> where Self: Sized,163 fn and<Right: Matcher<ActualT = Self::ActualT>>(
164 self,
165 right: Right,
166 ) -> ConjunctionMatcher<Self, Right>
167 where
168 Self: Sized,
169 {
170 ConjunctionMatcher::new(self, right)
171 }
172
173 /// Constructs a matcher that matches when at least one of `self` or `right`
174 /// matches the input.
175 ///
176 /// ```
177 /// # use googletest::prelude::*;
178 /// # fn should_pass() -> Result<()> {
179 /// verify_that!(10, eq(2).or(ge(5)))?; // Passes
180 /// verify_that!(10, eq(2).or(eq(5)).or(ge(9)))?; // Passes
181 /// # Ok(())
182 /// # }
183 /// # fn should_fail() -> Result<()> {
184 /// verify_that!(10, eq(2).or(ge(15)))?; // Fails
185 /// # Ok(())
186 /// # }
187 /// # should_pass().unwrap();
188 /// # should_fail().unwrap_err();
189 /// ```
190 // TODO(b/264518763): Replace the return type with impl Matcher and reduce
191 // visibility of DisjunctionMatcher once impl in return position in trait
192 // methods is stable.
or<Right: Matcher<ActualT = Self::ActualT>>( self, right: Right, ) -> DisjunctionMatcher<Self, Right> where Self: Sized,193 fn or<Right: Matcher<ActualT = Self::ActualT>>(
194 self,
195 right: Right,
196 ) -> DisjunctionMatcher<Self, Right>
197 where
198 Self: Sized,
199 {
200 DisjunctionMatcher::new(self, right)
201 }
202 }
203
204 /// Any actual value whose debug length is greater than this value will be
205 /// pretty-printed. Otherwise, it will have normal debug output formatting.
206 const PRETTY_PRINT_LENGTH_THRESHOLD: usize = 60;
207
208 /// Constructs a [`TestAssertionFailure`] reporting that the given `matcher`
209 /// does not match the value `actual`.
210 ///
211 /// The parameter `actual_expr` contains the expression which was evaluated to
212 /// obtain `actual`.
create_assertion_failure<T: Debug + ?Sized>( matcher: &impl Matcher<ActualT = T>, actual: &T, actual_expr: &'static str, source_location: SourceLocation, ) -> TestAssertionFailure213 pub(crate) fn create_assertion_failure<T: Debug + ?Sized>(
214 matcher: &impl Matcher<ActualT = T>,
215 actual: &T,
216 actual_expr: &'static str,
217 source_location: SourceLocation,
218 ) -> TestAssertionFailure {
219 let actual_formatted = format!("{actual:?}");
220 let actual_formatted = if actual_formatted.len() > PRETTY_PRINT_LENGTH_THRESHOLD {
221 format!("{actual:#?}")
222 } else {
223 actual_formatted
224 };
225 TestAssertionFailure::create(format!(
226 "\
227 Value of: {actual_expr}
228 Expected: {}
229 Actual: {actual_formatted},
230 {}
231 {source_location}",
232 matcher.describe(MatcherResult::Match),
233 matcher.explain_match(actual).indent(),
234 ))
235 }
236
237 /// The result of applying a [`Matcher`] on an actual value.
238 #[derive(Debug, PartialEq, Clone, Copy)]
239 pub enum MatcherResult {
240 /// The actual value matches according to the [`Matcher`] definition.
241 Match,
242 /// The actual value does not match according to the [`Matcher`] definition.
243 NoMatch,
244 }
245
246 impl From<bool> for MatcherResult {
from(b: bool) -> Self247 fn from(b: bool) -> Self {
248 if b { MatcherResult::Match } else { MatcherResult::NoMatch }
249 }
250 }
251
252 impl From<MatcherResult> for bool {
from(matcher_result: MatcherResult) -> Self253 fn from(matcher_result: MatcherResult) -> Self {
254 matcher_result.is_match()
255 }
256 }
257
258 impl MatcherResult {
259 /// Returns `true` if `self` is [`MatcherResult::Match`], otherwise
260 /// `false`.
is_match(self) -> bool261 pub fn is_match(self) -> bool {
262 matches!(self, MatcherResult::Match)
263 }
264
265 /// Returns `true` if `self` is [`MatcherResult::NoMatch`], otherwise
266 /// `false`.
is_no_match(self) -> bool267 pub fn is_no_match(self) -> bool {
268 matches!(self, MatcherResult::NoMatch)
269 }
270 }
271