Macro googletest::matchers::matches_pattern
source · macro_rules! matches_pattern { ($($t:tt)*) => { ... }; }
Expand description
Matches a value according to a pattern of matchers.
This takes as an argument a specification similar to a struct or enum
initialiser, where each value is a Matcher
which is applied to the corresponding field.
This can be used to match arbitrary combinations of fields on structures using arbitrary matchers:
#[derive(Debug)]
struct MyStruct {
a_field: String,
another_field: String,
}
let my_struct = MyStruct {
a_field: "Something to believe in".into(),
another_field: "Something else".into()
};
verify_that!(my_struct, matches_pattern!(MyStruct {
a_field: starts_with("Something"),
another_field: ends_with("else"),
}))
It is not required to include all named fields in the specification. Omitted fields have no effect on the output of the matcher.
verify_that!(my_struct, matches_pattern!(MyStruct {
a_field: starts_with("Something"),
// another_field is missing, so it may be anything.
}))
One can use it recursively to match nested structures:
#[derive(Debug)]
struct MyStruct {
a_nested_struct: MyInnerStruct,
}
#[derive(Debug)]
struct MyInnerStruct {
a_field: String,
}
let my_struct = MyStruct {
a_nested_struct: MyInnerStruct { a_field: "Something to believe in".into() },
};
verify_that!(my_struct, matches_pattern!(MyStruct {
a_nested_struct: matches_pattern!(MyInnerStruct {
a_field: starts_with("Something"),
}),
}))
One can use the alias pat
to make this less
verbose:
verify_that!(my_struct, matches_pattern!(MyStruct {
a_nested_struct: pat!(MyInnerStruct {
a_field: starts_with("Something"),
}),
}))
In addition to fields, one can match on the outputs of methods (“properties”):
#[derive(Debug)]
struct MyStruct {
a_field: String,
}
impl MyStruct {
fn get_a_field(&self) -> String { self.a_field.clone() }
}
let my_struct = MyStruct { a_field: "Something to believe in".into() };
verify_that!(my_struct, matches_pattern!(MyStruct {
get_a_field(): starts_with("Something"),
}))
Important: The method should be pure function with a deterministic output and no side effects. In particular, in the event of an assertion failure, it will be invoked a second time, with the assertion failure output reflecting the second invocation.
These may also include extra parameters you pass in:
impl MyStruct {
fn append_to_a_field(&self, suffix: &str) -> String { self.a_field.clone() + suffix }
}
verify_that!(my_struct, matches_pattern!(MyStruct {
append_to_a_field("a suffix"): ends_with("a suffix"),
}))
If the method returns a reference, precede it with a *
:
impl MyStruct {
fn get_a_field_ref(&self) -> &String { &self.a_field }
}
verify_that!(my_struct, matches_pattern!(MyStruct {
*get_a_field_ref(): starts_with("Something"),
}))
One can also match tuple structs with up to 10 fields. In this case, all fields must have matchers:
#[derive(Debug)]
struct MyTupleStruct(String, String);
let my_struct = MyTupleStruct("Something".into(), "Some other thing".into());
verify_that!(
my_struct,
matches_pattern!(MyTupleStruct(eq("Something"), eq("Some other thing")))
)
One can also match enum values:
#[derive(Debug)]
enum MyEnum {
A(u32),
B,
}
verify_that!(MyEnum::A(123), matches_pattern!(MyEnum::A(eq(123))))?; // Passes
verify_that!(MyEnum::B, matches_pattern!(MyEnum::A(eq(123))))?; // Fails - wrong enum variant
This macro does not support plain (non-struct) tuples. Use the macro
tuple
for that purpose.
Trailing commas are allowed (but not required) in both ordinary and tuple structs.
Unfortunately, this matcher does not work with methods returning string slices:
pub struct MyStruct {
a_string: String,
}
impl MyStruct {
pub fn get_a_string(&self) -> &str { &self.a_string }
}
let value = MyStruct { a_string: "A string".into() };
verify_that!(value, matches_pattern!( MyStruct {
get_a_string(): eq("A string"), // Does not compile
}))