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