Skip to main content

googletest/matchers/
any_matcher.rs

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// 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 which at least one of the given matchers match.
20///
21/// Each argument is a [`Matcher`][crate::matcher::Matcher] which matches
22/// against the actual value.
23///
24/// For example:
25///
26/// ```
27/// # use googletest::prelude::*;
28/// # fn should_pass() -> Result<()> {
29/// verify_that!("A string", any!(starts_with("A"), ends_with("string")))?; // Passes
30/// verify_that!("A string", any!(starts_with("A"), starts_with("string")))?; // Passes
31/// verify_that!("A string", any!(ends_with("A"), ends_with("string")))?; // Passes
32/// #     Ok(())
33/// # }
34/// # fn should_fail() -> Result<()> {
35/// verify_that!("A string", any!(starts_with("An"), ends_with("not a string")))?; // Fails
36/// #     Ok(())
37/// # }
38/// # should_pass().unwrap();
39/// # should_fail().unwrap_err();
40/// ```
41///
42/// Using this macro is equivalent to using the
43/// [`or`][crate::matcher::MatcherBase::or] method:
44///
45/// ```
46/// # use googletest::prelude::*;
47/// # fn should_pass() -> Result<()> {
48/// verify_that!(10, gt(9).or(lt(8)))?; // Also passes
49/// #     Ok(())
50/// # }
51/// # should_pass().unwrap();
52/// ```
53///
54/// Assertion failure messages are not guaranteed to be identical, however.
55///
56///  If an inner matcher is `eq(...)`, it can be omitted:
57///
58/// ```
59/// # use googletest::prelude::*;
60///
61/// verify_that!(123, any![lt(1), 123, gt(1000)])
62/// #     .unwrap();
63/// ```
64#[macro_export]
65#[doc(hidden)]
66macro_rules! __any {
67    ($(,)?) => {{
68        $crate::matchers::not($crate::matchers::anything())
69    }} ;
70    ($matcher:expr $(,)?) => {{
71        use $crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq;
72        auto_eq!($matcher)
73    }};
74    ($head:expr, $head2:expr $(,)?) => {{
75        use $crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq;
76        $crate::matchers::__internal_unstable_do_not_depend_on_these::DisjunctionMatcher::new(auto_eq!($head), auto_eq!($head2))
77    }};
78    ($head:expr, $head2:expr, $($tail:expr),+ $(,)?) => {{
79        use $crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq;
80        $crate::__any![
81            $crate::matchers::__internal_unstable_do_not_depend_on_these::DisjunctionMatcher::new(auto_eq!($head), auto_eq!($head2)),
82            $($tail),+
83        ]
84    }}
85}
86
87#[cfg(test)]
88mod tests {
89    use crate::matcher::MatcherResult;
90    use crate::prelude::*;
91    use crate::Result;
92    use indoc::indoc;
93
94    #[test]
95    fn description_shows_more_than_one_matcher() -> Result<()> {
96        let first_matcher = starts_with("A");
97        let second_matcher = ends_with("string");
98        let matcher = any!(first_matcher, second_matcher);
99
100        verify_that!(
101            Matcher::<&String>::describe(&matcher, MatcherResult::Match),
102            displays_as(eq(indoc!(
103                "
104                has at least one of the following properties:
105                  * starts with prefix \"A\"
106                  * ends with suffix \"string\""
107            )))
108        )
109    }
110
111    #[test]
112    fn description_shows_one_matcher_directly() -> Result<()> {
113        let first_matcher = starts_with("A");
114        let matcher = any!(first_matcher);
115
116        verify_that!(
117            Matcher::<&str>::describe(&matcher, MatcherResult::Match),
118            displays_as(eq("starts with prefix \"A\""))
119        )
120    }
121
122    #[test]
123    fn mismatch_description_shows_which_matcher_failed_if_more_than_one_constituent() -> Result<()>
124    {
125        let first_matcher = starts_with("Another");
126        let second_matcher = ends_with("string");
127        let matcher = any!(first_matcher, second_matcher);
128
129        verify_that!(
130            matcher.explain_match("A string"),
131            displays_as(eq("which does not start with \"Another\""))
132        )
133    }
134
135    #[test]
136    fn mismatch_description_is_simple_when_only_one_constituent() -> Result<()> {
137        let first_matcher = starts_with("Another");
138        let matcher = any!(first_matcher);
139
140        verify_that!(
141            matcher.explain_match("A string"),
142            displays_as(eq("which does not start with \"Another\""))
143        )
144    }
145
146    #[test]
147    fn empty_any_matcher_never_matches() -> Result<()> {
148        verify_that!(123, not(any![]))
149    }
150
151    #[test]
152    fn any_with_auto_eq() -> Result<()> {
153        verify_that!(42, any![1, 2, 42, gt(123)])
154    }
155}