Add matchers to make writing AstVisitor tests easier.
Matchers for matching types will come in a followup CL; tests that require such
matchers have not yet been rewritten.
PiperOrigin-RevId: 397295915
diff --git a/rs_bindings_from_cc/ast_visitor_test.cc b/rs_bindings_from_cc/ast_visitor_test.cc
index d4d4e5e..88a9e75 100644
--- a/rs_bindings_from_cc/ast_visitor_test.cc
+++ b/rs_bindings_from_cc/ast_visitor_test.cc
@@ -21,9 +21,56 @@
namespace rs_bindings_from_cc {
namespace {
+using ::testing::AllOf;
+using ::testing::ElementsAre;
using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::Property;
using ::testing::SizeIs;
+// Matches an IR node that has the given identifier.
+MATCHER_P(IdentifierIs, identifier, "") {
+ if (arg.identifier.Ident() == identifier) return true;
+
+ *result_listener << "actual identifier: '" << arg.identifier.Ident() << "'";
+ return false;
+}
+
+// Matches a Func that has the given mangled name.
+MATCHER_P(MangledNameIs, mangled_name, "") {
+ if (arg.mangled_name == mangled_name) return true;
+
+ *result_listener << "actual mangled name: '" << arg.mangled_name << "'";
+ return false;
+}
+
+// Matches a Func that has a return type matching `matcher`.
+template <typename Matcher>
+auto ReturnType(const Matcher& matcher) {
+ return testing::Field(&Func::return_type, matcher);
+}
+
+// Matches a Func that has parameters matching `matchers`.
+template <typename... Args>
+auto ParamsAre(const Args&... matchers) {
+ return testing::Field(&Func::params, ElementsAre(matchers...));
+}
+
+// Matches a Func that is inline.
+MATCHER(IsInline, "") { return arg.is_inline; }
+
+// Matches a type that is void.
+MATCHER(IsVoid, "") { return arg.IsVoid(); }
+
+// Matches a Record that has fields matching `matchers`.
+template <typename... Args>
+auto FieldsAre(const Args&... matchers) {
+ return testing::Field(&Record::fields, ElementsAre(matchers...));
+}
+
+// Matches a Field that has the given access specifier.
+MATCHER_P(AccessIs, access, "") { return arg.access == access; }
+
constexpr absl::string_view kVirtualInputPath =
"ast_visitor_test_virtual_input.cc";
@@ -61,8 +108,9 @@
TEST(AstVisitorTest, Noop) {
IR ir = ImportCode({"// nothing interesting there."}, {});
EXPECT_THAT(ir.functions, IsEmpty());
- ASSERT_THAT(ir.used_headers, SizeIs(1));
- EXPECT_EQ(ir.used_headers[0].IncludePath(), "test/testing_header_0.h");
+ EXPECT_THAT(ir.used_headers,
+ ElementsAre(Property(&HeaderName::IncludePath,
+ "test/testing_header_0.h")));
}
TEST(AstVisitorTest, IREmptyOnInvalidInput) {
@@ -72,61 +120,41 @@
TEST(AstVisitorTest, FuncWithVoidReturnType) {
IR ir = ImportCode({"void Foo();"}, {});
- ASSERT_THAT(ir.functions, SizeIs(1));
- Func func = ir.functions[0];
- EXPECT_EQ(func.identifier.Ident(), "Foo");
- EXPECT_EQ(func.mangled_name, "_Z3Foov");
- EXPECT_TRUE(func.return_type.IsVoid());
- EXPECT_THAT(func.params, IsEmpty());
+ EXPECT_THAT(ir.functions,
+ ElementsAre(AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
+ ReturnType(IsVoid()), ParamsAre())));
}
TEST(AstVisitorTest, TwoFuncs) {
IR ir = ImportCode({"void Foo(); void Bar();"}, {});
- ASSERT_THAT(ir.functions, SizeIs(2));
-
- Func foo = ir.functions[0];
- EXPECT_EQ(foo.identifier.Ident(), "Foo");
- EXPECT_EQ(foo.mangled_name, "_Z3Foov");
- EXPECT_TRUE(foo.return_type.IsVoid());
- EXPECT_THAT(foo.params, IsEmpty());
-
- Func bar = ir.functions[1];
- EXPECT_EQ(bar.identifier.Ident(), "Bar");
- EXPECT_EQ(bar.mangled_name, "_Z3Barv");
- EXPECT_TRUE(bar.return_type.IsVoid());
- EXPECT_THAT(bar.params, IsEmpty());
+ EXPECT_THAT(ir.functions,
+ ElementsAre(AllOf(IdentifierIs("Foo"), MangledNameIs("_Z3Foov"),
+ ReturnType(IsVoid()), ParamsAre()),
+ AllOf(IdentifierIs("Bar"), MangledNameIs("_Z3Barv"),
+ ReturnType(IsVoid()), ParamsAre())));
}
TEST(AstVisitorTest, TwoFuncsFromTwoHeaders) {
IR ir = ImportCode({"void Foo();", "void Bar();"}, {});
- ASSERT_THAT(ir.functions, SizeIs(2));
- Func foo = ir.functions[0];
- EXPECT_EQ(foo.identifier.Ident(), "Foo");
- Func bar = ir.functions[1];
- EXPECT_EQ(bar.identifier.Ident(), "Bar");
+ EXPECT_THAT(ir.functions,
+ ElementsAre(IdentifierIs("Foo"), IdentifierIs("Bar")));
}
TEST(AstVisitorTest, NonInlineFunc) {
IR ir = ImportCode({"void Foo() {}"}, {});
- ASSERT_THAT(ir.functions, SizeIs(1));
- Func func = ir.functions[0];
- EXPECT_EQ(func.identifier.Ident(), "Foo");
- EXPECT_FALSE(func.is_inline);
+ EXPECT_THAT(ir.functions,
+ ElementsAre(AllOf(IdentifierIs("Foo"), Not(IsInline()))));
}
TEST(AstVisitorTest, InlineFunc) {
IR ir = ImportCode({"inline void Foo() {}"}, {});
- ASSERT_THAT(ir.functions, SizeIs(1));
- Func func = ir.functions[0];
- EXPECT_EQ(func.identifier.Ident(), "Foo");
- EXPECT_TRUE(func.is_inline);
+ EXPECT_THAT(ir.functions,
+ ElementsAre(AllOf(IdentifierIs("Foo"), IsInline())));
}
TEST(AstVisitorTest, FuncJustOnce) {
IR ir = ImportCode({"void Foo(); void Foo();"}, {});
- ASSERT_THAT(ir.functions, SizeIs(1));
- Func func = ir.functions[0];
- EXPECT_EQ(func.identifier.Ident(), "Foo");
+ EXPECT_THAT(ir.functions, ElementsAre(AllOf(IdentifierIs("Foo"))));
}
TEST(AstVisitorTest, FuncParams) {
@@ -172,7 +200,7 @@
TEST(AstVisitorTest, Struct) {
IR ir = ImportCode(
{"struct SomeStruct { int first_field; int second_field; };"}, {});
- EXPECT_THAT(ir.functions, SizeIs(0));
+ EXPECT_THAT(ir.functions, IsEmpty());
EXPECT_THAT(ir.records, SizeIs(1));
Record some_struct = ir.records[0];
@@ -208,31 +236,22 @@
};
)"},
{});
- EXPECT_THAT(ir.functions, SizeIs(0));
- ASSERT_THAT(ir.records, SizeIs(2));
- Record some_struct = ir.records[0];
- EXPECT_EQ(some_struct.identifier.Ident(), "SomeStruct");
- ASSERT_THAT(some_struct.fields, SizeIs(4));
- Field field0 = some_struct.fields[0];
- EXPECT_EQ(field0.identifier.Ident(), "default_access_int");
- EXPECT_EQ(field0.access, kPublic);
- Field field1 = some_struct.fields[1];
- EXPECT_EQ(field1.identifier.Ident(), "public_int");
- EXPECT_EQ(field1.access, kPublic);
- Field field2 = some_struct.fields[2];
- EXPECT_EQ(field2.identifier.Ident(), "protected_int");
- EXPECT_EQ(field2.access, kProtected);
- Field field3 = some_struct.fields[3];
- EXPECT_EQ(field3.identifier.Ident(), "private_int");
- EXPECT_EQ(field3.access, kPrivate);
+ EXPECT_THAT(ir.functions, IsEmpty());
- Record some_class = ir.records[1];
- EXPECT_EQ(some_class.identifier.Ident(), "SomeClass");
- ASSERT_THAT(some_class.fields, SizeIs(1));
- field0 = some_class.fields[0];
- EXPECT_EQ(field0.identifier.Ident(), "default_access_int");
- EXPECT_EQ(field0.access, kPrivate);
+ EXPECT_THAT(
+ ir.records,
+ ElementsAre(
+ AllOf(
+ IdentifierIs("SomeStruct"),
+ FieldsAre(
+ AllOf(IdentifierIs("default_access_int"), AccessIs(kPublic)),
+ AllOf(IdentifierIs("public_int"), AccessIs(kPublic)),
+ AllOf(IdentifierIs("protected_int"), AccessIs(kProtected)),
+ AllOf(IdentifierIs("private_int"), AccessIs(kPrivate)))),
+ AllOf(IdentifierIs("SomeClass"),
+ FieldsAre(AllOf(IdentifierIs("default_access_int"),
+ AccessIs(kPrivate))))));
}
TEST(AstVisitorTest, IntegerTypes) {