1 // Copyright (C) 2019 The Android Open Source Project
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 // http://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 "repr/symbol/version_script_parser.h"
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include <map>
21 #include <sstream>
22 #include <string>
23
24
25 namespace header_checker {
26 namespace repr {
27
28
29 using testing::ElementsAre;
30 using testing::Key;
31
32
TEST(VersionScriptParserTest,SmokeTest)33 TEST(VersionScriptParserTest, SmokeTest) {
34 static const char testdata[] = R"TESTDATA(
35 LIBEX_1.0 {
36 global:
37 foo1;
38 bar1; # var
39 local:
40 *;
41 };
42
43 LIBEX_2.0 {
44 global:
45 foo2;
46 bar2; # var
47 } LIBEX_1.0;
48 )TESTDATA";
49
50 VersionScriptParser parser;
51
52 std::istringstream stream(testdata);
53 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
54 ASSERT_TRUE(result);
55
56 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
57 EXPECT_THAT(funcs, ElementsAre(Key("foo1"), Key("foo2")));
58
59 const ExportedSymbolSet::VarMap &vars = result->GetVars();
60 EXPECT_THAT(vars, ElementsAre(Key("bar1"), Key("bar2")));
61 }
62
63
TEST(VersionScriptParserTest,ExcludeSymbolVersions)64 TEST(VersionScriptParserTest, ExcludeSymbolVersions) {
65 static const char testdata[] = R"TESTDATA(
66 LIBEX_1.0 {
67 global:
68 foo1;
69 bar1; # var
70 local:
71 *;
72 };
73
74 LIBEX_PRIVATE {
75 global:
76 foo2;
77 bar2; # var
78 } LIBEX_1.0;
79 )TESTDATA";
80
81 // excluded_symbol_versions = {}
82 {
83 VersionScriptParser parser;
84
85 std::istringstream stream(testdata);
86 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
87 ASSERT_TRUE(result);
88
89 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
90 EXPECT_THAT(funcs, ElementsAre(Key("foo1"), Key("foo2")));
91
92 const ExportedSymbolSet::VarMap &vars = result->GetVars();
93 EXPECT_THAT(vars, ElementsAre(Key("bar1"), Key("bar2")));
94 }
95
96 {
97 VersionScriptParser parser;
98 parser.AddExcludedSymbolVersion("*_PRIVATE");
99
100 std::istringstream stream(testdata);
101 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
102 ASSERT_TRUE(result);
103
104 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
105 EXPECT_THAT(funcs, ElementsAre(Key("foo1")));
106
107 const ExportedSymbolSet::VarMap &vars = result->GetVars();
108 EXPECT_THAT(vars, ElementsAre(Key("bar1")));
109 }
110 }
111
112
TEST(VersionScriptParserTest,VisibilityLabels)113 TEST(VersionScriptParserTest, VisibilityLabels) {
114 static const char testdata[] = R"TESTDATA(
115 LIBEX_1.0 {
116 global:
117 global_f1;
118 global_v1; # var
119 local:
120 local_f2;
121 local_v2; # var
122 global:
123 global_f3;
124 global_v3; # var
125 global:
126 global_f4;
127 global_v4; # var
128 local:
129 local_f5;
130 local_v5; # var
131 local:
132 local_f6;
133 local_v6; # var
134 };
135 )TESTDATA";
136
137 VersionScriptParser parser;
138
139 std::istringstream stream(testdata);
140 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
141 ASSERT_TRUE(result);
142
143 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
144
145 EXPECT_THAT(
146 funcs, ElementsAre(Key("global_f1"), Key("global_f3"), Key("global_f4")));
147
148 const ExportedSymbolSet::VarMap &vars = result->GetVars();
149
150 EXPECT_THAT(
151 vars, ElementsAre(Key("global_v1"), Key("global_v3"), Key("global_v4")));
152 }
153
154
TEST(VersionScriptParserTest,ParseSymbolTagsIntroduced)155 TEST(VersionScriptParserTest, ParseSymbolTagsIntroduced) {
156 static const char testdata[] = R"TESTDATA(
157 LIBEX_1.0 { # introduced=18
158 global:
159 test1; # introduced=19
160 test2; # introduced=19 introduced-arm64=20
161 test3; # introduced-arm64=20 introduced=19
162 test4; # future
163 test5; # introduced=17
164 };
165 )TESTDATA";
166
167 {
168 VersionScriptParser parser;
169 parser.SetArch("arm64");
170 parser.SetApiLevel(17);
171
172 std::istringstream stream(testdata);
173 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
174 ASSERT_TRUE(result);
175
176 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
177 // This may be an undefined behavior. ndkstubgen includes it in llndk mode,
178 // but excludes it in ndk mode.
179 EXPECT_THAT(funcs, ElementsAre(Key("test5")));
180 }
181
182 {
183 VersionScriptParser parser;
184 parser.SetArch("arm64");
185 parser.SetApiLevel(18);
186
187 std::istringstream stream(testdata);
188 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
189 ASSERT_TRUE(result);
190
191 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
192
193 EXPECT_THAT(funcs, ElementsAre(Key("test5")));
194 }
195
196 {
197 VersionScriptParser parser;
198 parser.SetArch("arm64");
199 parser.SetApiLevel(19);
200
201 std::istringstream stream(testdata);
202 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
203 ASSERT_TRUE(result);
204
205 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
206
207 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test5")));
208 }
209
210 {
211 VersionScriptParser parser;
212 parser.SetArch("arm");
213 parser.SetApiLevel(19);
214
215 std::istringstream stream(testdata);
216 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
217 ASSERT_TRUE(result);
218
219 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
220
221 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2"), Key("test3"),
222 Key("test5")));
223 }
224
225 {
226 VersionScriptParser parser;
227 parser.SetArch("arm64");
228 parser.SetApiLevel(20);
229
230 std::istringstream stream(testdata);
231 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
232 ASSERT_TRUE(result);
233
234 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
235
236 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2"), Key("test3"),
237 Key("test5")));
238 }
239
240 {
241 VersionScriptParser parser;
242 parser.SetArch("arm64");
243 parser.SetApiLevel(utils::FUTURE_API_LEVEL);
244
245 std::istringstream stream(testdata);
246 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
247 ASSERT_TRUE(result);
248
249 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
250
251 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2"), Key("test3"),
252 Key("test4"), Key("test5")));
253 }
254 }
255
256
TEST(VersionScriptParserTest,ParseSymbolTagsArch)257 TEST(VersionScriptParserTest, ParseSymbolTagsArch) {
258 static const char testdata[] = R"TESTDATA(
259 LIBEX_1.0 {
260 global:
261 test1;
262 test2; # arm arm64
263 test3; # arm64
264 test4; # mips
265 };
266 )TESTDATA";
267
268 {
269 VersionScriptParser parser;
270 parser.SetArch("arm");
271
272 std::istringstream stream(testdata);
273 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
274 ASSERT_TRUE(result);
275
276 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
277
278 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2")));
279 }
280
281 {
282 VersionScriptParser parser;
283 parser.SetArch("arm64");
284
285 std::istringstream stream(testdata);
286 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
287 ASSERT_TRUE(result);
288
289 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
290
291 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2"), Key("test3")));
292 }
293
294 {
295 VersionScriptParser parser;
296 parser.SetArch("mips");
297
298 std::istringstream stream(testdata);
299 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
300 ASSERT_TRUE(result);
301
302 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
303
304 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test4")));
305 }
306 }
307
308
TEST(VersionScriptParserTest,ExcludeSymbolTags)309 TEST(VersionScriptParserTest, ExcludeSymbolTags) {
310 static const char testdata[] = R"TESTDATA(
311 LIBEX_1.0 { # exclude-tag-1
312 global:
313 test1;
314 test2; # exclude-tag-2
315 };
316 )TESTDATA";
317
318 // exclude_symbol_tags = {}
319 {
320 VersionScriptParser parser;
321
322 std::istringstream stream(testdata);
323 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
324 ASSERT_TRUE(result);
325
326 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
327
328 EXPECT_THAT(funcs, ElementsAre(Key("test1"), Key("test2")));
329 }
330
331 {
332 VersionScriptParser parser;
333 parser.AddExcludedSymbolTag("exclude-tag-1");
334
335 std::istringstream stream(testdata);
336 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
337 ASSERT_TRUE(result);
338
339 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
340
341 EXPECT_TRUE(funcs.empty());
342 }
343
344 {
345 VersionScriptParser parser;
346 parser.AddExcludedSymbolTag("exclude-tag-2");
347
348 std::istringstream stream(testdata);
349 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
350 ASSERT_TRUE(result);
351
352 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
353
354 EXPECT_THAT(funcs, ElementsAre(Key("test1")));
355 }
356 }
357
358
TEST(VersionScriptParserTest,IncludeSymbolTags)359 TEST(VersionScriptParserTest, IncludeSymbolTags) {
360 static const char testdata[] = R"TESTDATA(
361 LIBEX_1.0 {
362 global:
363 always; # unknown
364 api34; # introduced=34
365 api35; # introduced=35
366 llndk202404; # llndk=202404
367 llndk202504; # llndk=202504
368 systemapi; # systemapi
369 systemapi_llndk; # systemapi llndk
370 };
371 )TESTDATA";
372
373 {
374 VersionScriptParser parser;
375 parser.SetApiLevel(34);
376 parser.AddModeTag("llndk=202404");
377
378 std::istringstream stream(testdata);
379 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
380 ASSERT_TRUE(result);
381
382 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
383
384 EXPECT_THAT(funcs, ElementsAre(Key("always"), Key("api34"),
385 Key("llndk202404"), Key("systemapi_llndk")));
386 }
387
388 {
389 VersionScriptParser parser;
390 parser.SetApiLevel(34);
391 parser.AddModeTag("llndk");
392
393 std::istringstream stream(testdata);
394 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
395 ASSERT_TRUE(result);
396
397 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
398
399 EXPECT_THAT(funcs,
400 ElementsAre(Key("always"), Key("api34"), Key("llndk202404"),
401 Key("llndk202504"), Key("systemapi_llndk")));
402 }
403
404 // Include all mode tags
405 {
406 VersionScriptParser parser;
407 parser.SetApiLevel(utils::FUTURE_API_LEVEL);
408
409 std::istringstream stream(testdata);
410 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
411 ASSERT_TRUE(result);
412
413 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
414
415 EXPECT_THAT(funcs, ElementsAre(Key("always"), Key("api34"), Key("api35"),
416 Key("llndk202404"), Key("llndk202504"),
417 Key("systemapi"), Key("systemapi_llndk")));
418 }
419
420 // Exclude all mode tags
421 {
422 VersionScriptParser parser;
423 parser.SetApiLevel(utils::FUTURE_API_LEVEL);
424 parser.AddModeTag("none");
425
426 std::istringstream stream(testdata);
427 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
428 ASSERT_TRUE(result);
429
430 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
431
432 EXPECT_THAT(funcs, ElementsAre(Key("always"), Key("api34"), Key("api35")));
433 }
434 }
435
436
TEST(VersionScriptParserTest,SetModeTagPolicy)437 TEST(VersionScriptParserTest, SetModeTagPolicy) {
438 static const char testdata[] = R"TESTDATA(
439 LIBEX_1.0 { # introduced=36
440 api36;
441 api36_llndk202504;
442 api36_llndk202504; # llndk=202504
443 llndk202504; # llndk=202504
444 };
445 )TESTDATA";
446
447 {
448 VersionScriptParser parser;
449 parser.SetApiLevel(35);
450 parser.AddModeTag("llndk=202504");
451 parser.SetModeTagPolicy(ModeTagPolicy::MatchTagAndApi);
452
453 std::istringstream stream(testdata);
454 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
455 ASSERT_TRUE(result);
456
457 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
458
459 EXPECT_TRUE(funcs.empty());
460 }
461
462 {
463 VersionScriptParser parser;
464 parser.SetApiLevel(35);
465 parser.AddModeTag("llndk=202504");
466 parser.SetModeTagPolicy(ModeTagPolicy::MatchTagOnly);
467
468 std::istringstream stream(testdata);
469 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
470 ASSERT_TRUE(result);
471
472 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
473
474 EXPECT_THAT(funcs,
475 ElementsAre(Key("api36_llndk202504"), Key("llndk202504")));
476 }
477
478 {
479 VersionScriptParser parser;
480 parser.SetApiLevel(36);
481 parser.SetModeTagPolicy(ModeTagPolicy::MatchTagAndApi);
482
483 std::istringstream stream(testdata);
484 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
485 ASSERT_TRUE(result);
486
487 const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
488
489 EXPECT_THAT(funcs, ElementsAre(Key("api36"), Key("api36_llndk202504"),
490 Key("llndk202504")));
491 }
492 }
493
494
TEST(VersionScriptParserTest,ParseExternCpp)495 TEST(VersionScriptParserTest, ParseExternCpp) {
496 static const char testdata[] = R"TESTDATA(
497 LIBEX_1.0 {
498 global:
499 test1;
500 extern "C++" {
501 Test2::test();
502 Test3::test();
503 Test4::*;
504 };
505 test5;
506 };
507 )TESTDATA";
508
509 VersionScriptParser parser;
510
511 std::istringstream stream(testdata);
512 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
513 ASSERT_TRUE(result);
514
515 const ExportedSymbolSet::NameSet &cpp_symbols =
516 result->GetDemangledCppSymbols();
517
518 EXPECT_THAT(cpp_symbols, ElementsAre("Test2::test()", "Test3::test()"));
519
520 const ExportedSymbolSet::GlobPatternSet &cpp_glob_patterns =
521 result->GetDemangledCppGlobPatterns();
522
523 EXPECT_THAT(cpp_glob_patterns, ElementsAre("Test4::*"));
524 }
525
526
TEST(VersionScriptParserTest,ParseGlobPattern)527 TEST(VersionScriptParserTest, ParseGlobPattern) {
528 static const char testdata[] = R"TESTDATA(
529 LIBEX_1.0 {
530 global:
531 test1*;
532 test2[Aa];
533 test3?;
534 test4;
535 };
536 )TESTDATA";
537
538
539 VersionScriptParser parser;
540
541 std::istringstream stream(testdata);
542 std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
543 ASSERT_TRUE(result);
544
545 const ExportedSymbolSet::GlobPatternSet &glob_patterns =
546 result->GetGlobPatterns();
547
548 EXPECT_THAT(glob_patterns, ElementsAre("test1*", "test2[Aa]", "test3?"));
549 }
550
551
552 } // namespace repr
553 } // namespace header_checker
554