blob: 09551eabbd11326004ff47f58b9a316ab3dc9325 [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
Dan Albert06f58af2020-06-22 15:10:31 -070022import symbolfile
Dan Albertead21552021-06-04 14:30:40 -070023from symbolfile import Arch, Tags
24
25import ndkstubgen
Dan Albert06f58af2020-06-22 15:10:31 -070026
27
28# pylint: disable=missing-docstring
29
30
31class GeneratorTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -070032 def test_omit_version(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070033 # Thorough testing of the cases involved here is handled by
34 # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
35 src_file = io.StringIO()
36 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -070037 symbol_list_file = io.StringIO()
38 generator = ndkstubgen.Generator(src_file,
39 version_file, symbol_list_file,
40 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -070041
Dan Albertead21552021-06-04 14:30:40 -070042 version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [
43 symbolfile.Symbol('foo', Tags()),
Dan Albert06f58af2020-06-22 15:10:31 -070044 ])
45 generator.write_version(version)
46 self.assertEqual('', src_file.getvalue())
47 self.assertEqual('', version_file.getvalue())
48
Dan Albertead21552021-06-04 14:30:40 -070049 version = symbolfile.Version('VERSION', None, Tags.from_strs(['x86']),
50 [
51 symbolfile.Symbol('foo', Tags()),
52 ])
Dan Albert06f58af2020-06-22 15:10:31 -070053 generator.write_version(version)
54 self.assertEqual('', src_file.getvalue())
55 self.assertEqual('', version_file.getvalue())
56
Dan Albertead21552021-06-04 14:30:40 -070057 version = symbolfile.Version('VERSION', None,
58 Tags.from_strs(['introduced=14']), [
59 symbolfile.Symbol('foo', Tags()),
60 ])
Dan Albert06f58af2020-06-22 15:10:31 -070061 generator.write_version(version)
62 self.assertEqual('', src_file.getvalue())
63 self.assertEqual('', version_file.getvalue())
64
Dan Albertaf7b36d2020-06-23 11:21:21 -070065 def test_omit_symbol(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070066 # Thorough testing of the cases involved here is handled by
67 # SymbolPresenceTest.
68 src_file = io.StringIO()
69 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -070070 symbol_list_file = io.StringIO()
71 generator = ndkstubgen.Generator(src_file,
72 version_file, symbol_list_file,
73 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -070074
Dan Albertead21552021-06-04 14:30:40 -070075 version = symbolfile.Version('VERSION_1', None, Tags(), [
76 symbolfile.Symbol('foo', Tags.from_strs(['x86'])),
Dan Albert06f58af2020-06-22 15:10:31 -070077 ])
78 generator.write_version(version)
79 self.assertEqual('', src_file.getvalue())
80 self.assertEqual('', version_file.getvalue())
81
Dan Albertead21552021-06-04 14:30:40 -070082 version = symbolfile.Version('VERSION_1', None, Tags(), [
83 symbolfile.Symbol('foo', Tags.from_strs(['introduced=14'])),
Dan Albert06f58af2020-06-22 15:10:31 -070084 ])
85 generator.write_version(version)
86 self.assertEqual('', src_file.getvalue())
87 self.assertEqual('', version_file.getvalue())
88
Dan Albertead21552021-06-04 14:30:40 -070089 version = symbolfile.Version('VERSION_1', None, Tags(), [
90 symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
Dan Albert06f58af2020-06-22 15:10:31 -070091 ])
92 generator.write_version(version)
93 self.assertEqual('', src_file.getvalue())
94 self.assertEqual('', version_file.getvalue())
95
Dan Albertead21552021-06-04 14:30:40 -070096 version = symbolfile.Version('VERSION_1', None, Tags(), [
97 symbolfile.Symbol('foo', Tags.from_strs(['apex'])),
Dan Albert06f58af2020-06-22 15:10:31 -070098 ])
99 generator.write_version(version)
100 self.assertEqual('', src_file.getvalue())
101 self.assertEqual('', version_file.getvalue())
102
Dan Albertaf7b36d2020-06-23 11:21:21 -0700103 def test_write(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700104 src_file = io.StringIO()
105 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700106 symbol_list_file = io.StringIO()
107 generator = ndkstubgen.Generator(src_file,
108 version_file, symbol_list_file,
109 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700110
111 versions = [
Dan Albertead21552021-06-04 14:30:40 -0700112 symbolfile.Version('VERSION_1', None, Tags(), [
113 symbolfile.Symbol('foo', Tags()),
114 symbolfile.Symbol('bar', Tags.from_strs(['var'])),
115 symbolfile.Symbol('woodly', Tags.from_strs(['weak'])),
116 symbolfile.Symbol('doodly', Tags.from_strs(['weak', 'var'])),
Dan Albert06f58af2020-06-22 15:10:31 -0700117 ]),
Dan Albertead21552021-06-04 14:30:40 -0700118 symbolfile.Version('VERSION_2', 'VERSION_1', Tags(), [
119 symbolfile.Symbol('baz', Tags()),
Dan Albert06f58af2020-06-22 15:10:31 -0700120 ]),
Dan Albertead21552021-06-04 14:30:40 -0700121 symbolfile.Version('VERSION_3', 'VERSION_1', Tags(), [
122 symbolfile.Symbol('qux', Tags.from_strs(['versioned=14'])),
Dan Albert06f58af2020-06-22 15:10:31 -0700123 ]),
124 ]
125
126 generator.write(versions)
127 expected_src = textwrap.dedent("""\
128 void foo() {}
129 int bar = 0;
130 __attribute__((weak)) void woodly() {}
131 __attribute__((weak)) int doodly = 0;
132 void baz() {}
133 void qux() {}
134 """)
135 self.assertEqual(expected_src, src_file.getvalue())
136
137 expected_version = textwrap.dedent("""\
138 VERSION_1 {
139 global:
140 foo;
141 bar;
142 woodly;
143 doodly;
144 };
145 VERSION_2 {
146 global:
147 baz;
148 } VERSION_1;
149 """)
150 self.assertEqual(expected_version, version_file.getvalue())
151
Dan Albertf1d14c72020-07-30 14:32:55 -0700152 expected_allowlist = textwrap.dedent("""\
153 [abi_symbol_list]
154 foo
155 bar
156 woodly
157 doodly
158 baz
159 qux
160 """)
161 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
162
Dan Albert06f58af2020-06-22 15:10:31 -0700163
164class IntegrationTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -0700165 def test_integration(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700166 api_map = {
167 'O': 9000,
168 'P': 9001,
169 }
170
171 input_file = io.StringIO(textwrap.dedent("""\
172 VERSION_1 {
173 global:
174 foo; # var
175 bar; # x86
176 fizz; # introduced=O
177 buzz; # introduced=P
178 local:
179 *;
180 };
181
182 VERSION_2 { # arm
183 baz; # introduced=9
184 qux; # versioned=14
185 } VERSION_1;
186
187 VERSION_3 { # introduced=14
188 woodly;
189 doodly; # var
190 } VERSION_2;
191
192 VERSION_4 { # versioned=9
193 wibble;
194 wizzes; # llndk
195 waggle; # apex
196 } VERSION_2;
197
198 VERSION_5 { # versioned=14
199 wobble;
200 } VERSION_4;
201 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700202 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
203 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700204 versions = parser.parse()
205
206 src_file = io.StringIO()
207 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700208 symbol_list_file = io.StringIO()
209 generator = ndkstubgen.Generator(src_file,
210 version_file, symbol_list_file,
211 Arch('arm'), 9, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700212 generator.write(versions)
213
214 expected_src = textwrap.dedent("""\
215 int foo = 0;
216 void baz() {}
217 void qux() {}
218 void wibble() {}
219 void wobble() {}
220 """)
221 self.assertEqual(expected_src, src_file.getvalue())
222
223 expected_version = textwrap.dedent("""\
224 VERSION_1 {
225 global:
226 foo;
227 };
228 VERSION_2 {
229 global:
230 baz;
231 } VERSION_1;
232 VERSION_4 {
233 global:
234 wibble;
235 } VERSION_2;
236 """)
237 self.assertEqual(expected_version, version_file.getvalue())
238
Dan Albertf1d14c72020-07-30 14:32:55 -0700239 expected_allowlist = textwrap.dedent("""\
240 [abi_symbol_list]
241 foo
242 baz
243 qux
244 wibble
245 wobble
246 """)
247 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
248
Dan Albertaf7b36d2020-06-23 11:21:21 -0700249 def test_integration_future_api(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700250 api_map = {
251 'O': 9000,
252 'P': 9001,
253 'Q': 9002,
254 }
255
256 input_file = io.StringIO(textwrap.dedent("""\
257 VERSION_1 {
258 global:
259 foo; # introduced=O
260 bar; # introduced=P
261 baz; # introduced=Q
262 local:
263 *;
264 };
265 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700266 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
267 9001, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700268 versions = parser.parse()
269
270 src_file = io.StringIO()
271 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700272 symbol_list_file = io.StringIO()
273 generator = ndkstubgen.Generator(src_file,
274 version_file, symbol_list_file,
275 Arch('arm'), 9001, False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700276 generator.write(versions)
277
278 expected_src = textwrap.dedent("""\
279 void foo() {}
280 void bar() {}
281 """)
282 self.assertEqual(expected_src, src_file.getvalue())
283
284 expected_version = textwrap.dedent("""\
285 VERSION_1 {
286 global:
287 foo;
288 bar;
289 };
290 """)
291 self.assertEqual(expected_version, version_file.getvalue())
292
Dan Albertf1d14c72020-07-30 14:32:55 -0700293 expected_allowlist = textwrap.dedent("""\
294 [abi_symbol_list]
295 foo
296 bar
297 """)
298 self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
299
Dan Albertaf7b36d2020-06-23 11:21:21 -0700300 def test_multiple_definition(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700301 input_file = io.StringIO(textwrap.dedent("""\
302 VERSION_1 {
303 global:
304 foo;
305 foo;
306 bar;
307 baz;
308 qux; # arm
309 local:
310 *;
311 };
312
313 VERSION_2 {
314 global:
315 bar;
316 qux; # arm64
317 } VERSION_1;
318
319 VERSION_PRIVATE {
320 global:
321 baz;
322 } VERSION_2;
323
324 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700325 parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
326 False, False)
Dan Albert06f58af2020-06-22 15:10:31 -0700327
328 with self.assertRaises(
329 symbolfile.MultiplyDefinedSymbolError) as ex_context:
330 parser.parse()
331 self.assertEqual(['bar', 'foo'],
332 ex_context.exception.multiply_defined_symbols)
333
Dan Albertaf7b36d2020-06-23 11:21:21 -0700334 def test_integration_with_apex(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700335 api_map = {
336 'O': 9000,
337 'P': 9001,
338 }
339
340 input_file = io.StringIO(textwrap.dedent("""\
341 VERSION_1 {
342 global:
343 foo; # var
344 bar; # x86
345 fizz; # introduced=O
346 buzz; # introduced=P
347 local:
348 *;
349 };
350
351 VERSION_2 { # arm
352 baz; # introduced=9
353 qux; # versioned=14
354 } VERSION_1;
355
356 VERSION_3 { # introduced=14
357 woodly;
358 doodly; # var
359 } VERSION_2;
360
361 VERSION_4 { # versioned=9
362 wibble;
363 wizzes; # llndk
364 waggle; # apex
365 bubble; # apex llndk
366 duddle; # llndk apex
367 } VERSION_2;
368
369 VERSION_5 { # versioned=14
370 wobble;
371 } VERSION_4;
372 """))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700373 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
374 9, False, True)
Dan Albert06f58af2020-06-22 15:10:31 -0700375 versions = parser.parse()
376
377 src_file = io.StringIO()
378 version_file = io.StringIO()
Dan Albertf1d14c72020-07-30 14:32:55 -0700379 symbol_list_file = io.StringIO()
380 generator = ndkstubgen.Generator(src_file,
381 version_file, symbol_list_file,
382 Arch('arm'), 9, False, True)
Dan Albert06f58af2020-06-22 15:10:31 -0700383 generator.write(versions)
384
385 expected_src = textwrap.dedent("""\
386 int foo = 0;
387 void baz() {}
388 void qux() {}
389 void wibble() {}
390 void waggle() {}
391 void bubble() {}
392 void duddle() {}
393 void wobble() {}
394 """)
395 self.assertEqual(expected_src, src_file.getvalue())
396
397 expected_version = textwrap.dedent("""\
398 VERSION_1 {
399 global:
400 foo;
401 };
402 VERSION_2 {
403 global:
404 baz;
405 } VERSION_1;
406 VERSION_4 {
407 global:
408 wibble;
409 waggle;
410 bubble;
411 duddle;
412 } VERSION_2;
413 """)
414 self.assertEqual(expected_version, version_file.getvalue())
415
Dan Albertaf7b36d2020-06-23 11:21:21 -0700416
417def main() -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700418 suite = unittest.TestLoader().loadTestsFromName(__name__)
419 unittest.TextTestRunner(verbosity=3).run(suite)
420
421
422if __name__ == '__main__':
423 main()