Skip to main content

googletest/matchers/
matches_pattern.rs

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// There are no visible documentation elements in this module; the declarative
16// macro is documented in the matchers module.
17#![doc(hidden)]
18
19/// Matches a value according to a pattern of matchers.
20///
21/// This takes as an argument a specification similar to a struct or enum
22/// initialiser, where each value is a [`Matcher`][crate::matcher::Matcher]
23/// which is applied to the corresponding field.
24///
25/// This can be used to match arbitrary combinations of fields on structures
26/// using arbitrary matchers:
27///
28/// ```
29/// # use googletest::prelude::*;
30/// #[derive(Debug)]
31/// struct MyStruct {
32///     a_field: String,
33///     another_field: String,
34/// }
35///
36/// let my_struct = MyStruct {
37///     a_field: "Something to believe in".into(),
38///     another_field: "Something else".into()
39/// };
40/// verify_that!(my_struct, matches_pattern!(MyStruct {
41///     a_field: starts_with("Something"),
42///     another_field: ends_with("else"),
43/// }))
44/// #     .unwrap();
45/// ```
46///
47/// If any fields are provided in the pattern, then all fields must be
48/// specified, or the pattern must end with `..`, just like regular match
49/// patterns. Omitted fields have no effect on the output of the matcher.
50/// The `..` is unnecessary when no fields are provided and only method
51/// values are checked.
52///
53/// ```
54/// # use googletest::prelude::*;
55/// # #[derive(Debug)]
56/// # struct MyStruct {
57/// #     a_field: String,
58/// #     another_field: String,
59/// # }
60/// #
61/// # let my_struct = MyStruct {
62/// #     a_field: "Something to believe in".into(),
63/// #     another_field: "Something else".into()
64/// # };
65/// verify_that!(my_struct, matches_pattern!(MyStruct {
66///     a_field: starts_with("Something"),
67///     .. // another_field is missing, so it may be anything.
68/// }))
69/// #     .unwrap();
70/// ```
71///
72/// One can use it recursively to match nested structures:
73///
74/// ```
75/// # use googletest::prelude::*;
76/// #[derive(Debug)]
77/// struct MyStruct {
78///     a_nested_struct: MyInnerStruct,
79/// }
80///
81/// #[derive(Debug)]
82/// struct MyInnerStruct {
83///     a_field: String,
84/// }
85///
86/// let my_struct = MyStruct {
87///     a_nested_struct: MyInnerStruct { a_field: "Something to believe in".into() },
88/// };
89/// verify_that!(my_struct, matches_pattern!(MyStruct {
90///      a_nested_struct: matches_pattern!(MyInnerStruct {
91///         a_field: starts_with("Something"),
92///     }),
93/// }))
94/// #     .unwrap();
95/// ```
96///
97/// One can use the alias [`pat`][crate::matchers::pat] to make this less
98/// verbose:
99///
100/// ```
101/// # use googletest::prelude::*;
102/// # #[derive(Debug)]
103/// # struct MyStruct {
104/// #     a_nested_struct: MyInnerStruct,
105/// # }
106/// #
107/// # #[derive(Debug)]
108/// # struct MyInnerStruct {
109/// #     a_field: String,
110/// # }
111/// #
112/// # let my_struct = MyStruct {
113/// #     a_nested_struct: MyInnerStruct { a_field: "Something to believe in".into() },
114/// # };
115/// verify_that!(my_struct, matches_pattern!(MyStruct {
116///     a_nested_struct: pat!(MyInnerStruct {
117///         a_field: starts_with("Something"),
118///     }),
119/// }))
120/// #     .unwrap();
121/// ```
122///
123/// In addition to fields, one can match on the outputs of methods
124/// ("properties"):
125///
126/// ```
127/// # use googletest::prelude::*;
128/// #[derive(Debug)]
129/// struct MyStruct {
130///     a_field: String,
131/// }
132///
133/// impl MyStruct {
134///     fn get_a_field(&self) -> String { self.a_field.clone() }
135/// }
136///
137/// let my_struct = MyStruct { a_field: "Something to believe in".into() };
138/// verify_that!(my_struct, matches_pattern!(MyStruct {
139///     get_a_field(): starts_with("Something"),
140/// }))
141/// #     .unwrap();
142/// ```
143///
144/// If an inner matcher is `eq(...)`, it can be omitted:
145///
146/// ```
147/// # use googletest::prelude::*;
148/// #[derive(Debug)]
149/// struct MyStruct {
150///     a_field: String,
151///     another_field: String,
152/// }
153///
154/// let my_struct = MyStruct {
155///     a_field: "this".into(),
156///     another_field: "that".into()
157/// };
158/// verify_that!(my_struct, matches_pattern!(MyStruct {
159///     a_field: "this",
160///     another_field: "that",
161/// }))
162/// #     .unwrap();
163/// ```
164///
165/// **Important**: The method should be pure function with a deterministic
166/// output and no side effects. In particular, in the event of an assertion
167/// failure, it will be invoked a second time, with the assertion failure output
168/// reflecting the *second* invocation.
169///
170/// These may also include extra litteral parameters you pass in:
171///
172/// ```
173/// # use googletest::prelude::*;
174/// # #[derive(Debug)]
175/// # struct MyStruct {
176/// #     a_field: String,
177/// # }
178/// #
179/// impl MyStruct {
180///     fn append_to_a_field(&self, suffix: &str) -> String { self.a_field.clone() + suffix }
181/// }
182///
183/// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
184/// verify_that!(my_struct, matches_pattern!(&MyStruct {
185///     append_to_a_field("a suffix"): ref ends_with("a suffix"),
186/// }))
187/// #     .unwrap();
188/// ```
189///
190/// You can precede both field and property matchers with a `ref` to match the
191/// result by reference:
192///
193/// ```
194/// # use googletest::prelude::*;
195/// # #[derive(Debug)]
196/// # struct MyStruct {
197/// #     a_field: String,
198/// # }
199/// #
200/// impl MyStruct {
201///     fn get_a_field_ref(&self) -> String { self.a_field.clone() }
202/// }
203///
204/// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
205/// verify_that!(my_struct, matches_pattern!(&MyStruct {
206///     get_a_field_ref(): ref starts_with("Something"),
207/// }))
208/// #    .unwrap();
209/// ```
210///
211/// Note that if the `actual` is of type `&ActualT` and the pattern type is
212/// `ActualT`, this is automatically performed. This behavior is similar to the
213/// reference binding mode in pattern matching.
214///
215/// ```
216/// # use googletest::prelude::*;
217/// # #[derive(Debug)]
218/// # struct MyStruct {
219/// #     a_field: String,
220/// # }
221/// #
222/// impl MyStruct {
223///     fn get_a_field_ref(&self) -> String { self.a_field.clone() }
224/// }
225///
226/// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
227/// verify_that!(my_struct, matches_pattern!(MyStruct {
228///     get_a_field_ref(): starts_with("Something"),
229/// }))
230/// #    .unwrap();
231/// ```
232///
233/// One can also match tuple structs with up to 10 fields. In this case, all
234/// fields must have matchers:
235///
236/// ```
237/// # use googletest::prelude::*;
238/// #[derive(Debug)]
239/// struct MyTupleStruct(String, String);
240///
241/// let my_struct = MyTupleStruct("Something".into(), "Some other thing".into());
242/// verify_that!(
243///     my_struct,
244///     matches_pattern!(&MyTupleStruct(ref eq("Something"), ref eq("Some other thing")))
245/// )
246/// #    .unwrap();
247/// ```
248///
249/// The macro also allows matching on specific enum values and supports wildcard
250/// patterns like `MyEnum::Case(_)`.
251///
252/// ```
253/// # use googletest::prelude::*;
254/// #[derive(Debug)]
255/// enum MyEnum {
256///     A(u32),
257///     B,
258/// }
259///
260/// # fn should_pass() -> Result<()> {
261/// verify_that!(MyEnum::A(123), matches_pattern!(&MyEnum::A(eq(123))))?; // Passes
262/// #     Ok(())
263/// # }
264/// # fn should_pass_with_wildcard() -> Result<()> {
265/// verify_that!(MyEnum::A(123), matches_pattern!(MyEnum::A(_)))?; // Passes
266/// #     Ok(())
267/// # }
268/// # fn should_fail() -> Result<()> {
269/// verify_that!(MyEnum::B, matches_pattern!(&MyEnum::A(eq(123))))?; // Fails - wrong enum variant
270/// #     Ok(())
271/// # }
272/// # should_pass().unwrap();
273/// # should_pass_with_wildcard().unwrap();
274/// # should_fail().unwrap_err();
275/// ```
276///
277/// This macro does not support plain (non-struct) tuples. But it should not be
278/// necessary as tuple of matchers are matchers of tuple. In other words, if
279/// `MatcherU: Matcher<U>` and `MatcherT: Matcher<T>`, then `(MatcherU,
280/// MatcherT): Matcher<(U, T)>`.
281///
282/// Trailing commas are allowed (but not required) in both ordinary and tuple
283/// structs.
284///
285/// Note that the default format (rustfmt) can format macros if the macro
286/// argument is parseable Rust code. This is mostly true for this macro with two
287/// exceptions:
288///  * property matching
289///  * `ref` keyword with named fields
290///
291/// An option for formatting large is to avoid these exceptions (by removing the
292/// parenthesis of properties and the `ref` keywords), run `rustfmt` and add
293/// them back.
294#[macro_export]
295#[doc(hidden)]
296macro_rules! __matches_pattern {
297    ($($t:tt)*) => { $crate::matches_pattern_internal!($($t)*) }
298}
299
300// Internal-only macro created so that the macro definition does not appear in
301// generated documentation.
302#[doc(hidden)]
303#[macro_export]
304macro_rules! matches_pattern_internal {
305    ($($tt:tt)*) => {
306        {
307            use $crate::{self as googletest};
308            #[allow(unused)]
309            use $crate::matchers::{all, field, property};
310            $crate::matchers::__internal_unstable_do_not_depend_on_these::__googletest_macro_matches_pattern!($($tt)*)
311        }
312    };
313}
314
315/// An alias for [`matches_pattern`][crate::matchers::matches_pattern!].
316#[macro_export]
317#[doc(hidden)]
318macro_rules! __pat {
319    ($($t:tt)*) => { $crate::matches_pattern_internal!($($t)*) }
320}
321
322#[doc(hidden)]
323pub mod internal {
324    use crate::matcher::{Matcher, MatcherBase};
325    use std::fmt::Debug;
326
327    pub use ::googletest_macro::__googletest_macro_matches_pattern;
328
329    // Specialized implementation of the `predicate` matcher to support ref binding
330    // mode for `matches_pattern`.
331    pub fn pattern_only<T>(
332        matcher_function: fn(&T) -> bool,
333        match_description: &'static str,
334        no_match_description: &'static str,
335    ) -> PatternOnlyMatcher<T> {
336        PatternOnlyMatcher { matcher_function, match_description, no_match_description }
337    }
338
339    #[derive(MatcherBase)]
340    #[doc(hidden)]
341    pub struct PatternOnlyMatcher<T> {
342        matcher_function: fn(&T) -> bool,
343        match_description: &'static str,
344        no_match_description: &'static str,
345    }
346
347    impl<'a, T: Debug> Matcher<&'a T> for PatternOnlyMatcher<T> {
348        fn matches(&self, actual: &'a T) -> crate::matcher::MatcherResult {
349            (self.matcher_function)(actual).into()
350        }
351
352        fn describe(
353            &self,
354            matcher_result: crate::matcher::MatcherResult,
355        ) -> crate::description::Description {
356            match matcher_result {
357                crate::matcher::MatcherResult::Match => self.match_description.into(),
358                crate::matcher::MatcherResult::NoMatch => self.no_match_description.into(),
359            }
360        }
361    }
362
363    impl<T: Debug + Copy> Matcher<T> for PatternOnlyMatcher<T> {
364        fn matches(&self, actual: T) -> crate::matcher::MatcherResult {
365            (self.matcher_function)(&actual).into()
366        }
367
368        fn describe(
369            &self,
370            matcher_result: crate::matcher::MatcherResult,
371        ) -> crate::description::Description {
372            match matcher_result {
373                crate::matcher::MatcherResult::Match => self.match_description.into(),
374                crate::matcher::MatcherResult::NoMatch => self.no_match_description.into(),
375            }
376        }
377    }
378
379    /// A matcher that ensures that the passed-in function compiles with the
380    /// benefit of inference from the value being tested. The passed-in
381    /// matcher is what is actually invoked for matching.
382    ///
383    /// It forwards all description responsibilities to the passed-in matcher.
384    pub fn compile_assert_and_match<T, M>(
385        must_compile_function: fn(&T),
386        matcher: M,
387    ) -> CompileAssertAndMatch<T, M> {
388        CompileAssertAndMatch { must_compile_function, matcher }
389    }
390
391    #[derive(MatcherBase)]
392    #[doc(hidden)]
393    pub struct CompileAssertAndMatch<T, M> {
394        #[allow(dead_code)]
395        must_compile_function: fn(&T),
396        matcher: M,
397    }
398
399    impl<'a, T: Debug, M> Matcher<&'a T> for CompileAssertAndMatch<T, M>
400    where
401        M: Matcher<&'a T>,
402    {
403        fn matches(&self, actual: &'a T) -> crate::matcher::MatcherResult {
404            self.matcher.matches(actual)
405        }
406
407        fn describe(
408            &self,
409            matcher_result: crate::matcher::MatcherResult,
410        ) -> crate::description::Description {
411            self.matcher.describe(matcher_result)
412        }
413
414        fn explain_match(&self, actual: &'a T) -> crate::description::Description {
415            self.matcher.explain_match(actual)
416        }
417    }
418
419    impl<T: Debug + Copy, M> Matcher<T> for CompileAssertAndMatch<T, M>
420    where
421        M: Matcher<T>,
422    {
423        fn matches(&self, actual: T) -> crate::matcher::MatcherResult {
424            self.matcher.matches(actual)
425        }
426
427        fn describe(
428            &self,
429            matcher_result: crate::matcher::MatcherResult,
430        ) -> crate::description::Description {
431            self.matcher.describe(matcher_result)
432        }
433
434        fn explain_match(&self, actual: T) -> crate::description::Description {
435            self.matcher.explain_match(actual)
436        }
437    }
438}
439
440mod compile_fail_tests {
441    /// ```compile_fail
442    /// use ::googletest::prelude::*;
443    /// #[derive(Debug)]
444    /// struct Foo { a: u32 }
445    /// impl Foo {
446    ///   fn b() {}
447    /// }
448    /// let actual = Foo { a: 1 };
449    /// verify_that!(actual, matches_pattern!(Foo { a: eq(&1), b(): _ }));
450    /// ```
451    fn _underscore_unsupported_for_methods() {}
452
453    /// ```compile_fail
454    /// use ::googletest::prelude::*;
455    /// #[derive(Debug)]
456    /// struct Foo { a: u32, b: u32 }
457    /// let actual = Foo { a: 1, b: 2 };
458    /// verify_that!(actual, matches_pattern!(Foo { a: eq(&1), .., }));
459    /// ```
460    fn _dot_dot_supported_only_at_end_of_struct_pattern() {}
461
462    /// ```compile_fail
463    /// use ::googletest::prelude::*;
464    /// #[derive(Debug)]
465    /// struct Foo(u32, u32);
466    /// let actual = Foo(1, 2);
467    /// verify_that!(actual, matches_pattern!(Foo(eq(&1), .., )));
468    /// ```
469    fn _dot_dot_supported_only_at_end_of_tuple_struct_pattern() {}
470
471    /// ```compile_fail
472    /// use ::googletest::prelude::*;
473    /// #[derive(Debug)]
474    /// struct Foo { a: u32, b: u32 }
475    /// let actual = Foo { a: 1, b: 2 };
476    /// verify_that!(actual, matches_pattern!(Foo { a: eq(&1) }));
477    /// ```
478    fn _unexhaustive_struct_field_check_requires_dot_dot() {}
479
480    /// ```compile_fail
481    /// use ::googletest::prelude::*;
482    /// #[derive(Debug)]
483    /// enum Foo {
484    ///     Bar { a: u32, b: u32 }
485    /// }
486    /// let actual = Foo::Bar { a: 1, b: 2 };
487    /// verify_that!(actual, matches_pattern!(Foo::Bar { a: eq(&1) }));
488    /// ```
489    fn _unexhaustive_enum_struct_field_check_requires_dot_dot() {}
490
491    /// ```compile_fail
492    /// use ::googletest::prelude::*;
493    /// #[derive(Debug)]
494    /// struct Foo(u32, u32, u32);
495    /// let actual = Foo(1, 2, 3);
496    /// verify_that!(actual, matches_pattern!(Foo(eq(&1), eq(&2) )));
497    /// ```
498    fn _unexhaustive_tuple_struct_field_check_requires_dot_dot() {}
499
500    /// ```compile_fail
501    /// use ::googletest::prelude::*;
502    /// verify_that!(1, matches_pattern!(UndefinedSymbol { }));
503    /// ```
504    fn _should_fail_to_compile_unknown_struct_with_no_fields() {}
505
506    /// ```compile_fail
507    /// use ::googletest::prelude::*;
508    /// verify_that!(1, matches_pattern!(UndefinedSymbol { a: 1 }));
509    /// ```
510    fn _should_fail_to_compile_unknown_struct_with_field() {}
511
512    /// ```compile_fail
513    /// use ::googletest::prelude::*;
514    /// verify_that!(1, matches_pattern!(UndefinedSymbol { .. }));
515    /// ```
516    fn _should_fail_to_compile_unknown_struct_with_dot_dot() {}
517
518    /// ```compile_fail
519    /// use ::googletest::prelude::*;
520    /// verify_that!(1, matches_pattern!(UndefinedSymbol( .. )));
521    /// ```
522    fn _should_fail_to_compile_unknown_tuple_struct_with_dot_dot() {}
523}