xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/tools/clang_generator/emitter_test.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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