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 #include <algorithm>
6 #include <unittest/unittest.h>
7
8 #include <fidl/flat_ast.h>
9 #include <fidl/lexer.h>
10 #include <fidl/parser.h>
11 #include <fidl/source_file.h>
12
13 #include "test_library.h"
14
15 namespace {
16
17 class MaxBytesMultiPassLibrary : public TestLibrary {
18 public:
MaxBytesMultiPassLibrary()19 MaxBytesMultiPassLibrary()
20 : TestLibrary(multipass_main_file) {
21 source_files_.push_back(
22 MakeSourceFile("max_bytes_multipass_main.fidl", multipass_main_file));
23 source_files_.push_back(
24 MakeSourceFile("max_bytes_multipass_extern_defs.fidl", multipass_extern_defs_file));
25 }
26
Compile()27 bool Compile() {
28 for (auto& file : source_files_) {
29 fidl::Lexer lexer(file, &error_reporter_);
30 fidl::Parser parser(&lexer, &error_reporter_);
31
32 auto ast = parser.Parse();
33 if (!parser.Ok() || !library_->ConsumeFile(std::move(ast))) {
34 return false;
35 }
36 }
37
38 return library_->Compile();
39 }
40
GetLibrary() const41 fidl::flat::Library& GetLibrary() const {
42 return *library_;
43 }
44
45 private:
46 static constexpr auto multipass_main_file = R"FIDL(
47 library fidl.test.maxbytesmultipass;
48
49 struct SimpleStruct {
50 uint32 a;
51 };
52
53 struct OptionalStruct {
54 SimpleStruct? a;
55 SimpleStruct? b;
56 };
57
58 struct HandleStruct {
59 uint32 a;
60 handle<vmo> b;
61 };
62
63 struct ArrayOfSimpleStructs {
64 array<SimpleStruct>:42 arr;
65 };
66
67 struct ArrayOfOptionalStructs {
68 array<OptionalStruct>:42 arr;
69 };
70
71 struct ArrayOfHandleStructs {
72 array<HandleStruct>:42 arr;
73 };
74
75 union OptionalAndHandleUnion {
76 OptionalStruct opt;
77 HandleStruct hnd;
78 };
79
80 struct ArrayOfOptionalAndHandleUnions {
81 array<OptionalAndHandleUnion>:42 arr;
82 };
83
84 struct ExternalArrayStruct {
85 array<ExternalSimpleStruct>:EXTERNAL_SIZE_DEF a;
86 };
87
88 struct ExternalStringSizeStruct {
89 string:EXTERNAL_SIZE_DEF a;
90 };
91
92 struct ExternalVectorSizeStruct {
93 vector<handle>:EXTERNAL_SIZE_DEF a;
94 };
95
96 )FIDL";
97
98 static constexpr auto multipass_extern_defs_file = R"FIDL(
99 library fidl.test.maxbytesmultipass;
100
101 const uint32 EXTERNAL_SIZE_DEF = ANOTHER_INDIRECTION;
102 const uint32 ANOTHER_INDIRECTION = 32;
103
104 struct ExternalSimpleStruct {
105 uint32 a;
106 };
107
108 )FIDL";
109 std::vector<fidl::SourceFile> source_files_;
110 };
111
simple_struct_array(void)112 static bool simple_struct_array(void) {
113 BEGIN_TEST;
114
115 MaxBytesMultiPassLibrary test_library;
116 EXPECT_TRUE(test_library.Compile());
117
118 auto smp_struct = test_library.LookupStruct("SimpleStruct");
119 EXPECT_NONNULL(smp_struct);
120 EXPECT_EQ(smp_struct->typeshape.Size(), 4);
121 EXPECT_EQ(smp_struct->typeshape.MaxOutOfLine(), 0);
122 EXPECT_EQ(smp_struct->typeshape.MaxHandles(), 0);
123
124 auto arr_of_smps = test_library.LookupStruct("ArrayOfSimpleStructs");
125 EXPECT_NONNULL(arr_of_smps);
126 EXPECT_EQ(arr_of_smps->typeshape.Size(), smp_struct->typeshape.Size() * 42);
127 EXPECT_EQ(arr_of_smps->typeshape.MaxOutOfLine(), smp_struct->typeshape.MaxOutOfLine() * 42);
128 EXPECT_EQ(arr_of_smps->typeshape.MaxHandles(), smp_struct->typeshape.MaxHandles() * 42);
129
130 END_TEST;
131 }
132
optional_struct_array(void)133 static bool optional_struct_array(void) {
134 BEGIN_TEST;
135
136 MaxBytesMultiPassLibrary test_library;
137 EXPECT_TRUE(test_library.Compile());
138
139 auto opt_struct = test_library.LookupStruct("OptionalStruct");
140 EXPECT_NONNULL(opt_struct);
141 EXPECT_EQ(opt_struct->typeshape.Size(), 16);
142 EXPECT_EQ(opt_struct->typeshape.MaxOutOfLine(), 16);
143 EXPECT_EQ(opt_struct->typeshape.MaxHandles(), 0);
144
145 auto arr_of_opt_struct = test_library.LookupStruct("ArrayOfOptionalStructs");
146 EXPECT_NONNULL(arr_of_opt_struct);
147 EXPECT_EQ(arr_of_opt_struct->typeshape.Size(), opt_struct->typeshape.Size() * 42);
148 EXPECT_EQ(arr_of_opt_struct->typeshape.MaxOutOfLine(),
149 opt_struct->typeshape.MaxOutOfLine() * 42);
150 EXPECT_EQ(arr_of_opt_struct->typeshape.MaxHandles(), opt_struct->typeshape.MaxHandles() * 42);
151
152 END_TEST;
153 }
154
handle_struct_array(void)155 static bool handle_struct_array(void) {
156 BEGIN_TEST;
157
158 MaxBytesMultiPassLibrary test_library;
159 EXPECT_TRUE(test_library.Compile());
160
161 auto hnd_struct = test_library.LookupStruct("HandleStruct");
162 EXPECT_NONNULL(hnd_struct);
163 EXPECT_EQ(hnd_struct->typeshape.Size(), 8);
164 EXPECT_EQ(hnd_struct->typeshape.MaxOutOfLine(), 0);
165 EXPECT_EQ(hnd_struct->typeshape.MaxHandles(), 1);
166
167 auto arr_of_hnd_struct = test_library.LookupStruct("ArrayOfHandleStructs");
168 EXPECT_NONNULL(arr_of_hnd_struct);
169 EXPECT_EQ(arr_of_hnd_struct->typeshape.Size(), hnd_struct->typeshape.Size() * 42);
170 EXPECT_EQ(arr_of_hnd_struct->typeshape.MaxOutOfLine(),
171 hnd_struct->typeshape.MaxOutOfLine() * 42);
172 EXPECT_EQ(arr_of_hnd_struct->typeshape.MaxHandles(), hnd_struct->typeshape.MaxHandles() * 42);
173
174 END_TEST;
175 }
optional_handle_union_array(void)176 static bool optional_handle_union_array(void) {
177 BEGIN_TEST;
178
179 MaxBytesMultiPassLibrary test_library;
180 EXPECT_TRUE(test_library.Compile());
181
182 auto opt_struct = test_library.LookupStruct("OptionalStruct");
183 EXPECT_NONNULL(opt_struct);
184
185 auto hnd_struct = test_library.LookupStruct("HandleStruct");
186 EXPECT_NONNULL(hnd_struct);
187
188 auto opt_hnd_union = test_library.LookupUnion("OptionalAndHandleUnion");
189 EXPECT_NONNULL(opt_hnd_union);
190 EXPECT_EQ(opt_hnd_union->typeshape.Size(), 24);
191 EXPECT_EQ(opt_hnd_union->typeshape.MaxOutOfLine(),
192 std::max(opt_struct->typeshape.MaxOutOfLine(), hnd_struct->typeshape.MaxOutOfLine()));
193 EXPECT_EQ(opt_hnd_union->typeshape.MaxHandles(),
194 std::max(opt_struct->typeshape.MaxHandles(), hnd_struct->typeshape.MaxHandles()));
195
196 auto arr_of_unions_struct = test_library.LookupStruct("ArrayOfOptionalAndHandleUnions");
197 EXPECT_NONNULL(arr_of_unions_struct);
198 EXPECT_EQ(arr_of_unions_struct->typeshape.Size(), opt_hnd_union->typeshape.Size() * 42);
199 EXPECT_EQ(arr_of_unions_struct->typeshape.MaxOutOfLine(),
200 opt_hnd_union->typeshape.MaxOutOfLine() * 42);
201 EXPECT_EQ(arr_of_unions_struct->typeshape.MaxHandles(),
202 opt_hnd_union->typeshape.MaxHandles() * 42);
203
204 END_TEST;
205 }
206
external_definitions(void)207 static bool external_definitions(void) {
208 BEGIN_TEST;
209
210 MaxBytesMultiPassLibrary test_library;
211 EXPECT_TRUE(test_library.Compile());
212
213 auto ext_struct = test_library.LookupStruct("ExternalSimpleStruct");
214 EXPECT_NONNULL(ext_struct);
215 EXPECT_EQ(ext_struct->typeshape.Size(), 4);
216 EXPECT_EQ(ext_struct->typeshape.MaxOutOfLine(), 0);
217 EXPECT_EQ(ext_struct->typeshape.MaxHandles(), 0);
218
219 auto ext_arr_struct = test_library.LookupStruct("ExternalArrayStruct");
220 EXPECT_NONNULL(ext_arr_struct);
221 EXPECT_EQ(ext_arr_struct->typeshape.Size(), ext_struct->typeshape.Size() * 32);
222
223 auto ext_str_struct = test_library.LookupStruct("ExternalStringSizeStruct");
224 EXPECT_NONNULL(ext_str_struct);
225 EXPECT_EQ(ext_str_struct->typeshape.MaxOutOfLine(), 32);
226
227 auto ext_vec_struct = test_library.LookupStruct("ExternalVectorSizeStruct");
228 EXPECT_NONNULL(ext_vec_struct);
229 EXPECT_EQ(ext_vec_struct->typeshape.MaxOutOfLine(), 32 * 4);
230 EXPECT_EQ(ext_vec_struct->typeshape.MaxHandles(), 32);
231
232 END_TEST;
233 }
234
235 } // namespace
236
237 BEGIN_TEST_CASE(max_bytes_multipass_tests);
238 RUN_TEST(simple_struct_array);
239 RUN_TEST(optional_struct_array);
240 RUN_TEST(handle_struct_array);
241 RUN_TEST(optional_handle_union_array);
242 RUN_TEST(external_definitions);
243 END_TEST_CASE(max_bytes_multipass_tests);
244