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