Skip to content

Commit f4b64c1

Browse files
marcianxcopybara-github
authored andcommitted
In property_matcher! and field_matcher!, support explicit type parameters in structs and method calls. This effectively also adds support for these in matches_pattern!.
PiperOrigin-RevId: 708364017
1 parent 842a570 commit f4b64c1

File tree

9 files changed

+337
-80
lines changed

9 files changed

+337
-80
lines changed

googletest/src/internal/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
pub(crate) mod description_renderer;
1818
pub mod glob;
19+
pub mod test_data;
1920
pub mod test_filter;
2021
pub mod test_outcome;
2122
pub mod test_sharding;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! This is for testing only to provide fully-qualified struct paths to macros.
2+
3+
#[doc(hidden)]
4+
#[derive(Debug)]
5+
pub struct TestStruct {
6+
#[doc(hidden)]
7+
pub value: u32,
8+
}
9+
10+
impl TestStruct {
11+
#[doc(hidden)]
12+
pub fn get_value(&self) -> u32 {
13+
self.value
14+
}
15+
}
16+
17+
#[doc(hidden)]
18+
#[derive(Debug)]
19+
pub struct GenericTestStruct<T> {
20+
#[doc(hidden)]
21+
pub value: T,
22+
}
23+
24+
impl<T> GenericTestStruct<T> {
25+
#[doc(hidden)]
26+
pub fn get_value<U>(&self, a: U) -> U {
27+
a
28+
}
29+
}

googletest/src/matchers/field_matcher.rs

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -196,41 +196,42 @@ macro_rules! __field {
196196
#[doc(hidden)]
197197
#[macro_export]
198198
macro_rules! field_internal {
199-
(&$($t:ident)::+.$field:tt, ref $m:expr) => {{
200-
$crate::matchers::__internal_unstable_do_not_depend_on_these::field_matcher(
201-
|o: &_| {
202-
match o {
203-
&$($t)::* {$field: ref value, .. } => Some(value),
204-
// The pattern below is unreachable if the type is a struct (as opposed to an
205-
// enum). Since the macro can't know which it is, we always include it and just
206-
// tell the compiler not to complain.
207-
#[allow(unreachable_patterns)]
208-
_ => None,
209-
}
210-
},
211-
&stringify!($field),
212-
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
199+
(&$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, ref $m:expr) => {{
200+
$crate::field_internal!(@internal
201+
[&_] [&$($t)::* $(::<$($t_ty_args),*>)*]
202+
[$field] [ref] [$m])
213203
}};
214-
(&$($t:ident)::+.$field:tt, $m:expr) => {{
215-
$crate::matchers::__internal_unstable_do_not_depend_on_these::field_matcher(
216-
|o: &&_| {
217-
match o {
218-
&$($t)::* {$field: value, .. } => Some(value),
219-
// The pattern below is unreachable if the type is a struct (as opposed to an
220-
// enum). Since the macro can't know which it is, we always include it and just
221-
// tell the compiler not to complain.
222-
#[allow(unreachable_patterns)]
223-
_ => None,
224-
}
225-
},
226-
&stringify!($field),
227-
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
204+
(&$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
205+
$crate::field_internal!(@internal
206+
[&&_] [&$($t)::* $(::<$($t_ty_args),*>)*]
207+
[$field] [] [$m])
228208
}};
229-
($($t:ident)::+.$field:tt, $m:expr) => {{
209+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
210+
$crate::field_internal!(@internal
211+
[&_] [$($t)::* $(::<$($t_ty_args),*>)*]
212+
[$field] [] [$m])
213+
}};
214+
(& :: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, ref $m:expr) => {{
215+
$crate::field_internal!(@internal
216+
[&_] [&::$($t)::* $(::<$($t_ty_args),*>)*]
217+
[$field] [ref] [$m])
218+
}};
219+
(& :: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
220+
$crate::field_internal!(@internal
221+
[&&_] [&::$($t)::* $(::<$($t_ty_args),*>)*]
222+
[$field] [] [$m])
223+
}};
224+
(:: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
225+
$crate::field_internal!(@internal
226+
[&_] [::$($t)::* $(::<$($t_ty_args),*>)*]
227+
[$field] [] [$m])
228+
}};
229+
230+
(@internal [$struct_ty:ty] [$($field_prefix:tt)*] [$field:tt] [$($ref:tt)?] [$m:expr]) => {{
230231
$crate::matchers::__internal_unstable_do_not_depend_on_these::field_matcher(
231-
|o: &_| {
232+
|o: $struct_ty| {
232233
match o {
233-
$($t)::* {$field: value, .. } => Some(value),
234+
$($field_prefix)* {$field: $($ref)* value, .. } => Some(value),
234235
// The pattern below is unreachable if the type is a struct (as opposed to an
235236
// enum). Since the macro can't know which it is, we always include it and just
236237
// tell the compiler not to complain.
@@ -240,7 +241,8 @@ macro_rules! field_internal {
240241
},
241242
&stringify!($field),
242243
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
243-
}};
244+
245+
}}
244246
}
245247

246248
/// Functions for use only by the declarative macros in this module.

googletest/src/matchers/property_matcher.rs

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,29 +176,82 @@ macro_rules! __property {
176176
#[doc(hidden)]
177177
#[macro_export]
178178
macro_rules! property_internal {
179+
(& $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
180+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
181+
ref $m:expr) => {{
182+
$crate::property_internal!(@self_arg
183+
struct_type: [&$($t)::+ $( <$($t_ty_args),*>)*]
184+
method_prefix: [ $($t)::+ $(::<$($t_ty_args),*>)*]
185+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
186+
}};
187+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
188+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
189+
ref $m:expr) => {{
190+
$crate::property_internal!(@self_arg
191+
struct_type: [$($t)::+ $( <$($t_ty_args),*>)*]
192+
method_prefix: [$($t)::+ $(::<$($t_ty_args),*>)*]
193+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
194+
}};
195+
(& ::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
196+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
197+
ref $m:expr) => {{
198+
$crate::property_internal!(@self_arg
199+
struct_type: [&::$($t)::+ $( <$($t_ty_args),*>)*]
200+
method_prefix: [ ::$($t)::+ $(::<$($t_ty_args),*>)*]
201+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
202+
}};
203+
(::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
204+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
205+
ref $m:expr) => {{
206+
$crate::property_internal!(@self_arg
207+
struct_type: [::$($t)::+ $( <$($t_ty_args),*>)*]
208+
method_prefix: [::$($t)::+ $(::<$($t_ty_args),*>)*]
209+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
210+
}};
179211

180-
(&$($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
181-
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_ref_matcher(
182-
|o: &$($t)::+| $($t)::+::$method(o, $($argument),*),
183-
&stringify!($method($($argument),*)),
184-
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
212+
(& $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
213+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
214+
$m:expr) => {{
215+
$crate::property_internal!(@self_dot
216+
struct_type: [&&$($t)::+ $(<$($t_ty_args),*>)*]
217+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
185218
}};
186-
($($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
187-
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_ref_matcher(
188-
|o: $($t)::+| $($t)::+::$method(o, $($argument),*),
189-
&stringify!($method($($argument),*)),
190-
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
219+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
220+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
221+
$m:expr) => {{
222+
$crate::property_internal!(@self_dot
223+
struct_type: [&$($t)::+ $(<$($t_ty_args),*>)*]
224+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
191225
}};
192-
(& $($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
193-
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_matcher(
194-
|o: &&$($t)::+| o.$method($($argument),*),
195-
&stringify!($method($($argument),*)),
226+
(& ::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
227+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
228+
$m:expr) => {{
229+
$crate::property_internal!(@self_dot
230+
struct_type: [&&::$($t)::+ $(<$($t_ty_args),*>)*]
231+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
232+
}};
233+
(::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
234+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
235+
$m:expr) => {{
236+
$crate::property_internal!(@self_dot
237+
struct_type: [&::$($t)::+ $(<$($t_ty_args),*>)*]
238+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
239+
}};
240+
241+
(@self_arg struct_type: [$struct_ty:ty]
242+
method_prefix: [$($method_prefix:tt)+]
243+
[$($method:tt)*] [$($argument:expr),*] [$m:expr]) => {{
244+
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_ref_matcher(
245+
|o: $struct_ty| $($method_prefix)*::$($method)* (o, $($argument),*),
246+
&stringify!($($method)* ($($argument),*)),
196247
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
197248
}};
198-
($($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
249+
250+
(@self_dot struct_type: [$struct_ty:ty]
251+
[$($method:tt)*] [$($argument:expr),*] [$m:expr]) => {{
199252
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_matcher(
200-
|o: &$($t)::+| o.$method($($argument),*),
201-
&stringify!($method($($argument),*)),
253+
|o: $struct_ty| o.$($method)* ($($argument),*),
254+
&stringify!($($method)* ($($argument),*)),
202255
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
203256
}};
204257
}

googletest/tests/field_matcher_test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,52 @@ fn matches_enum_with_auto_eq_with_wrapper() -> Result<()> {
263263
field!(Wrapper.wrapped, field!(Wrapper.wrapped, &23))
264264
)
265265
}
266+
267+
#[test]
268+
fn supports_fully_qualified_struct_path() -> Result<()> {
269+
// Ensure that the macro expands to the fully-qualified struct path.
270+
mod googletest {}
271+
272+
let value = ::googletest::internal::test_data::TestStruct { value: 10 };
273+
verify_that!(value, field!(&::googletest::internal::test_data::TestStruct.value, ref eq(&10)))?;
274+
verify_that!(value, field!(&::googletest::internal::test_data::TestStruct.value, eq(10)))?;
275+
verify_that!(value, field!(::googletest::internal::test_data::TestStruct.value, eq(&10)))?;
276+
Ok(())
277+
}
278+
279+
#[test]
280+
fn supports_generic_struct() -> Result<()> {
281+
#[derive(Debug)]
282+
struct Struct<S, T> {
283+
#[allow(dead_code)] // The property1 field is used only for adding the type parameter.
284+
property1: S,
285+
property2: T,
286+
}
287+
288+
let value = Struct { property1: 1, property2: 10 };
289+
verify_that!(&value, field!(&Struct::<i32, u32>.property2, ref eq(&10)))?;
290+
verify_that!(value, field!(&Struct::<i32, u32>.property2, eq(10)))?;
291+
verify_that!(value, field!(Struct::<i32, u32>.property2, eq(&10)))?;
292+
Ok(())
293+
}
294+
295+
#[test]
296+
fn supports_fully_qualified_generic_struct() -> Result<()> {
297+
// Ensure that the macro expands to the fully-qualified struct path.
298+
mod googletest {}
299+
300+
let value = ::googletest::internal::test_data::GenericTestStruct { value: 10 };
301+
verify_that!(
302+
&value,
303+
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, ref eq(&10))
304+
)?;
305+
verify_that!(
306+
value,
307+
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(10))
308+
)?;
309+
verify_that!(
310+
value,
311+
field!(::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(&10))
312+
)?;
313+
Ok(())
314+
}

googletest/tests/lib.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.

googletest/tests/matches_pattern_struct_test.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,3 +1194,57 @@ fn matches_struct_with_a_method_taking_two_parameters_ret_ref_and_field() -> Res
11941194
matches_pattern!(&AStruct { get_field_ref(2, 3): eq(&1), another_field: eq(123), .. })
11951195
)
11961196
}
1197+
1198+
#[test]
1199+
fn matches_with_fully_qualified_struct_path() -> Result<()> {
1200+
// Ensure that the macro expands to the fully-qualified struct path.
1201+
mod googletest {}
1202+
1203+
let value = ::googletest::internal::test_data::TestStruct { value: 10 };
1204+
verify_that!(
1205+
value,
1206+
matches_pattern!(
1207+
&::googletest::internal::test_data::TestStruct {
1208+
value: eq(10),
1209+
get_value(): eq(10)
1210+
}
1211+
)
1212+
)
1213+
}
1214+
1215+
#[test]
1216+
fn matches_with_explicit_type_parameters() -> Result<()> {
1217+
#[derive(Debug)]
1218+
struct AStruct<T> {
1219+
field: T,
1220+
}
1221+
1222+
impl<T: Copy> AStruct<T> {
1223+
fn get_default<U: Default>(&self) -> U {
1224+
Default::default()
1225+
}
1226+
}
1227+
1228+
let actual = AStruct::<i32> { field: 1 };
1229+
verify_that!(
1230+
actual,
1231+
matches_pattern!(&AStruct::<i32> { field: eq(1), get_default::<i16>(): eq(0) })
1232+
)
1233+
}
1234+
1235+
#[test]
1236+
fn matches_with_fully_qualified_generic_struct_path() -> Result<()> {
1237+
// Ensure that the macro expands to the fully-qualified struct path.
1238+
mod googletest {}
1239+
1240+
let value = ::googletest::internal::test_data::GenericTestStruct { value: 10 };
1241+
verify_that!(
1242+
value,
1243+
matches_pattern!(
1244+
&::googletest::internal::test_data::GenericTestStruct::<i16> {
1245+
value: eq(10),
1246+
get_value::<i16>(20): eq(20)
1247+
}
1248+
)
1249+
)
1250+
}

0 commit comments

Comments
 (0)