blob: 3dbab61805d7b11ca66f6b71b6083f448add9504 [file] [log] [blame]
Dan Albert06f58af2020-06-22 15:10:31 -07001#!/usr/bin/env python
2#
3# Copyright (C) 2016 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17"""Tests for ndkstubgen.py."""
18import io
19import textwrap
20import unittest
21
22import ndkstubgen
23import symbolfile
Dan Albertaf7b36d2020-06-23 11:21:21 -070024from symbolfile import Arch, Tag
Dan Albert06f58af2020-06-22 15:10:31 -070025
26
27# pylint: disable=missing-docstring
28
29
30class GeneratorTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -070031 def test_omit_version(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070032 # Thorough testing of the cases involved here is handled by
33 # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
34 src_file = io.StringIO()
35 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -070036 symbol_list_file = io.StringIO()
37 generator = ndkstubgen.Generator(src_file,
38 version_file, symbol_list_file,
39 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -070040
41 version = symbolfile.Version('VERSION_PRIVATE', None, [], [
42 symbolfile.Symbol('foo', []),
43 ])
44 generator.write_version(version)
45 self.assertEqual('', src_file.getvalue())
46 self.assertEqual('', version_file.getvalue())
47
Dan Albertaf7b36d2020-06-23 11:21:21 -070048 version = symbolfile.Version('VERSION', None, [Tag('x86')], [
Dan Albert06f58af2020-06-22 15:10:31 -070049 symbolfile.Symbol('foo', []),
50 ])
51 generator.write_version(version)
52 self.assertEqual('', src_file.getvalue())
53 self.assertEqual('', version_file.getvalue())
54
Dan Albertaf7b36d2020-06-23 11:21:21 -070055 version = symbolfile.Version('VERSION', None, [Tag('introduced=14')], [
Dan Albert06f58af2020-06-22 15:10:31 -070056 symbolfile.Symbol('foo', []),
57 ])
58 generator.write_version(version)
59 self.assertEqual('', src_file.getvalue())
60 self.assertEqual('', version_file.getvalue())
61
Dan Albertaf7b36d2020-06-23 11:21:21 -070062 def test_omit_symbol(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070063 # Thorough testing of the cases involved here is handled by
64 # SymbolPresenceTest.
65 src_file = io.StringIO()
66 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -070067 symbol_list_file = io.StringIO()
68 generator = ndkstubgen.Generator(src_file,
69 version_file, symbol_list_file,
70 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -070071
72 version = symbolfile.Version('VERSION_1', None, [], [
Dan Albertaf7b36d2020-06-23 11:21:21 -070073 symbolfile.Symbol('foo', [Tag('x86')]),
Dan Albert06f58af2020-06-22 15:10:31 -070074 ])
75 generator.write_version(version)
76 self.assertEqual('', src_file.getvalue())
77 self.assertEqual('', version_file.getvalue())
78
79 version = symbolfile.Version('VERSION_1', None, [], [
Dan Albertaf7b36d2020-06-23 11:21:21 -070080 symbolfile.Symbol('foo', [Tag('introduced=14')]),
Dan Albert06f58af2020-06-22 15:10:31 -070081 ])
82 generator.write_version(version)
83 self.assertEqual('', src_file.getvalue())
84 self.assertEqual('', version_file.getvalue())
85
86 version = symbolfile.Version('VERSION_1', None, [], [
Dan Albertaf7b36d2020-06-23 11:21:21 -070087 symbolfile.Symbol('foo', [Tag('llndk')]),
Dan Albert06f58af2020-06-22 15:10:31 -070088 ])
89 generator.write_version(version)
90 self.assertEqual('', src_file.getvalue())
91 self.assertEqual('', version_file.getvalue())
92
93 version = symbolfile.Version('VERSION_1', None, [], [
Dan Albertaf7b36d2020-06-23 11:21:21 -070094 symbolfile.Symbol('foo', [Tag('apex')]),
Dan Albert06f58af2020-06-22 15:10:31 -070095 ])
96 generator.write_version(version)
97 self.assertEqual('', src_file.getvalue())
98 self.assertEqual('', version_file.getvalue())
99
Dan Albertaf7b36d2020-06-23 11:21:21 -0700100 def test_write(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700101 src_file = io.StringIO()
102 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700103 symbol_list_file = io.StringIO()
104 generator = ndkstubgen.Generator(src_file,
105 version_file, symbol_list_file,
106 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700107
108 versions = [
109 symbolfile.Version('VERSION_1', None, [], [
110 symbolfile.Symbol('foo', []),
Dan Albertaf7b36d2020-06-23 11:21:21 -0700111 symbolfile.Symbol('bar', [Tag('var')]),
112 symbolfile.Symbol('woodly', [Tag('weak')]),
113 symbolfile.Symbol('doodly',
114 [Tag('weak'), Tag('var')]),
Dan Albert06f58af2020-06-22 15:10:31 -0700115 ]),
116 symbolfile.Version('VERSION_2', 'VERSION_1', [], [
117 symbolfile.Symbol('baz', []),
118 ]),
119 symbolfile.Version('VERSION_3', 'VERSION_1', [], [
Dan Albertaf7b36d2020-06-23 11:21:21 -0700120 symbolfile.Symbol('qux', [Tag('versioned=14')]),
Dan Albert06f58af2020-06-22 15:10:31 -0700121 ]),
122 ]
123
124 generator.write(versions)
125 expected_src = textwrap.dedent("""\
126 void foo() {}
127 int bar = 0;
128 __attribute__((weak)) void woodly() {}
129 __attribute__((weak)) int doodly = 0;
130 void baz() {}
131 void qux() {}
132 """)
133 self.assertEqual(expected_src, src_file.getvalue())
134
135 expected_version = textwrap.dedent("""\
136 VERSION_1 {
137 global:
138 foo;
139 bar;
140 woodly;
141 doodly;
142 };
143 VERSION_2 {
144 global:
145 baz;
146 } VERSION_1;
147 """)
148 self.assertEqual(expected_version, version_file.getvalue())
149
Dan Albertf1d14c72020-07-30 14:32:55 -0700150 expected_allowlist = textwrap.dedent("""\
151 [abi_symbol_list]
152 foo
153 bar
154 woodly
155 doodly
156 baz
157 qux
158 """)
159 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
160
Dan Albert06f58af2020-06-22 15:10:31 -0700161
162class IntegrationTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -0700163 def test_integration(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700164 api_map = {
165 'O': 9000,
166 'P': 9001,
167 }
168
169 input_file = io.StringIO(textwrap.dedent("""\
170 VERSION_1 {
171 global:
172 foo; # var
173 bar; # x86
174 fizz; # introduced=O
175 buzz; # introduced=P
176 local:
177 *;
178 };
179
180 VERSION_2 { # arm
181 baz; # introduced=9
182 qux; # versioned=14
183 } VERSION_1;
184
185 VERSION_3 { # introduced=14
186 woodly;
187 doodly; # var
188 } VERSION_2;
189
190 VERSION_4 { # versioned=9
191 wibble;
192 wizzes; # llndk
193 waggle; # apex
194 } VERSION_2;
195
196 VERSION_5 { # versioned=14
197 wobble;
198 } VERSION_4;
199 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700200 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
201 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700202 versions = parser.parse()
203
204 src_file = io.StringIO()
205 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700206 symbol_list_file = io.StringIO()
207 generator = ndkstubgen.Generator(src_file,
208 version_file, symbol_list_file,
209 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700210 generator.write(versions)
211
212 expected_src = textwrap.dedent("""\
213 int foo = 0;
214 void baz() {}
215 void qux() {}
216 void wibble() {}
217 void wobble() {}
218 """)
219 self.assertEqual(expected_src, src_file.getvalue())
220
221 expected_version = textwrap.dedent("""\
222 VERSION_1 {
223 global:
224 foo;
225 };
226 VERSION_2 {
227 global:
228 baz;
229 } VERSION_1;
230 VERSION_4 {
231 global:
232 wibble;
233 } VERSION_2;
234 """)
235 self.assertEqual(expected_version, version_file.getvalue())
236
Dan Albertf1d14c72020-07-30 14:32:55 -0700237 expected_allowlist = textwrap.dedent("""\
238 [abi_symbol_list]
239 foo
240 baz
241 qux
242 wibble
243 wobble
244 """)
245 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
246
Dan Albertaf7b36d2020-06-23 11:21:21 -0700247 def test_integration_future_api(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700248 api_map = {
249 'O': 9000,
250 'P': 9001,
251 'Q': 9002,
252 }
253
254 input_file = io.StringIO(textwrap.dedent("""\
255 VERSION_1 {
256 global:
257 foo; # introduced=O
258 bar; # introduced=P
259 baz; # introduced=Q
260 local:
261 *;
262 };
263 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700264 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
265 9001, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700266 versions = parser.parse()
267
268 src_file = io.StringIO()
269 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700270 symbol_list_file = io.StringIO()
271 generator = ndkstubgen.Generator(src_file,
272 version_file, symbol_list_file,
273 Arch('arm'), 9001, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700274 generator.write(versions)
275
276 expected_src = textwrap.dedent("""\
277 void foo() {}
278 void bar() {}
279 """)
280 self.assertEqual(expected_src, src_file.getvalue())
281
282 expected_version = textwrap.dedent("""\
283 VERSION_1 {
284 global:
285 foo;
286 bar;
287 };
288 """)
289 self.assertEqual(expected_version, version_file.getvalue())
290
Dan Albertf1d14c72020-07-30 14:32:55 -0700291 expected_allowlist = textwrap.dedent("""\
292 [abi_symbol_list]
293 foo
294 bar
295 """)
296 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
297
Dan Albertaf7b36d2020-06-23 11:21:21 -0700298 def test_multiple_definition(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700299 input_file = io.StringIO(textwrap.dedent("""\
300 VERSION_1 {
301 global:
302 foo;
303 foo;
304 bar;
305 baz;
306 qux; # arm
307 local:
308 *;
309 };
310
311 VERSION_2 {
312 global:
313 bar;
314 qux; # arm64
315 } VERSION_1;
316
317 VERSION_PRIVATE {
318 global:
319 baz;
320 } VERSION_2;
321
322 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700323 parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
324 False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700325
326 with self.assertRaises(
327 symbolfile.MultiplyDefinedSymbolError) as ex_context:
328 parser.parse()
329 self.assertEqual(['bar', 'foo'],
330 ex_context.exception.multiply_defined_symbols)
331
Dan Albertaf7b36d2020-06-23 11:21:21 -0700332 def test_integration_with_apex(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700333 api_map = {
334 'O': 9000,
335 'P': 9001,
336 }
337
338 input_file = io.StringIO(textwrap.dedent("""\
339 VERSION_1 {
340 global:
341 foo; # var
342 bar; # x86
343 fizz; # introduced=O
344 buzz; # introduced=P
345 local:
346 *;
347 };
348
349 VERSION_2 { # arm
350 baz; # introduced=9
351 qux; # versioned=14
352 } VERSION_1;
353
354 VERSION_3 { # introduced=14
355 woodly;
356 doodly; # var
357 } VERSION_2;
358
359 VERSION_4 { # versioned=9
360 wibble;
361 wizzes; # llndk
362 waggle; # apex
363 bubble; # apex llndk
364 duddle; # llndk apex
365 } VERSION_2;
366
367 VERSION_5 { # versioned=14
368 wobble;
369 } VERSION_4;
370 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700371 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
372 9, False, True)
Dan Albert06f58af2020-06-22 15:10:31 -0700373 versions = parser.parse()
374
375 src_file = io.StringIO()
376 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700377 symbol_list_file = io.StringIO()
378 generator = ndkstubgen.Generator(src_file,
379 version_file, symbol_list_file,
380 Arch('arm'), 9, False, True)
Dan Albert06f58af2020-06-22 15:10:31 -0700381 generator.write(versions)
382
383 expected_src = textwrap.dedent("""\
384 int foo = 0;
385 void baz() {}
386 void qux() {}
387 void wibble() {}
388 void waggle() {}
389 void bubble() {}
390 void duddle() {}
391 void wobble() {}
392 """)
393 self.assertEqual(expected_src, src_file.getvalue())
394
395 expected_version = textwrap.dedent("""\
396 VERSION_1 {
397 global:
398 foo;
399 };
400 VERSION_2 {
401 global:
402 baz;
403 } VERSION_1;
404 VERSION_4 {
405 global:
406 wibble;
407 waggle;
408 bubble;
409 duddle;
410 } VERSION_2;
411 """)
412 self.assertEqual(expected_version, version_file.getvalue())
413
Dan Albertaf7b36d2020-06-23 11:21:21 -0700414
415def main() -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700416 suite = unittest.TestLoader().loadTestsFromName(__name__)
417 unittest.TextTestRunner(verbosity=3).run(suite)
418
419
420if __name__ == '__main__':
421 main()