1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
6 #define ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
7
8 #include <fidl/flat_ast.h>
9 #include <fidl/json_generator.h>
10 #include <fidl/lexer.h>
11 #include <fidl/parser.h>
12 #include <fidl/source_file.h>
13
MakeSourceFile(const std::string & filename,const std::string & raw_source_code)14 static fidl::SourceFile MakeSourceFile(const std::string& filename, const std::string& raw_source_code) {
15 std::string source_code(raw_source_code);
16 // NUL terminate the string.
17 source_code.resize(source_code.size() + 1);
18 return fidl::SourceFile(filename, source_code);
19 }
20
21 class TestLibrary {
22 public:
TestLibrary(const std::string & raw_source_code)23 TestLibrary(const std::string& raw_source_code)
24 : TestLibrary("example.fidl", raw_source_code) {}
25
TestLibrary(const std::string & filename,const std::string & raw_source_code)26 TestLibrary(const std::string& filename, const std::string& raw_source_code)
27 : source_file_(MakeSourceFile(filename, raw_source_code)),
28 lexer_(source_file_, &error_reporter_),
29 parser_(&lexer_, &error_reporter_),
30 library_(std::make_unique<fidl::flat::Library>(
31 &all_libraries_, &error_reporter_, &typespace_)) {}
32
AddDependentLibrary(TestLibrary & dependent_library)33 bool AddDependentLibrary(TestLibrary& dependent_library) {
34 // For testing, we have conveniences to construct compiled test
35 // libraries, which we usurp here to move it into the current library
36 // under test. This would be made clearer with a helper object which
37 // owned all libraries under test.
38 if (!all_libraries_.Insert(std::unique_ptr<fidl::flat::Library>(dependent_library.library_.get()))) {
39 return false;
40 }
41 dependent_library.library_.release();
42 return true;
43 }
44
AddAttributeSchema(const std::string & name,fidl::flat::AttributeSchema schema)45 void AddAttributeSchema(const std::string& name, fidl::flat::AttributeSchema schema) {
46 all_libraries_.AddAttributeSchema(name, std::move(schema));
47 }
48
Parse(std::unique_ptr<fidl::raw::File> & ast_ptr)49 bool Parse(std::unique_ptr<fidl::raw::File>& ast_ptr) {
50 ast_ptr.reset(parser_.Parse().release());
51 return parser_.Ok();
52 }
53
Compile()54 bool Compile() {
55 auto ast = parser_.Parse();
56 return parser_.Ok() &&
57 library_->ConsumeFile(std::move(ast)) &&
58 library_->Compile();
59 }
60
GenerateJSON()61 std::string GenerateJSON() {
62 auto json_generator = fidl::JSONGenerator(library_.get());
63 auto out = json_generator.Produce();
64 return out.str();
65 }
66
AddSourceFile(const std::string & filename,const std::string & raw_source_code)67 bool AddSourceFile(const std::string& filename, const std::string& raw_source_code) {
68 auto source_file = MakeSourceFile(filename, raw_source_code);
69 fidl::Lexer lexer(source_file, &error_reporter_);
70 fidl::Parser parser(&lexer, &error_reporter_);
71 auto ast = parser.Parse();
72 return parser.Ok() &&
73 library_->ConsumeFile(std::move(ast)) &&
74 library_->Compile();
75 }
76
LookupStruct(const std::string & name)77 const fidl::flat::Struct* LookupStruct(const std::string& name) {
78 for (const auto& struct_decl : library_->struct_declarations_) {
79 if (struct_decl->GetName() == name) {
80 return struct_decl.get();
81 }
82 }
83 return nullptr;
84 }
85
LookupTable(const std::string & name)86 const fidl::flat::Table* LookupTable(const std::string& name) {
87 for (const auto& table_decl : library_->table_declarations_) {
88 if (table_decl->GetName() == name) {
89 return table_decl.get();
90 }
91 }
92 return nullptr;
93 }
94
LookupUnion(const std::string & name)95 const fidl::flat::Union* LookupUnion(const std::string& name) {
96 for (const auto& union_decl : library_->union_declarations_) {
97 if (union_decl->GetName() == name) {
98 return union_decl.get();
99 }
100 }
101 return nullptr;
102 }
103
LookupInterface(const std::string & name)104 const fidl::flat::Interface* LookupInterface(const std::string& name) {
105 for (const auto& interface_decl : library_->interface_declarations_) {
106 if (interface_decl->GetName() == name) {
107 return interface_decl.get();
108 }
109 }
110 return nullptr;
111 }
112
library()113 const fidl::flat::Library* library() const {
114 return library_.get();
115 }
116
source_file()117 fidl::SourceFile source_file() {
118 return source_file_;
119 }
120
errors()121 const std::vector<std::string>& errors() const {
122 return error_reporter_.errors();
123 }
124
warnings()125 const std::vector<std::string>& warnings() const {
126 return error_reporter_.warnings();
127 }
128
129 protected:
130 fidl::SourceFile source_file_;
131 fidl::ErrorReporter error_reporter_;
132 fidl::flat::Typespace typespace_ = fidl::flat::Typespace::RootTypes();
133 fidl::Lexer lexer_;
134 fidl::Parser parser_;
135 fidl::flat::Libraries all_libraries_;
136 std::unique_ptr<fidl::flat::Library> library_;
137 };
138
139 #endif // ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
140