clang_generator: Refactor frontend test utilities

This makes it easier to write tests with expected compilation/parsing failures.

PiperOrigin-RevId: 485331205
Change-Id: Ia545934849d38bded9320537c71e970fb4730cb6
This commit is contained in:
Christian Blichmann 2022-11-01 08:59:48 -07:00 committed by Copybara-Service
parent c3889ce379
commit 7e0f72e445
3 changed files with 65 additions and 67 deletions

View File

@ -46,13 +46,14 @@ class EmitterTest : public FrontendActionTest {};
TEST_F(EmitterTest, BasicFunctionality) {
GeneratorOptions options;
options.out_file = "input.h";
options.set_function_names<std::initializer_list<std::string>>(
{"ExposedFunction"});
EmitterForTesting emitter;
RunFrontendAction(R"(extern "C" void ExposedFunction() {})",
std::make_unique<GeneratorAction>(emitter, options));
ASSERT_THAT(
RunFrontendAction(R"(extern "C" void ExposedFunction() {})",
std::make_unique<GeneratorAction>(emitter, options)),
IsOk());
EXPECT_THAT(emitter.functions_, SizeIs(1));
@ -62,25 +63,25 @@ TEST_F(EmitterTest, BasicFunctionality) {
TEST_F(EmitterTest, RelatedTypes) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
namespace std {
using size_t = unsigned long;
} // namespace std
using std::size_t;
typedef enum { kRed, kGreen, kBlue } Color;
struct Channel {
Color color;
size_t width;
size_t height;
};
struct ByValue { int value; };
extern "C" void Colorize(Channel* chan, ByValue v) {}
ASSERT_THAT(
RunFrontendAction(
R"(namespace std {
using size_t = unsigned long;
} // namespace std
using std::size_t;
typedef enum { kRed, kGreen, kBlue } Color;
struct Channel {
Color color;
size_t width;
size_t height;
};
struct ByValue { int value; };
extern "C" void Colorize(Channel* chan, ByValue v);
typedef struct { int member; } MyStruct;
extern "C" void Structize(MyStruct* s);
)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
typedef struct { int member; } MyStruct;
extern "C" void Structize(MyStruct* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
// Types from "std" should be skipped
EXPECT_THAT(emitter.rendered_types_["std"], IsEmpty());
@ -97,16 +98,16 @@ TEST_F(EmitterTest, RelatedTypes) {
TEST_F(EmitterTest, NestedStruct) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A {
struct B { int number; };
B b;
int data;
};
extern "C" void Structize(A* s);
)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
ASSERT_THAT(
RunFrontendAction(
R"(struct A {
struct B { int number; };
B b;
int data;
};
extern "C" void Structize(A* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.rendered_types_[""]),
ElementsAre("struct A {"
@ -117,15 +118,15 @@ TEST_F(EmitterTest, NestedStruct) {
TEST_F(EmitterTest, NestedAnonymousStruct) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A {
struct { int number; } b;
int data;
};
extern "C" void Structize(A* s);
)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
ASSERT_THAT(
RunFrontendAction(
R"(struct A {
struct { int number; } b;
int data;
};
extern "C" void Structize(A* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.rendered_types_[""]),
ElementsAre("struct A {"
@ -135,16 +136,16 @@ TEST_F(EmitterTest, NestedAnonymousStruct) {
TEST_F(EmitterTest, ParentNotCollected) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A {
struct B { int number; };
B b;
int data;
};
extern "C" void Structize(A::B* s);
)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
ASSERT_THAT(
RunFrontendAction(
R"(struct A {
struct B { int number; };
B b;
int data;
};
extern "C" void Structize(A::B* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.rendered_types_[""]),
ElementsAre("struct A {"
@ -155,12 +156,12 @@ TEST_F(EmitterTest, ParentNotCollected) {
TEST_F(EmitterTest, RemoveQualifiers) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A { int data; };
extern "C" void Structize(const A* in, A* out);
)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
ASSERT_THAT(
RunFrontendAction(
R"(struct A { int data; };
extern "C" void Structize(const A* in, A* out);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.rendered_types_[""]),
ElementsAre("struct A { int data; }"));

View File

@ -56,21 +56,20 @@ class FrontendActionTest : public ::testing::Test {
absl::string_view input_file);
// Runs the specified frontend action on in-memory source code.
void RunFrontendAction(absl::string_view code,
std::unique_ptr<clang::FrontendAction> action) {
absl::Status RunFrontendAction(
absl::string_view code, std::unique_ptr<clang::FrontendAction> action) {
std::vector<std::string> command_line =
GetCommandLineFlagsForTesting(input_file_);
AddCode(input_file_, code);
ASSERT_THAT(
internal::RunClangTool(command_line, file_contents_, std::move(action)),
IsOk());
return internal::RunClangTool(command_line, file_contents_,
std::move(action));
}
// Runs the specified frontend action. Provided for compatibility with LLVM <
// 10. Takes ownership.
void RunFrontendAction(absl::string_view code,
clang::FrontendAction* action) {
RunFrontendAction(code, absl::WrapUnique(action));
absl::Status RunFrontendAction(absl::string_view code,
clang::FrontendAction* action) {
return RunFrontendAction(code, absl::WrapUnique(action));
}
private:

View File

@ -19,8 +19,6 @@
#include <string>
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
@ -51,7 +49,7 @@ struct GeneratorOptions {
std::string namespace_name; // Namespace to wrap the SAPI in
// Output path of the generated header. Used to build the header include
// guard.
std::string out_file;
std::string out_file = "out_file.cc";
std::string embed_dir; // Directory with embedded includes
std::string embed_name; // Identifier of the embed object
};