xref: /aosp_15_r20/build/soong/cc/ndkstubgen/test_ndkstubgen.py (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker#!/usr/bin/env python
2*333d2b36SAndroid Build Coastguard Worker#
3*333d2b36SAndroid Build Coastguard Worker# Copyright (C) 2016 The Android Open Source Project
4*333d2b36SAndroid Build Coastguard Worker#
5*333d2b36SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*333d2b36SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*333d2b36SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*333d2b36SAndroid Build Coastguard Worker#
9*333d2b36SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*333d2b36SAndroid Build Coastguard Worker#
11*333d2b36SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*333d2b36SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*333d2b36SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*333d2b36SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*333d2b36SAndroid Build Coastguard Worker# limitations under the License.
16*333d2b36SAndroid Build Coastguard Worker#
17*333d2b36SAndroid Build Coastguard Worker"""Tests for ndkstubgen.py."""
18*333d2b36SAndroid Build Coastguard Workerimport io
19*333d2b36SAndroid Build Coastguard Workerimport textwrap
20*333d2b36SAndroid Build Coastguard Workerimport unittest
21*333d2b36SAndroid Build Coastguard Workerfrom copy import copy
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Workerimport symbolfile
24*333d2b36SAndroid Build Coastguard Workerfrom symbolfile import Arch, Tags
25*333d2b36SAndroid Build Coastguard Worker
26*333d2b36SAndroid Build Coastguard Workerimport ndkstubgen
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Worker# pylint: disable=missing-docstring
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Workerclass GeneratorTest(unittest.TestCase):
33*333d2b36SAndroid Build Coastguard Worker    def setUp(self) -> None:
34*333d2b36SAndroid Build Coastguard Worker        self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Worker    def test_omit_version(self) -> None:
37*333d2b36SAndroid Build Coastguard Worker        # Thorough testing of the cases involved here is handled by
38*333d2b36SAndroid Build Coastguard Worker        # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
39*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
40*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
41*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
42*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
43*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file,
44*333d2b36SAndroid Build Coastguard Worker                                         self.filter)
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [
47*333d2b36SAndroid Build Coastguard Worker            symbolfile.Symbol('foo', Tags()),
48*333d2b36SAndroid Build Coastguard Worker        ])
49*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
50*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
51*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION', None, Tags.from_strs(['x86']),
54*333d2b36SAndroid Build Coastguard Worker                                     [
55*333d2b36SAndroid Build Coastguard Worker                                         symbolfile.Symbol('foo', Tags()),
56*333d2b36SAndroid Build Coastguard Worker                                     ])
57*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
58*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
59*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
60*333d2b36SAndroid Build Coastguard Worker
61*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION', None,
62*333d2b36SAndroid Build Coastguard Worker                                     Tags.from_strs(['introduced=14']), [
63*333d2b36SAndroid Build Coastguard Worker                                         symbolfile.Symbol('foo', Tags()),
64*333d2b36SAndroid Build Coastguard Worker                                     ])
65*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
66*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
67*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
68*333d2b36SAndroid Build Coastguard Worker
69*333d2b36SAndroid Build Coastguard Worker    def test_omit_symbol(self) -> None:
70*333d2b36SAndroid Build Coastguard Worker        # Thorough testing of the cases involved here is handled by
71*333d2b36SAndroid Build Coastguard Worker        # SymbolPresenceTest.
72*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
73*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
74*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
75*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
76*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file,
77*333d2b36SAndroid Build Coastguard Worker                                         self.filter)
78*333d2b36SAndroid Build Coastguard Worker
79*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION_1', None, Tags(), [
80*333d2b36SAndroid Build Coastguard Worker            symbolfile.Symbol('foo', Tags.from_strs(['x86'])),
81*333d2b36SAndroid Build Coastguard Worker        ])
82*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
83*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
84*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION_1', None, Tags(), [
87*333d2b36SAndroid Build Coastguard Worker            symbolfile.Symbol('foo', Tags.from_strs(['introduced=14'])),
88*333d2b36SAndroid Build Coastguard Worker        ])
89*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
90*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
91*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
92*333d2b36SAndroid Build Coastguard Worker
93*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION_1', None, Tags(), [
94*333d2b36SAndroid Build Coastguard Worker            symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
95*333d2b36SAndroid Build Coastguard Worker        ])
96*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
97*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
98*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
99*333d2b36SAndroid Build Coastguard Worker
100*333d2b36SAndroid Build Coastguard Worker        version = symbolfile.Version('VERSION_1', None, Tags(), [
101*333d2b36SAndroid Build Coastguard Worker            symbolfile.Symbol('foo', Tags.from_strs(['apex'])),
102*333d2b36SAndroid Build Coastguard Worker        ])
103*333d2b36SAndroid Build Coastguard Worker        generator.write_version(version)
104*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
105*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
106*333d2b36SAndroid Build Coastguard Worker
107*333d2b36SAndroid Build Coastguard Worker    def test_write(self) -> None:
108*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
109*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
110*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
111*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
112*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file,
113*333d2b36SAndroid Build Coastguard Worker                                         self.filter)
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Worker        versions = [
116*333d2b36SAndroid Build Coastguard Worker            symbolfile.Version('VERSION_1', None, Tags(), [
117*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('foo', Tags()),
118*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('bar', Tags.from_strs(['var'])),
119*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('woodly', Tags.from_strs(['weak'])),
120*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('doodly', Tags.from_strs(['weak', 'var'])),
121*333d2b36SAndroid Build Coastguard Worker            ]),
122*333d2b36SAndroid Build Coastguard Worker            symbolfile.Version('VERSION_2', 'VERSION_1', Tags(), [
123*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('baz', Tags()),
124*333d2b36SAndroid Build Coastguard Worker            ]),
125*333d2b36SAndroid Build Coastguard Worker            symbolfile.Version('VERSION_3', 'VERSION_1', Tags(), [
126*333d2b36SAndroid Build Coastguard Worker                symbolfile.Symbol('qux', Tags.from_strs(['versioned=14'])),
127*333d2b36SAndroid Build Coastguard Worker            ]),
128*333d2b36SAndroid Build Coastguard Worker        ]
129*333d2b36SAndroid Build Coastguard Worker
130*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
131*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
132*333d2b36SAndroid Build Coastguard Worker            void foo() {}
133*333d2b36SAndroid Build Coastguard Worker            int bar = 0;
134*333d2b36SAndroid Build Coastguard Worker            __attribute__((weak)) void woodly() {}
135*333d2b36SAndroid Build Coastguard Worker            __attribute__((weak)) int doodly = 0;
136*333d2b36SAndroid Build Coastguard Worker            void baz() {}
137*333d2b36SAndroid Build Coastguard Worker            void qux() {}
138*333d2b36SAndroid Build Coastguard Worker        """)
139*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
142*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
143*333d2b36SAndroid Build Coastguard Worker                global:
144*333d2b36SAndroid Build Coastguard Worker                    foo;
145*333d2b36SAndroid Build Coastguard Worker                    bar;
146*333d2b36SAndroid Build Coastguard Worker                    woodly;
147*333d2b36SAndroid Build Coastguard Worker                    doodly;
148*333d2b36SAndroid Build Coastguard Worker            };
149*333d2b36SAndroid Build Coastguard Worker            VERSION_2 {
150*333d2b36SAndroid Build Coastguard Worker                global:
151*333d2b36SAndroid Build Coastguard Worker                    baz;
152*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
153*333d2b36SAndroid Build Coastguard Worker        """)
154*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
155*333d2b36SAndroid Build Coastguard Worker
156*333d2b36SAndroid Build Coastguard Worker        expected_allowlist = textwrap.dedent("""\
157*333d2b36SAndroid Build Coastguard Worker            [abi_symbol_list]
158*333d2b36SAndroid Build Coastguard Worker            foo
159*333d2b36SAndroid Build Coastguard Worker            bar
160*333d2b36SAndroid Build Coastguard Worker            woodly
161*333d2b36SAndroid Build Coastguard Worker            doodly
162*333d2b36SAndroid Build Coastguard Worker            baz
163*333d2b36SAndroid Build Coastguard Worker            qux
164*333d2b36SAndroid Build Coastguard Worker        """)
165*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
166*333d2b36SAndroid Build Coastguard Worker
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Workerclass IntegrationTest(unittest.TestCase):
169*333d2b36SAndroid Build Coastguard Worker    def setUp(self) -> None:
170*333d2b36SAndroid Build Coastguard Worker        self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
171*333d2b36SAndroid Build Coastguard Worker
172*333d2b36SAndroid Build Coastguard Worker    def test_integration(self) -> None:
173*333d2b36SAndroid Build Coastguard Worker        api_map = {
174*333d2b36SAndroid Build Coastguard Worker            'O': 9000,
175*333d2b36SAndroid Build Coastguard Worker            'P': 9001,
176*333d2b36SAndroid Build Coastguard Worker        }
177*333d2b36SAndroid Build Coastguard Worker
178*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
179*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
180*333d2b36SAndroid Build Coastguard Worker                global:
181*333d2b36SAndroid Build Coastguard Worker                    foo; # var
182*333d2b36SAndroid Build Coastguard Worker                    bar; # x86
183*333d2b36SAndroid Build Coastguard Worker                    fizz; # introduced=O
184*333d2b36SAndroid Build Coastguard Worker                    buzz; # introduced=P
185*333d2b36SAndroid Build Coastguard Worker                local:
186*333d2b36SAndroid Build Coastguard Worker                    *;
187*333d2b36SAndroid Build Coastguard Worker            };
188*333d2b36SAndroid Build Coastguard Worker
189*333d2b36SAndroid Build Coastguard Worker            VERSION_2 { # arm
190*333d2b36SAndroid Build Coastguard Worker                baz; # introduced=9
191*333d2b36SAndroid Build Coastguard Worker                qux; # versioned=14
192*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
193*333d2b36SAndroid Build Coastguard Worker
194*333d2b36SAndroid Build Coastguard Worker            VERSION_3 { # introduced=14
195*333d2b36SAndroid Build Coastguard Worker                woodly;
196*333d2b36SAndroid Build Coastguard Worker                doodly; # var
197*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
198*333d2b36SAndroid Build Coastguard Worker
199*333d2b36SAndroid Build Coastguard Worker            VERSION_4 { # versioned=9
200*333d2b36SAndroid Build Coastguard Worker                wibble;
201*333d2b36SAndroid Build Coastguard Worker                wizzes; # llndk
202*333d2b36SAndroid Build Coastguard Worker                waggle; # apex
203*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
204*333d2b36SAndroid Build Coastguard Worker
205*333d2b36SAndroid Build Coastguard Worker            VERSION_5 { # versioned=14
206*333d2b36SAndroid Build Coastguard Worker                wobble;
207*333d2b36SAndroid Build Coastguard Worker            } VERSION_4;
208*333d2b36SAndroid Build Coastguard Worker        """))
209*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, api_map, self.filter)
210*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
211*333d2b36SAndroid Build Coastguard Worker
212*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
213*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
214*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
215*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
216*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file,
217*333d2b36SAndroid Build Coastguard Worker                                         self.filter)
218*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
219*333d2b36SAndroid Build Coastguard Worker
220*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
221*333d2b36SAndroid Build Coastguard Worker            int foo = 0;
222*333d2b36SAndroid Build Coastguard Worker            void baz() {}
223*333d2b36SAndroid Build Coastguard Worker            void qux() {}
224*333d2b36SAndroid Build Coastguard Worker            void wibble() {}
225*333d2b36SAndroid Build Coastguard Worker            void wobble() {}
226*333d2b36SAndroid Build Coastguard Worker        """)
227*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
228*333d2b36SAndroid Build Coastguard Worker
229*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
230*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
231*333d2b36SAndroid Build Coastguard Worker                global:
232*333d2b36SAndroid Build Coastguard Worker                    foo;
233*333d2b36SAndroid Build Coastguard Worker            };
234*333d2b36SAndroid Build Coastguard Worker            VERSION_2 {
235*333d2b36SAndroid Build Coastguard Worker                global:
236*333d2b36SAndroid Build Coastguard Worker                    baz;
237*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
238*333d2b36SAndroid Build Coastguard Worker            VERSION_4 {
239*333d2b36SAndroid Build Coastguard Worker                global:
240*333d2b36SAndroid Build Coastguard Worker                    wibble;
241*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
242*333d2b36SAndroid Build Coastguard Worker        """)
243*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Worker        expected_allowlist = textwrap.dedent("""\
246*333d2b36SAndroid Build Coastguard Worker            [abi_symbol_list]
247*333d2b36SAndroid Build Coastguard Worker            foo
248*333d2b36SAndroid Build Coastguard Worker            baz
249*333d2b36SAndroid Build Coastguard Worker            qux
250*333d2b36SAndroid Build Coastguard Worker            wibble
251*333d2b36SAndroid Build Coastguard Worker            wobble
252*333d2b36SAndroid Build Coastguard Worker        """)
253*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
254*333d2b36SAndroid Build Coastguard Worker
255*333d2b36SAndroid Build Coastguard Worker    def test_integration_future_api(self) -> None:
256*333d2b36SAndroid Build Coastguard Worker        api_map = {
257*333d2b36SAndroid Build Coastguard Worker            'O': 9000,
258*333d2b36SAndroid Build Coastguard Worker            'P': 9001,
259*333d2b36SAndroid Build Coastguard Worker            'Q': 9002,
260*333d2b36SAndroid Build Coastguard Worker        }
261*333d2b36SAndroid Build Coastguard Worker
262*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
263*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
264*333d2b36SAndroid Build Coastguard Worker                global:
265*333d2b36SAndroid Build Coastguard Worker                    foo; # introduced=O
266*333d2b36SAndroid Build Coastguard Worker                    bar; # introduced=P
267*333d2b36SAndroid Build Coastguard Worker                    baz; # introduced=Q
268*333d2b36SAndroid Build Coastguard Worker                local:
269*333d2b36SAndroid Build Coastguard Worker                    *;
270*333d2b36SAndroid Build Coastguard Worker            };
271*333d2b36SAndroid Build Coastguard Worker        """))
272*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
273*333d2b36SAndroid Build Coastguard Worker        f.api = 9001
274*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, api_map, f)
275*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
276*333d2b36SAndroid Build Coastguard Worker
277*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
278*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
279*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
280*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
281*333d2b36SAndroid Build Coastguard Worker        f.api = 9001
282*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
283*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file, f)
284*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
285*333d2b36SAndroid Build Coastguard Worker
286*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
287*333d2b36SAndroid Build Coastguard Worker            void foo() {}
288*333d2b36SAndroid Build Coastguard Worker            void bar() {}
289*333d2b36SAndroid Build Coastguard Worker        """)
290*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
291*333d2b36SAndroid Build Coastguard Worker
292*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
293*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
294*333d2b36SAndroid Build Coastguard Worker                global:
295*333d2b36SAndroid Build Coastguard Worker                    foo;
296*333d2b36SAndroid Build Coastguard Worker                    bar;
297*333d2b36SAndroid Build Coastguard Worker            };
298*333d2b36SAndroid Build Coastguard Worker        """)
299*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
300*333d2b36SAndroid Build Coastguard Worker
301*333d2b36SAndroid Build Coastguard Worker        expected_allowlist = textwrap.dedent("""\
302*333d2b36SAndroid Build Coastguard Worker            [abi_symbol_list]
303*333d2b36SAndroid Build Coastguard Worker            foo
304*333d2b36SAndroid Build Coastguard Worker            bar
305*333d2b36SAndroid Build Coastguard Worker        """)
306*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
307*333d2b36SAndroid Build Coastguard Worker
308*333d2b36SAndroid Build Coastguard Worker    def test_multiple_definition(self) -> None:
309*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
310*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
311*333d2b36SAndroid Build Coastguard Worker                global:
312*333d2b36SAndroid Build Coastguard Worker                    foo;
313*333d2b36SAndroid Build Coastguard Worker                    foo;
314*333d2b36SAndroid Build Coastguard Worker                    bar;
315*333d2b36SAndroid Build Coastguard Worker                    baz;
316*333d2b36SAndroid Build Coastguard Worker                    qux; # arm
317*333d2b36SAndroid Build Coastguard Worker                local:
318*333d2b36SAndroid Build Coastguard Worker                    *;
319*333d2b36SAndroid Build Coastguard Worker            };
320*333d2b36SAndroid Build Coastguard Worker
321*333d2b36SAndroid Build Coastguard Worker            VERSION_2 {
322*333d2b36SAndroid Build Coastguard Worker                global:
323*333d2b36SAndroid Build Coastguard Worker                    bar;
324*333d2b36SAndroid Build Coastguard Worker                    qux; # arm64
325*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
326*333d2b36SAndroid Build Coastguard Worker
327*333d2b36SAndroid Build Coastguard Worker            VERSION_PRIVATE {
328*333d2b36SAndroid Build Coastguard Worker                global:
329*333d2b36SAndroid Build Coastguard Worker                    baz;
330*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
331*333d2b36SAndroid Build Coastguard Worker
332*333d2b36SAndroid Build Coastguard Worker        """))
333*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
334*333d2b36SAndroid Build Coastguard Worker        f.api = 16
335*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, {}, f)
336*333d2b36SAndroid Build Coastguard Worker
337*333d2b36SAndroid Build Coastguard Worker        with self.assertRaises(
338*333d2b36SAndroid Build Coastguard Worker                symbolfile.MultiplyDefinedSymbolError) as ex_context:
339*333d2b36SAndroid Build Coastguard Worker            parser.parse()
340*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(['bar', 'foo'],
341*333d2b36SAndroid Build Coastguard Worker                         ex_context.exception.multiply_defined_symbols)
342*333d2b36SAndroid Build Coastguard Worker
343*333d2b36SAndroid Build Coastguard Worker    def test_integration_with_apex(self) -> None:
344*333d2b36SAndroid Build Coastguard Worker        api_map = {
345*333d2b36SAndroid Build Coastguard Worker            'O': 9000,
346*333d2b36SAndroid Build Coastguard Worker            'P': 9001,
347*333d2b36SAndroid Build Coastguard Worker        }
348*333d2b36SAndroid Build Coastguard Worker
349*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
350*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
351*333d2b36SAndroid Build Coastguard Worker                global:
352*333d2b36SAndroid Build Coastguard Worker                    foo; # var
353*333d2b36SAndroid Build Coastguard Worker                    bar; # x86
354*333d2b36SAndroid Build Coastguard Worker                    fizz; # introduced=O
355*333d2b36SAndroid Build Coastguard Worker                    buzz; # introduced=P
356*333d2b36SAndroid Build Coastguard Worker                local:
357*333d2b36SAndroid Build Coastguard Worker                    *;
358*333d2b36SAndroid Build Coastguard Worker            };
359*333d2b36SAndroid Build Coastguard Worker
360*333d2b36SAndroid Build Coastguard Worker            VERSION_2 { # arm
361*333d2b36SAndroid Build Coastguard Worker                baz; # introduced=9
362*333d2b36SAndroid Build Coastguard Worker                qux; # versioned=14
363*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
364*333d2b36SAndroid Build Coastguard Worker
365*333d2b36SAndroid Build Coastguard Worker            VERSION_3 { # introduced=14
366*333d2b36SAndroid Build Coastguard Worker                woodly;
367*333d2b36SAndroid Build Coastguard Worker                doodly; # var
368*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
369*333d2b36SAndroid Build Coastguard Worker
370*333d2b36SAndroid Build Coastguard Worker            VERSION_4 { # versioned=9
371*333d2b36SAndroid Build Coastguard Worker                wibble;
372*333d2b36SAndroid Build Coastguard Worker                wizzes; # llndk
373*333d2b36SAndroid Build Coastguard Worker                waggle; # apex
374*333d2b36SAndroid Build Coastguard Worker                bubble; # apex llndk
375*333d2b36SAndroid Build Coastguard Worker                duddle; # llndk apex
376*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
377*333d2b36SAndroid Build Coastguard Worker
378*333d2b36SAndroid Build Coastguard Worker            VERSION_5 { # versioned=14
379*333d2b36SAndroid Build Coastguard Worker                wobble;
380*333d2b36SAndroid Build Coastguard Worker            } VERSION_4;
381*333d2b36SAndroid Build Coastguard Worker        """))
382*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
383*333d2b36SAndroid Build Coastguard Worker        f.apex = True
384*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, api_map, f)
385*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
386*333d2b36SAndroid Build Coastguard Worker
387*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
388*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
389*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
390*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
391*333d2b36SAndroid Build Coastguard Worker        f.apex = True
392*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
393*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file, f)
394*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
395*333d2b36SAndroid Build Coastguard Worker
396*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
397*333d2b36SAndroid Build Coastguard Worker            int foo = 0;
398*333d2b36SAndroid Build Coastguard Worker            void baz() {}
399*333d2b36SAndroid Build Coastguard Worker            void qux() {}
400*333d2b36SAndroid Build Coastguard Worker            void wibble() {}
401*333d2b36SAndroid Build Coastguard Worker            void waggle() {}
402*333d2b36SAndroid Build Coastguard Worker            void bubble() {}
403*333d2b36SAndroid Build Coastguard Worker            void duddle() {}
404*333d2b36SAndroid Build Coastguard Worker            void wobble() {}
405*333d2b36SAndroid Build Coastguard Worker        """)
406*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
407*333d2b36SAndroid Build Coastguard Worker
408*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
409*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
410*333d2b36SAndroid Build Coastguard Worker                global:
411*333d2b36SAndroid Build Coastguard Worker                    foo;
412*333d2b36SAndroid Build Coastguard Worker            };
413*333d2b36SAndroid Build Coastguard Worker            VERSION_2 {
414*333d2b36SAndroid Build Coastguard Worker                global:
415*333d2b36SAndroid Build Coastguard Worker                    baz;
416*333d2b36SAndroid Build Coastguard Worker            } VERSION_1;
417*333d2b36SAndroid Build Coastguard Worker            VERSION_4 {
418*333d2b36SAndroid Build Coastguard Worker                global:
419*333d2b36SAndroid Build Coastguard Worker                    wibble;
420*333d2b36SAndroid Build Coastguard Worker                    waggle;
421*333d2b36SAndroid Build Coastguard Worker                    bubble;
422*333d2b36SAndroid Build Coastguard Worker                    duddle;
423*333d2b36SAndroid Build Coastguard Worker            } VERSION_2;
424*333d2b36SAndroid Build Coastguard Worker        """)
425*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
426*333d2b36SAndroid Build Coastguard Worker
427*333d2b36SAndroid Build Coastguard Worker    def test_integration_with_nondk(self) -> None:
428*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
429*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
430*333d2b36SAndroid Build Coastguard Worker                global:
431*333d2b36SAndroid Build Coastguard Worker                    foo;
432*333d2b36SAndroid Build Coastguard Worker                    bar; # apex
433*333d2b36SAndroid Build Coastguard Worker                local:
434*333d2b36SAndroid Build Coastguard Worker                    *;
435*333d2b36SAndroid Build Coastguard Worker            };
436*333d2b36SAndroid Build Coastguard Worker        """))
437*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
438*333d2b36SAndroid Build Coastguard Worker        f.apex = True
439*333d2b36SAndroid Build Coastguard Worker        f.ndk = False   # ndk symbols should be excluded
440*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, {}, f)
441*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
442*333d2b36SAndroid Build Coastguard Worker
443*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
444*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
445*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
446*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
447*333d2b36SAndroid Build Coastguard Worker        f.apex = True
448*333d2b36SAndroid Build Coastguard Worker        f.ndk = False   # ndk symbols should be excluded
449*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
450*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file, f)
451*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
452*333d2b36SAndroid Build Coastguard Worker
453*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
454*333d2b36SAndroid Build Coastguard Worker            void bar() {}
455*333d2b36SAndroid Build Coastguard Worker        """)
456*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
457*333d2b36SAndroid Build Coastguard Worker
458*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
459*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
460*333d2b36SAndroid Build Coastguard Worker                global:
461*333d2b36SAndroid Build Coastguard Worker                    bar;
462*333d2b36SAndroid Build Coastguard Worker            };
463*333d2b36SAndroid Build Coastguard Worker        """)
464*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
465*333d2b36SAndroid Build Coastguard Worker
466*333d2b36SAndroid Build Coastguard Worker    def test_integration_with_llndk(self) -> None:
467*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
468*333d2b36SAndroid Build Coastguard Worker            VERSION_34 { # introduced=34
469*333d2b36SAndroid Build Coastguard Worker                global:
470*333d2b36SAndroid Build Coastguard Worker                    foo;
471*333d2b36SAndroid Build Coastguard Worker                    bar; # llndk
472*333d2b36SAndroid Build Coastguard Worker            };
473*333d2b36SAndroid Build Coastguard Worker            VERSION_35 { # introduced=35
474*333d2b36SAndroid Build Coastguard Worker                global:
475*333d2b36SAndroid Build Coastguard Worker                    wiggle;
476*333d2b36SAndroid Build Coastguard Worker                    waggle; # llndk
477*333d2b36SAndroid Build Coastguard Worker            } VERSION_34;
478*333d2b36SAndroid Build Coastguard Worker            VERSION_36 { # introduced=36
479*333d2b36SAndroid Build Coastguard Worker                global:
480*333d2b36SAndroid Build Coastguard Worker                    abc;
481*333d2b36SAndroid Build Coastguard Worker                    xyz; # llndk
482*333d2b36SAndroid Build Coastguard Worker            } VERSION_35;
483*333d2b36SAndroid Build Coastguard Worker        """))
484*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
485*333d2b36SAndroid Build Coastguard Worker        f.llndk = True
486*333d2b36SAndroid Build Coastguard Worker        f.api = 35
487*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, {}, f)
488*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
489*333d2b36SAndroid Build Coastguard Worker
490*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
491*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
492*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
493*333d2b36SAndroid Build Coastguard Worker
494*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
495*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file, f)
496*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
497*333d2b36SAndroid Build Coastguard Worker
498*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
499*333d2b36SAndroid Build Coastguard Worker            void foo() {}
500*333d2b36SAndroid Build Coastguard Worker            void bar() {}
501*333d2b36SAndroid Build Coastguard Worker            void wiggle() {}
502*333d2b36SAndroid Build Coastguard Worker            void waggle() {}
503*333d2b36SAndroid Build Coastguard Worker        """)
504*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
505*333d2b36SAndroid Build Coastguard Worker
506*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
507*333d2b36SAndroid Build Coastguard Worker            VERSION_34 {
508*333d2b36SAndroid Build Coastguard Worker                global:
509*333d2b36SAndroid Build Coastguard Worker                    foo;
510*333d2b36SAndroid Build Coastguard Worker                    bar;
511*333d2b36SAndroid Build Coastguard Worker            };
512*333d2b36SAndroid Build Coastguard Worker            VERSION_35 {
513*333d2b36SAndroid Build Coastguard Worker                global:
514*333d2b36SAndroid Build Coastguard Worker                    wiggle;
515*333d2b36SAndroid Build Coastguard Worker                    waggle;
516*333d2b36SAndroid Build Coastguard Worker            } VERSION_34;
517*333d2b36SAndroid Build Coastguard Worker        """)
518*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
519*333d2b36SAndroid Build Coastguard Worker
520*333d2b36SAndroid Build Coastguard Worker    def test_integration_with_llndk_with_single_version_block(self) -> None:
521*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
522*333d2b36SAndroid Build Coastguard Worker            LIBANDROID {
523*333d2b36SAndroid Build Coastguard Worker                global:
524*333d2b36SAndroid Build Coastguard Worker                    foo; # introduced=34
525*333d2b36SAndroid Build Coastguard Worker                    bar; # introduced=35 llndk
526*333d2b36SAndroid Build Coastguard Worker                    baz; # introduced=V
527*333d2b36SAndroid Build Coastguard Worker                    qux; # introduced=36
528*333d2b36SAndroid Build Coastguard Worker            };
529*333d2b36SAndroid Build Coastguard Worker        """))
530*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
531*333d2b36SAndroid Build Coastguard Worker        f.llndk = True
532*333d2b36SAndroid Build Coastguard Worker        f.api = 35
533*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, {'V': 35}, f)
534*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
535*333d2b36SAndroid Build Coastguard Worker
536*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
537*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
538*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
539*333d2b36SAndroid Build Coastguard Worker
540*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
541*333d2b36SAndroid Build Coastguard Worker                                         version_file, symbol_list_file, f)
542*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
543*333d2b36SAndroid Build Coastguard Worker
544*333d2b36SAndroid Build Coastguard Worker        expected_src = textwrap.dedent("""\
545*333d2b36SAndroid Build Coastguard Worker            void foo() {}
546*333d2b36SAndroid Build Coastguard Worker            void bar() {}
547*333d2b36SAndroid Build Coastguard Worker            void baz() {}
548*333d2b36SAndroid Build Coastguard Worker        """)
549*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_src, src_file.getvalue())
550*333d2b36SAndroid Build Coastguard Worker
551*333d2b36SAndroid Build Coastguard Worker        expected_version = textwrap.dedent("""\
552*333d2b36SAndroid Build Coastguard Worker            LIBANDROID {
553*333d2b36SAndroid Build Coastguard Worker                global:
554*333d2b36SAndroid Build Coastguard Worker                    foo;
555*333d2b36SAndroid Build Coastguard Worker                    bar;
556*333d2b36SAndroid Build Coastguard Worker                    baz;
557*333d2b36SAndroid Build Coastguard Worker            };
558*333d2b36SAndroid Build Coastguard Worker        """)
559*333d2b36SAndroid Build Coastguard Worker        self.assertEqual(expected_version, version_file.getvalue())
560*333d2b36SAndroid Build Coastguard Worker
561*333d2b36SAndroid Build Coastguard Worker    def test_empty_stub(self) -> None:
562*333d2b36SAndroid Build Coastguard Worker        """Tests that empty stubs can be generated.
563*333d2b36SAndroid Build Coastguard Worker
564*333d2b36SAndroid Build Coastguard Worker        This is not a common case, but libraries whose only behavior is to
565*333d2b36SAndroid Build Coastguard Worker        interpose symbols to alter existing behavior do not need to expose
566*333d2b36SAndroid Build Coastguard Worker        their interposing symbols as API, so it's possible for the stub to be
567*333d2b36SAndroid Build Coastguard Worker        empty while still needing a stub to link against. libsigchain is an
568*333d2b36SAndroid Build Coastguard Worker        example of this.
569*333d2b36SAndroid Build Coastguard Worker        """
570*333d2b36SAndroid Build Coastguard Worker        input_file = io.StringIO(textwrap.dedent("""\
571*333d2b36SAndroid Build Coastguard Worker            VERSION_1 {
572*333d2b36SAndroid Build Coastguard Worker                local:
573*333d2b36SAndroid Build Coastguard Worker                    *;
574*333d2b36SAndroid Build Coastguard Worker            };
575*333d2b36SAndroid Build Coastguard Worker        """))
576*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
577*333d2b36SAndroid Build Coastguard Worker        f.apex = True
578*333d2b36SAndroid Build Coastguard Worker        parser = symbolfile.SymbolFileParser(input_file, {}, f)
579*333d2b36SAndroid Build Coastguard Worker        versions = parser.parse()
580*333d2b36SAndroid Build Coastguard Worker
581*333d2b36SAndroid Build Coastguard Worker        src_file = io.StringIO()
582*333d2b36SAndroid Build Coastguard Worker        version_file = io.StringIO()
583*333d2b36SAndroid Build Coastguard Worker        symbol_list_file = io.StringIO()
584*333d2b36SAndroid Build Coastguard Worker        f = copy(self.filter)
585*333d2b36SAndroid Build Coastguard Worker        f.apex = True
586*333d2b36SAndroid Build Coastguard Worker        generator = ndkstubgen.Generator(src_file,
587*333d2b36SAndroid Build Coastguard Worker                                         version_file,
588*333d2b36SAndroid Build Coastguard Worker                                         symbol_list_file, f)
589*333d2b36SAndroid Build Coastguard Worker        generator.write(versions)
590*333d2b36SAndroid Build Coastguard Worker
591*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', src_file.getvalue())
592*333d2b36SAndroid Build Coastguard Worker        self.assertEqual('', version_file.getvalue())
593*333d2b36SAndroid Build Coastguard Worker
594*333d2b36SAndroid Build Coastguard Worker
595*333d2b36SAndroid Build Coastguard Workerdef main() -> None:
596*333d2b36SAndroid Build Coastguard Worker    suite = unittest.TestLoader().loadTestsFromName(__name__)
597*333d2b36SAndroid Build Coastguard Worker    unittest.TextTestRunner(verbosity=3).run(suite)
598*333d2b36SAndroid Build Coastguard Worker
599*333d2b36SAndroid Build Coastguard Worker
600*333d2b36SAndroid Build Coastguard Workerif __name__ == '__main__':
601*333d2b36SAndroid Build Coastguard Worker    main()
602