Skip to main content

googletest/matchers/
tuple_matcher.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 at the top level.
17#![doc(hidden)]
18
19/// Functions for use only by the declarative macros in this module.
20///
21/// **For internal use only. API stablility is not guaranteed!**
22#[doc(hidden)]
23pub mod internal {
24    use crate::{
25        description::Description,
26        matcher::{Matcher, MatcherBase, MatcherResult},
27    };
28    use std::fmt::Debug;
29
30    impl MatcherBase for () {}
31
32    // This implementation is provided for completeness, but is completely trivial.
33    // The only actual value which can be supplied is (), which must match.
34    impl Matcher<()> for () {
35        fn matches(&self, _: ()) -> MatcherResult {
36            MatcherResult::Match
37        }
38
39        fn describe(&self, matcher_result: MatcherResult) -> Description {
40            match matcher_result {
41                MatcherResult::Match => "is the empty tuple".into(),
42                MatcherResult::NoMatch => "is not the empty tuple".into(),
43            }
44        }
45    }
46
47    impl Matcher<&()> for () {
48        fn matches(&self, _: &()) -> MatcherResult {
49            MatcherResult::Match
50        }
51
52        fn describe(&self, matcher_result: MatcherResult) -> Description {
53            <Self as Matcher<()>>::describe(self, matcher_result)
54        }
55    }
56
57    /// Generates a tuple matcher for tuples of a specific length.
58    ///
59    /// **For internal use only. API stablility is not guaranteed!**
60    #[doc(hidden)]
61    macro_rules! tuple_matcher_n {
62        ($([$field_number:tt, $matcher_type:ident, $field_type:ident]),*) => {
63            impl<$($matcher_type: MatcherBase),*> MatcherBase for ($($matcher_type,)*){}
64
65            impl<$($field_type: Debug + Copy, $matcher_type: Matcher<$field_type>),*>
66                Matcher<($($field_type,)*)> for ($($matcher_type,)*)
67            {
68                fn matches(&self, actual:  ($($field_type,)*)) -> MatcherResult {
69                    $(match self.$field_number.matches(actual.$field_number) {
70                        MatcherResult::Match => {},
71                        MatcherResult::NoMatch => {
72                            return MatcherResult::NoMatch;
73                        }
74                    })*
75                    MatcherResult::Match
76                }
77
78                fn explain_match(&self, actual:  ($($field_type,)*)) -> Description  {
79                    let mut explanation = Description::new().text("which").nested(
80                        self.describe(self.matches(actual)));
81                    $(match self.$field_number.matches(actual.$field_number) {
82                        MatcherResult::Match => {},
83                        MatcherResult::NoMatch => {
84                            explanation = explanation
85                                .text(format!(concat!("Element #", $field_number, " is {:?},"),
86                                    actual.$field_number))
87                                .nested(self.$field_number.explain_match(actual.$field_number));
88                        }
89                    })*
90                    explanation
91                }
92
93                fn describe(&self, matcher_result: MatcherResult) -> Description {
94                    match matcher_result {
95                        MatcherResult::Match => {
96                            let mut description = Description::new().text(
97                                "is a tuple whose values respectively match:");
98                            $(description = description.nested(
99                                self.$field_number.describe(matcher_result));)*
100                            description
101                        }
102                        MatcherResult::NoMatch => {
103                            let mut description = Description::new().text(
104                                "is a tuple whose values do not respectively match:");
105                            $(description = description.nested(
106                                self.$field_number.describe(MatcherResult::Match));)*
107                            description
108                        }
109                    }
110                }
111            }
112            impl<'a, $($field_type: Debug, $matcher_type: Matcher<&'a $field_type>),*>
113                Matcher<&'a ($($field_type,)*)> for ($($matcher_type,)*)
114            {
115                fn matches(&self, actual:  &'a ($($field_type,)*)) -> MatcherResult {
116                    $(match self.$field_number.matches(&actual.$field_number) {
117                        MatcherResult::Match => {},
118                        MatcherResult::NoMatch => {
119                            return MatcherResult::NoMatch;
120                        }
121                    })*
122                    MatcherResult::Match
123                }
124
125                fn explain_match(&self, actual:  &'a ($($field_type,)*)) -> Description  {
126                    let mut explanation = Description::new()
127                        .text("which")
128                        .nested(
129                            Matcher::<&'a ($($field_type,)*)>::describe(
130                                self, self.matches(actual)));
131                    $(match self.$field_number.matches(&actual.$field_number) {
132                        MatcherResult::Match => {},
133                        MatcherResult::NoMatch => {
134                            explanation = explanation
135                                .text(format!(
136                                    concat!(
137                                        "Element #",
138                                        $field_number,
139                                        " is {:?},"),
140                                        actual.$field_number))
141                                .nested(self.$field_number.explain_match(&actual.$field_number));
142                        }
143                    })*
144                    explanation
145                }
146
147                fn describe(&self, matcher_result: MatcherResult) -> Description {
148                    match matcher_result {
149                        MatcherResult::Match => {
150                            let mut description = Description::new().text(
151                                "is a tuple whose values respectively match:");
152                            $(description = description.nested(
153                                self.$field_number.describe(matcher_result));)*
154                            description
155                        }
156                        MatcherResult::NoMatch => {
157                            let mut description = Description::new().text(
158                                "is a tuple whose values do not respectively match:");
159                            $(description = description.nested(
160                                self.$field_number.describe(MatcherResult::Match));)*
161                            description
162                        }
163                    }
164                }
165            }
166        };
167    }
168
169    tuple_matcher_n!([0, I0, T0]);
170
171    tuple_matcher_n!([0, I0, T0], [1, I1, T1]);
172
173    tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2]);
174
175    tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3]);
176
177    tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4]);
178
179    tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4], [5, I5, T5]);
180
181    tuple_matcher_n!(
182        [0, I0, T0],
183        [1, I1, T1],
184        [2, I2, T2],
185        [3, I3, T3],
186        [4, I4, T4],
187        [5, I5, T5],
188        [6, I6, T6]
189    );
190
191    tuple_matcher_n!(
192        [0, I0, T0],
193        [1, I1, T1],
194        [2, I2, T2],
195        [3, I3, T3],
196        [4, I4, T4],
197        [5, I5, T5],
198        [6, I6, T6],
199        [7, I7, T7]
200    );
201
202    tuple_matcher_n!(
203        [0, I0, T0],
204        [1, I1, T1],
205        [2, I2, T2],
206        [3, I3, T3],
207        [4, I4, T4],
208        [5, I5, T5],
209        [6, I6, T6],
210        [7, I7, T7],
211        [8, I8, T8]
212    );
213
214    tuple_matcher_n!(
215        [0, I0, T0],
216        [1, I1, T1],
217        [2, I2, T2],
218        [3, I3, T3],
219        [4, I4, T4],
220        [5, I5, T5],
221        [6, I6, T6],
222        [7, I7, T7],
223        [8, I8, T8],
224        [9, I9, T9]
225    );
226
227    tuple_matcher_n!(
228        [0, I0, T0],
229        [1, I1, T1],
230        [2, I2, T2],
231        [3, I3, T3],
232        [4, I4, T4],
233        [5, I5, T5],
234        [6, I6, T6],
235        [7, I7, T7],
236        [8, I8, T8],
237        [9, I9, T9],
238        [10, I10, T10]
239    );
240
241    tuple_matcher_n!(
242        [0, I0, T0],
243        [1, I1, T1],
244        [2, I2, T2],
245        [3, I3, T3],
246        [4, I4, T4],
247        [5, I5, T5],
248        [6, I6, T6],
249        [7, I7, T7],
250        [8, I8, T8],
251        [9, I9, T9],
252        [10, I10, T10],
253        [11, I11, T11]
254    );
255}