1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "sandboxed_api/tools/clang_generator/emitter.h"
16
17 #include <initializer_list>
18 #include <memory>
19 #include <string>
20 #include <vector>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/status/statusor.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/string_view.h"
27 #include "sandboxed_api/tools/clang_generator/emitter_base.h"
28 #include "sandboxed_api/tools/clang_generator/frontend_action_test_util.h"
29 #include "sandboxed_api/tools/clang_generator/generator.h"
30 #include "sandboxed_api/util/status_matchers.h"
31
32 namespace sapi {
33 namespace {
34
35 using ::testing::ElementsAre;
36 using ::testing::IsEmpty;
37 using ::testing::MatchesRegex;
38 using ::testing::SizeIs;
39 using ::testing::StrEq;
40 using ::testing::StrNe;
41
42 class EmitterForTesting : public Emitter {
43 public:
SpellingsForNS(const std::string & ns_name)44 std::vector<std::string> SpellingsForNS(const std::string& ns_name) {
45 std::vector<std::string> result;
46 for (const RenderedType* rt : rendered_types_ordered_) {
47 if (rt->ns_name == ns_name) {
48 result.push_back(rt->spelling);
49 }
50 }
51 return result;
52 }
53
GetRenderedFunctions()54 const std::vector<std::string>& GetRenderedFunctions() {
55 return rendered_functions_ordered_;
56 }
57 };
58
59 class EmitterTest : public FrontendActionTest {};
60
TEST_F(EmitterTest,BasicFunctionality)61 TEST_F(EmitterTest, BasicFunctionality) {
62 GeneratorOptions options;
63 options.set_function_names<std::initializer_list<std::string>>(
64 {"ExposedFunction"});
65
66 EmitterForTesting emitter;
67 ASSERT_THAT(
68 RunFrontendAction(R"(extern "C" void ExposedFunction() {})",
69 std::make_unique<GeneratorAction>(emitter, options)),
70 IsOk());
71 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
72
73 absl::StatusOr<std::string> header = emitter.EmitHeader(options);
74 EXPECT_THAT(header, IsOk());
75 }
76
TEST_F(EmitterTest,RelatedTypes)77 TEST_F(EmitterTest, RelatedTypes) {
78 EmitterForTesting emitter;
79 ASSERT_THAT(
80 RunFrontendAction(
81 R"(namespace std {
82 using size_t = unsigned long;
83 } // namespace std
84 using std::size_t;
85 typedef enum { kRed, kGreen, kBlue } Color;
86 struct Channel {
87 Color color;
88 size_t width;
89 size_t height;
90 };
91 extern "C" void Colorize(Channel* chan);
92
93 typedef struct { int member; } MyStruct;
94 extern "C" void Structize(MyStruct* s);)",
95 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
96 IsOk());
97 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(2));
98
99 // Types from "std" should be skipped
100 EXPECT_THAT(emitter.SpellingsForNS("std"), IsEmpty());
101
102 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
103 ElementsAre("typedef enum { kRed, kGreen, kBlue } Color",
104 "struct Channel {"
105 " Color color;"
106 " size_t width;"
107 " size_t height; }",
108 "typedef struct { int member; } MyStruct"));
109 }
110
TEST_F(EmitterTest,CollectFunctionPointer)111 TEST_F(EmitterTest, CollectFunctionPointer) {
112 EmitterForTesting emitter;
113 EXPECT_THAT(
114 RunFrontendAction(
115 R"(typedef void (callback_t)(void*);
116 struct HandlerData {
117 int member;
118 callback_t* cb;
119 };
120 extern "C" int Structize(HandlerData*);)",
121 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
122 IsOk());
123 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
124
125 EXPECT_THAT(
126 UglifyAll(emitter.SpellingsForNS("")),
127 ElementsAre("typedef void (callback_t)(void *)",
128 "struct HandlerData { int member; callback_t *cb; }"));
129 }
130
TEST_F(EmitterTest,TypedefNames)131 TEST_F(EmitterTest, TypedefNames) {
132 EmitterForTesting emitter;
133 ASSERT_THAT(
134 RunFrontendAction(
135 R"(typedef enum { kNone, kSome } E;
136 struct A { E member; };
137 typedef struct { int member; } B;
138 typedef struct tagC { int member; } C;
139 extern "C" void Colorize(A*, B*, C*);)",
140 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
141 IsOk());
142
143 EXPECT_THAT(
144 UglifyAll(emitter.SpellingsForNS("")),
145 ElementsAre("typedef enum { kNone, kSome } E", "struct A { E member; }",
146 "typedef struct { int member; } B",
147 "struct tagC { int member; }", "typedef struct tagC C"));
148 }
149
TEST_F(EmitterTest,TypedefAnonymousWithFieldStructure)150 TEST_F(EmitterTest, TypedefAnonymousWithFieldStructure) {
151 EmitterForTesting emitter;
152 ASSERT_THAT(
153 RunFrontendAction(
154 R"(struct A { int number; };
155 typedef struct { A member; } B;
156 extern "C" void Foo(B*);)",
157 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
158 IsOk());
159
160 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
161 ElementsAre("struct A { int number; }",
162 "typedef struct { A member; } B"));
163 }
164
TEST_F(EmitterTest,NamedEnumWithoutTypedef)165 TEST_F(EmitterTest, NamedEnumWithoutTypedef) {
166 EmitterForTesting emitter;
167 ASSERT_THAT(
168 RunFrontendAction(
169 R"(enum Color { kRed, kGreen, kBlue };
170 typedef struct { enum Color member; } B;
171 extern "C" void Foo(B*);)",
172 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
173 IsOk());
174
175 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
176 ElementsAre("enum Color { kRed, kGreen, kBlue }",
177 "typedef struct { enum Color member; } B"));
178 }
179
TEST_F(EmitterTest,NestedStruct)180 TEST_F(EmitterTest, NestedStruct) {
181 EmitterForTesting emitter;
182 ASSERT_THAT(
183 RunFrontendAction(
184 R"(struct A {
185 struct B { int number; };
186 B b;
187 int data;
188 };
189 extern "C" void Structize(A* s);)",
190 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
191 IsOk());
192
193 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
194 ElementsAre("struct A {"
195 " struct B { int number; };"
196 " B b;"
197 " int data; }"));
198 }
199
TEST_F(EmitterTest,NestedAnonymousStruct)200 TEST_F(EmitterTest, NestedAnonymousStruct) {
201 EmitterForTesting emitter;
202 ASSERT_THAT(
203 RunFrontendAction(
204 R"(struct A {
205 struct { int number; } b;
206 int data;
207 };
208 extern "C" void Structize(A* s);)",
209 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
210 IsOk());
211
212 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
213 ElementsAre("struct A {"
214 " struct { int number; } b;"
215 " int data; }"));
216 }
217
TEST_F(EmitterTest,ParentNotCollected)218 TEST_F(EmitterTest, ParentNotCollected) {
219 EmitterForTesting emitter;
220 ASSERT_THAT(
221 RunFrontendAction(
222 R"(struct A {
223 struct B { int number; };
224 B b;
225 int data;
226 };
227 extern "C" void Structize(A::B* s);)",
228 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
229 IsOk());
230
231 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
232 ElementsAre("struct A {"
233 " struct B { int number; };"
234 " B b;"
235 " int data; }"));
236 }
237
TEST_F(EmitterTest,StructForwardDecl)238 TEST_F(EmitterTest, StructForwardDecl) {
239 EmitterForTesting emitter;
240 ASSERT_THAT(
241 RunFrontendAction(
242 R"(struct A;
243 extern "C" void UsingForwardDeclaredStruct(A* s);)",
244 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
245 IsOk());
246
247 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), ElementsAre("struct A"));
248 }
249
TEST_F(EmitterTest,AggregateStructWithDefaultedMembers)250 TEST_F(EmitterTest, AggregateStructWithDefaultedMembers) {
251 EmitterForTesting emitter;
252 ASSERT_THAT(
253 RunFrontendAction(
254 R"(struct A {
255 int a = 0;
256 int b = 42;
257 };
258 extern "C" void AggregateStruct(A* s);)",
259 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
260 IsOk());
261
262 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
263 ElementsAre("struct A {"
264 " int a = 0;"
265 " int b = 42; }"));
266 }
267
TEST_F(EmitterTest,AggregateStructWithMethods)268 TEST_F(EmitterTest, AggregateStructWithMethods) {
269 EmitterForTesting emitter;
270 ASSERT_THAT(
271 RunFrontendAction(
272 R"(struct A {
273 int a = 0;
274 int b = 42;
275 int my_mem_fn();
276 };
277 extern "C" void AggregateStruct(A* s);)",
278 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
279 IsOk());
280
281 // Expect a forward decl in this case
282 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), ElementsAre("struct A"));
283 }
284
TEST_F(EmitterTest,RemoveQualifiers)285 TEST_F(EmitterTest, RemoveQualifiers) {
286 EmitterForTesting emitter;
287 ASSERT_THAT(
288 RunFrontendAction(
289 R"(struct A { int data; };
290 extern "C" void Structize(const A* in, A* out);)",
291 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
292 IsOk());
293
294 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
295 ElementsAre("struct A { int data; }"));
296 }
297
TEST_F(EmitterTest,StructByValueSkipsFunction)298 TEST_F(EmitterTest, StructByValueSkipsFunction) {
299 EmitterForTesting emitter;
300 EXPECT_THAT(
301 RunFrontendAction(
302 R"(struct A { int data; };
303 extern "C" int Structize(A a);)",
304 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
305 IsOk());
306 EXPECT_THAT(emitter.GetRenderedFunctions(), IsEmpty());
307 }
308
TEST_F(EmitterTest,ReturnStructByValueSkipsFunction)309 TEST_F(EmitterTest, ReturnStructByValueSkipsFunction) {
310 EmitterForTesting emitter;
311 EXPECT_THAT(
312 RunFrontendAction(
313 R"(struct A { int data; };
314 extern "C" A Structize();)",
315 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
316 IsOk());
317 EXPECT_THAT(emitter.GetRenderedFunctions(), IsEmpty());
318 }
319
TEST_F(EmitterTest,TypedefStructByValueSkipsFunction)320 TEST_F(EmitterTest, TypedefStructByValueSkipsFunction) {
321 EmitterForTesting emitter;
322 EXPECT_THAT(
323 RunFrontendAction(
324 R"(typedef struct { int data; } A;
325 extern "C" int Structize(A a);)",
326 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
327 IsOk());
328 EXPECT_THAT(emitter.GetRenderedFunctions(), IsEmpty());
329 }
330
TEST_F(EmitterTest,CollectTypedefPointerType)331 TEST_F(EmitterTest, CollectTypedefPointerType) {
332 EmitterForTesting emitter;
333 EXPECT_THAT(
334 RunFrontendAction(
335 R"(typedef struct _KernelProfileRecord {
336 int member;
337 }* KernelProfileRecord;
338 extern "C" const KernelProfileRecord*
339 GetOpenCLKernelProfileRecords(const int, long long int*);)",
340 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
341 IsOk());
342 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
343
344 EXPECT_THAT(
345 UglifyAll(emitter.SpellingsForNS("")),
346 ElementsAre("struct _KernelProfileRecord { int member; }",
347 "typedef struct _KernelProfileRecord *KernelProfileRecord"));
348 }
349
TEST_F(EmitterTest,TypedefTypeDependencies)350 TEST_F(EmitterTest, TypedefTypeDependencies) {
351 EmitterForTesting emitter;
352 EXPECT_THAT(
353 RunFrontendAction(
354 R"(typedef bool some_other_unused;
355 using size_t = long long int;
356 typedef struct _Image Image;
357 typedef size_t (*StreamHandler)(const Image*, const void*,
358 const size_t);
359 enum unrelated_unused { NONE, SOME };
360 struct _Image {
361 StreamHandler stream;
362 int size;
363 };
364 extern "C" void Process(StreamHandler handler);)",
365 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
366 IsOk());
367 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
368
369 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
370 ElementsAre("using size_t = long long", "struct _Image",
371 "typedef struct _Image Image",
372 "typedef size_t (*StreamHandler)(const Image *, "
373 "const void *, const size_t)",
374 "struct _Image {"
375 " StreamHandler stream;"
376 " int size; }"));
377 }
378
TEST_F(EmitterTest,OmitDependentTypes)379 TEST_F(EmitterTest, OmitDependentTypes) {
380 EmitterForTesting emitter;
381 EXPECT_THAT(
382 RunFrontendAction(
383 R"(template <typename T>
384 struct Callback {
385 typedef void (T::*MemberSignature)();
386 MemberSignature pointer;
387 };
388 struct S : public Callback<S> {
389 void Callable() {}
390 };
391 extern "C" void Invoke(S::MemberSignature* cb);)",
392 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
393 IsOk());
394 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
395
396 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), IsEmpty());
397 }
398
TEST_F(EmitterTest,SkipAbseilInternals)399 TEST_F(EmitterTest, SkipAbseilInternals) {
400 EmitterForTesting emitter;
401 EXPECT_THAT(
402 RunFrontendAction(
403 R"(namespace absl::internal {
404 typedef int Int;
405 }
406 extern "C" void TakesAnInternalInt(absl::internal::Int);
407 extern "C" void AbslInternalTakingAnInt(int);)",
408 std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
409 IsOk());
410 EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));
411
412 EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), IsEmpty());
413 }
414
TEST(IncludeGuard,CreatesRandomizedGuardForEmptyFilename)415 TEST(IncludeGuard, CreatesRandomizedGuardForEmptyFilename) {
416 // Copybara will transform the string. This is intentional.
417 constexpr absl::string_view kGeneratedHeaderPrefix =
418 "SANDBOXED_API_GENERATED_HEADER_";
419
420 const std::string include_guard = GetIncludeGuard("");
421 EXPECT_THAT(include_guard, MatchesRegex(absl::StrCat(kGeneratedHeaderPrefix,
422 R"([0-9A-F]+_)")));
423
424 EXPECT_THAT(GetIncludeGuard(""), StrNe(include_guard));
425 }
426
TEST(IncludeGuard,BasicFunctionality)427 TEST(IncludeGuard, BasicFunctionality) {
428 EXPECT_THAT(GetIncludeGuard("boost/graph/compressed_sparse_row_graph.hpp"),
429 StrEq("BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP_"));
430
431 // "SAPI_" prefix is there to avoid generating guards starting with "_"
432 EXPECT_THAT(GetIncludeGuard("/usr/include/unistd.h"),
433 StrEq("SAPI_USR_INCLUDE_UNISTD_H_"));
434 }
435
TEST(IncludeGuard,AvoidReservedIdentifiers)436 TEST(IncludeGuard, AvoidReservedIdentifiers) {
437 EXPECT_THAT(GetIncludeGuard("9p.h"), StrEq("SAPI_9P_H_"));
438 EXPECT_THAT(GetIncludeGuard("double__under.h"), StrEq("DOUBLE_UNDER_H_"));
439 EXPECT_THAT(GetIncludeGuard("_single.h"), StrEq("SAPI_SINGLE_H_"));
440 EXPECT_THAT(GetIncludeGuard("__double.h"), StrEq("SAPI_DOUBLE_H_"));
441 }
442
443 } // namespace
444 } // namespace sapi
445