xref: /aosp_15_r20/development/vndk/tools/header-checker/src/repr/symbol/version_script_parser_test.cpp (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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