• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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