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 <gtest/gtest.h>
18 
19 #include <map>
20 #include <sstream>
21 #include <string>
22 
23 
24 namespace header_checker {
25 namespace repr {
26 
27 
TEST(VersionScriptParserTest,SmokeTest)28 TEST(VersionScriptParserTest, SmokeTest) {
29   static const char testdata[] = R"TESTDATA(
30     LIBEX_1.0 {
31       global:
32         foo1;
33         bar1;  # var
34       local:
35         *;
36     };
37 
38     LIBEX_2.0 {
39       global:
40         foo2;
41         bar2;  # var
42     } LIBEX_1.0;
43   )TESTDATA";
44 
45   VersionScriptParser parser;
46 
47   std::istringstream stream(testdata);
48   std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
49   ASSERT_TRUE(result);
50 
51   const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
52   EXPECT_NE(funcs.end(), funcs.find("foo1"));
53   EXPECT_NE(funcs.end(), funcs.find("foo2"));
54   EXPECT_EQ(funcs.end(), funcs.find("bar1"));
55   EXPECT_EQ(funcs.end(), funcs.find("bar2"));
56 
57   const ExportedSymbolSet::VarMap &vars = result->GetVars();
58   EXPECT_NE(vars.end(), vars.find("bar1"));
59   EXPECT_NE(vars.end(), vars.find("bar2"));
60   EXPECT_EQ(vars.end(), vars.find("foo1"));
61   EXPECT_EQ(vars.end(), vars.find("foo2"));
62 }
63 
64 
TEST(VersionScriptParserTest,ExcludeSymbolVersions)65 TEST(VersionScriptParserTest, ExcludeSymbolVersions) {
66   static const char testdata[] = R"TESTDATA(
67     LIBEX_1.0 {
68       global:
69         foo1;
70         bar1;  # var
71       local:
72         *;
73     };
74 
75     LIBEX_PRIVATE {
76       global:
77         foo2;
78         bar2;  # var
79     } LIBEX_1.0;
80   )TESTDATA";
81 
82   // excluded_symbol_versions = {}
83   {
84     VersionScriptParser parser;
85 
86     std::istringstream stream(testdata);
87     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
88     ASSERT_TRUE(result);
89 
90     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
91     EXPECT_NE(funcs.end(), funcs.find("foo2"));
92 
93     const ExportedSymbolSet::VarMap &vars = result->GetVars();
94     EXPECT_NE(vars.end(), vars.find("bar2"));
95   }
96 
97   // excluded_symbol_versions = {"LIBEX_PRIVATE"}
98   {
99     VersionScriptParser parser;
100     parser.AddExcludedSymbolVersion("LIBEX_PRIVATE");
101 
102     std::istringstream stream(testdata);
103     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
104     ASSERT_TRUE(result);
105 
106     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
107     EXPECT_EQ(funcs.end(), funcs.find("foo2"));
108 
109     const ExportedSymbolSet::VarMap &vars = result->GetVars();
110     EXPECT_EQ(vars.end(), vars.find("bar2"));
111   }
112 }
113 
114 
TEST(VersionScriptParserTest,VisibilityLabels)115 TEST(VersionScriptParserTest, VisibilityLabels) {
116   static const char testdata[] = R"TESTDATA(
117     LIBEX_1.0 {
118       global:
119         global_f1;
120         global_v1;  # var
121       local:
122         local_f2;
123         local_v2;  # var
124       global:
125         global_f3;
126         global_v3;  # var
127       global:
128         global_f4;
129         global_v4;  # var
130       local:
131         local_f5;
132         local_v5;  # var
133       local:
134         local_f6;
135         local_v6;  # var
136     };
137   )TESTDATA";
138 
139   VersionScriptParser parser;
140 
141   std::istringstream stream(testdata);
142   std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
143   ASSERT_TRUE(result);
144 
145   const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
146 
147   EXPECT_NE(funcs.end(), funcs.find("global_f1"));
148   EXPECT_NE(funcs.end(), funcs.find("global_f3"));
149   EXPECT_NE(funcs.end(), funcs.find("global_f4"));
150 
151   EXPECT_EQ(funcs.end(), funcs.find("local_f2"));
152   EXPECT_EQ(funcs.end(), funcs.find("local_f5"));
153   EXPECT_EQ(funcs.end(), funcs.find("local_f6"));
154 
155   const ExportedSymbolSet::VarMap &vars = result->GetVars();
156 
157   EXPECT_NE(vars.end(), vars.find("global_v1"));
158   EXPECT_NE(vars.end(), vars.find("global_v3"));
159   EXPECT_NE(vars.end(), vars.find("global_v4"));
160 
161   EXPECT_EQ(vars.end(), vars.find("local_v2"));
162   EXPECT_EQ(vars.end(), vars.find("local_v5"));
163   EXPECT_EQ(vars.end(), vars.find("local_v6"));
164 }
165 
166 
TEST(VersionScriptParserTest,ParseSymbolTagsIntroduced)167 TEST(VersionScriptParserTest, ParseSymbolTagsIntroduced) {
168   static const char testdata[] = R"TESTDATA(
169     LIBEX_1.0 {
170       global:
171         test1;  # introduced=19
172         test2;  # introduced=19 introduced-arm64=20
173         test3;  # introduced-arm64=20 introduced=19
174         test4;  # future
175     };
176   )TESTDATA";
177 
178   {
179     VersionScriptParser parser;
180     parser.SetArch("arm64");
181     parser.SetApiLevel(18);
182 
183     std::istringstream stream(testdata);
184     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
185     ASSERT_TRUE(result);
186 
187     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
188 
189     EXPECT_EQ(funcs.end(), funcs.find("test1"));
190     EXPECT_EQ(funcs.end(), funcs.find("test2"));
191     EXPECT_EQ(funcs.end(), funcs.find("test3"));
192     EXPECT_EQ(funcs.end(), funcs.find("test4"));
193   }
194 
195   {
196     VersionScriptParser parser;
197     parser.SetArch("arm64");
198     parser.SetApiLevel(19);
199 
200     std::istringstream stream(testdata);
201     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
202     ASSERT_TRUE(result);
203 
204     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
205 
206     EXPECT_NE(funcs.end(), funcs.find("test1"));
207     EXPECT_EQ(funcs.end(), funcs.find("test2"));
208     EXPECT_EQ(funcs.end(), funcs.find("test3"));
209     EXPECT_EQ(funcs.end(), funcs.find("test4"));
210   }
211 
212   {
213     VersionScriptParser parser;
214     parser.SetArch("arm");
215     parser.SetApiLevel(19);
216 
217     std::istringstream stream(testdata);
218     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
219     ASSERT_TRUE(result);
220 
221     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
222 
223     EXPECT_NE(funcs.end(), funcs.find("test1"));
224     EXPECT_NE(funcs.end(), funcs.find("test2"));
225     EXPECT_NE(funcs.end(), funcs.find("test3"));
226     EXPECT_EQ(funcs.end(), funcs.find("test4"));
227   }
228 
229   {
230     VersionScriptParser parser;
231     parser.SetArch("arm64");
232     parser.SetApiLevel(20);
233 
234     std::istringstream stream(testdata);
235     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
236     ASSERT_TRUE(result);
237 
238     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
239 
240     EXPECT_NE(funcs.end(), funcs.find("test1"));
241     EXPECT_NE(funcs.end(), funcs.find("test2"));
242     EXPECT_NE(funcs.end(), funcs.find("test3"));
243     EXPECT_EQ(funcs.end(), funcs.find("test4"));
244   }
245 
246   {
247     VersionScriptParser parser;
248     parser.SetArch("arm64");
249     parser.SetApiLevel(utils::FUTURE_API_LEVEL);
250 
251     std::istringstream stream(testdata);
252     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
253     ASSERT_TRUE(result);
254 
255     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
256 
257     EXPECT_NE(funcs.end(), funcs.find("test1"));
258     EXPECT_NE(funcs.end(), funcs.find("test2"));
259     EXPECT_NE(funcs.end(), funcs.find("test3"));
260     EXPECT_NE(funcs.end(), funcs.find("test4"));
261   }
262 }
263 
264 
TEST(VersionScriptParserTest,ParseSymbolTagsArch)265 TEST(VersionScriptParserTest, ParseSymbolTagsArch) {
266   static const char testdata[] = R"TESTDATA(
267     LIBEX_1.0 {
268       global:
269         test1;
270         test2;  # arm arm64
271         test3;  # arm64
272         test4;  # mips
273     };
274   )TESTDATA";
275 
276   {
277     VersionScriptParser parser;
278     parser.SetArch("arm");
279 
280     std::istringstream stream(testdata);
281     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
282     ASSERT_TRUE(result);
283 
284     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
285 
286     EXPECT_NE(funcs.end(), funcs.find("test1"));
287     EXPECT_NE(funcs.end(), funcs.find("test2"));
288     EXPECT_EQ(funcs.end(), funcs.find("test3"));
289     EXPECT_EQ(funcs.end(), funcs.find("test4"));
290   }
291 
292   {
293     VersionScriptParser parser;
294     parser.SetArch("arm64");
295 
296     std::istringstream stream(testdata);
297     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
298     ASSERT_TRUE(result);
299 
300     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
301 
302     EXPECT_NE(funcs.end(), funcs.find("test1"));
303     EXPECT_NE(funcs.end(), funcs.find("test2"));
304     EXPECT_NE(funcs.end(), funcs.find("test3"));
305     EXPECT_EQ(funcs.end(), funcs.find("test4"));
306   }
307 
308   {
309     VersionScriptParser parser;
310     parser.SetArch("mips");
311 
312     std::istringstream stream(testdata);
313     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
314     ASSERT_TRUE(result);
315 
316     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
317 
318     EXPECT_NE(funcs.end(), funcs.find("test1"));
319     EXPECT_EQ(funcs.end(), funcs.find("test2"));
320     EXPECT_EQ(funcs.end(), funcs.find("test3"));
321     EXPECT_NE(funcs.end(), funcs.find("test4"));
322   }
323 }
324 
325 
TEST(VersionScriptParserTest,ExcludeSymbolTags)326 TEST(VersionScriptParserTest, ExcludeSymbolTags) {
327   static const char testdata[] = R"TESTDATA(
328     LIBEX_1.0 {
329       global:
330         test1;
331         test2;  # exclude-tag
332     };
333   )TESTDATA";
334 
335   // exclude_symbol_tags = {}
336   {
337     VersionScriptParser parser;
338 
339     std::istringstream stream(testdata);
340     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
341     ASSERT_TRUE(result);
342 
343     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
344 
345     EXPECT_NE(funcs.end(), funcs.find("test1"));
346     EXPECT_NE(funcs.end(), funcs.find("test2"));
347   }
348 
349   // exclude_symbol_tags = {"exclude-tag"}
350   {
351     VersionScriptParser parser;
352     parser.AddExcludedSymbolTag("exclude-tag");
353 
354     std::istringstream stream(testdata);
355     std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
356     ASSERT_TRUE(result);
357 
358     const ExportedSymbolSet::FunctionMap &funcs = result->GetFunctions();
359 
360     EXPECT_NE(funcs.end(), funcs.find("test1"));
361     EXPECT_EQ(funcs.end(), funcs.find("test2"));
362   }
363 }
364 
365 
TEST(VersionScriptParserTest,ParseExternCpp)366 TEST(VersionScriptParserTest, ParseExternCpp) {
367   static const char testdata[] = R"TESTDATA(
368     LIBEX_1.0 {
369       global:
370         test1;
371         extern "C++" {
372           Test2::test();
373           Test3::test();
374           Test4::*;
375         };
376         test5;
377     };
378   )TESTDATA";
379 
380   VersionScriptParser parser;
381 
382   std::istringstream stream(testdata);
383   std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
384   ASSERT_TRUE(result);
385 
386   const ExportedSymbolSet::NameSet &cpp_symbols =
387       result->GetDemangledCppSymbols();
388 
389   EXPECT_NE(cpp_symbols.end(), cpp_symbols.find("Test2::test()"));
390   EXPECT_NE(cpp_symbols.end(), cpp_symbols.find("Test3::test()"));
391 
392   EXPECT_EQ(cpp_symbols.end(), cpp_symbols.find("test1"));
393   EXPECT_EQ(cpp_symbols.end(), cpp_symbols.find("test4"));
394 
395   const ExportedSymbolSet::GlobPatternSet &cpp_glob_patterns =
396       result->GetDemangledCppGlobPatterns();
397 
398   EXPECT_NE(cpp_glob_patterns.end(), cpp_glob_patterns.find("Test4::*"));
399 }
400 
401 
TEST(VersionScriptParserTest,ParseGlobPattern)402 TEST(VersionScriptParserTest, ParseGlobPattern) {
403   static const char testdata[] = R"TESTDATA(
404     LIBEX_1.0 {
405       global:
406         test1*;
407         test2[Aa];
408         test3?;
409         test4;
410     };
411   )TESTDATA";
412 
413 
414   VersionScriptParser parser;
415 
416   std::istringstream stream(testdata);
417   std::unique_ptr<ExportedSymbolSet> result(parser.Parse(stream));
418   ASSERT_TRUE(result);
419 
420   const ExportedSymbolSet::GlobPatternSet &glob_patterns =
421       result->GetGlobPatterns();
422 
423   EXPECT_NE(glob_patterns.end(), glob_patterns.find("test1*"));
424   EXPECT_NE(glob_patterns.end(), glob_patterns.find("test2[Aa]"));
425   EXPECT_NE(glob_patterns.end(), glob_patterns.find("test3?"));
426 
427   EXPECT_EQ(glob_patterns.end(), glob_patterns.find("test4"));
428 }
429 
430 
431 }  // namespace repr
432 }  // namespace header_checker
433