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