blob: 856b9d76b74540504e6e40e6814119755766213a [file] [log] [blame]
Dan Albert06f58af2020-06-22 15:10:31 -07001#
2# Copyright (C) 2016 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16"""Tests for symbolfile."""
17import io
18import textwrap
19import unittest
20
21import symbolfile
Jiyong Park3f9c41d2022-07-16 23:30:09 +090022from symbolfile import Arch, Tag, Tags, Version, Symbol, Filter
23from copy import copy
Dan Albert06f58af2020-06-22 15:10:31 -070024
25# pylint: disable=missing-docstring
26
27
28class DecodeApiLevelTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -070029 def test_decode_api_level(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070030 self.assertEqual(9, symbolfile.decode_api_level('9', {}))
31 self.assertEqual(9000, symbolfile.decode_api_level('O', {'O': 9000}))
32
33 with self.assertRaises(KeyError):
34 symbolfile.decode_api_level('O', {})
35
36
37class TagsTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -070038 def test_get_tags_no_tags(self) -> None:
Dan Albertead21552021-06-04 14:30:40 -070039 self.assertEqual(Tags(), symbolfile.get_tags('', {}))
40 self.assertEqual(Tags(), symbolfile.get_tags('foo bar baz', {}))
Dan Albert06f58af2020-06-22 15:10:31 -070041
Dan Albertaf7b36d2020-06-23 11:21:21 -070042 def test_get_tags(self) -> None:
Dan Albertead21552021-06-04 14:30:40 -070043 self.assertEqual(Tags.from_strs(['foo', 'bar']),
44 symbolfile.get_tags('# foo bar', {}))
45 self.assertEqual(Tags.from_strs(['bar', 'baz']),
46 symbolfile.get_tags('foo # bar baz', {}))
Dan Albert06f58af2020-06-22 15:10:31 -070047
Dan Albertaf7b36d2020-06-23 11:21:21 -070048 def test_split_tag(self) -> None:
49 self.assertTupleEqual(('foo', 'bar'),
50 symbolfile.split_tag(Tag('foo=bar')))
51 self.assertTupleEqual(('foo', 'bar=baz'),
52 symbolfile.split_tag(Tag('foo=bar=baz')))
Dan Albert06f58af2020-06-22 15:10:31 -070053 with self.assertRaises(ValueError):
Dan Albertaf7b36d2020-06-23 11:21:21 -070054 symbolfile.split_tag(Tag('foo'))
Dan Albert06f58af2020-06-22 15:10:31 -070055
Dan Albertaf7b36d2020-06-23 11:21:21 -070056 def test_get_tag_value(self) -> None:
57 self.assertEqual('bar', symbolfile.get_tag_value(Tag('foo=bar')))
58 self.assertEqual('bar=baz',
59 symbolfile.get_tag_value(Tag('foo=bar=baz')))
Dan Albert06f58af2020-06-22 15:10:31 -070060 with self.assertRaises(ValueError):
Dan Albertaf7b36d2020-06-23 11:21:21 -070061 symbolfile.get_tag_value(Tag('foo'))
Dan Albert06f58af2020-06-22 15:10:31 -070062
Dan Albertaf7b36d2020-06-23 11:21:21 -070063 def test_is_api_level_tag(self) -> None:
64 self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced=24')))
65 self.assertTrue(symbolfile.is_api_level_tag(Tag('introduced-arm=24')))
66 self.assertTrue(symbolfile.is_api_level_tag(Tag('versioned=24')))
Dan Albert06f58af2020-06-22 15:10:31 -070067
68 # Shouldn't try to process things that aren't a key/value tag.
Dan Albertaf7b36d2020-06-23 11:21:21 -070069 self.assertFalse(symbolfile.is_api_level_tag(Tag('arm')))
70 self.assertFalse(symbolfile.is_api_level_tag(Tag('introduced')))
71 self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned')))
Dan Albert06f58af2020-06-22 15:10:31 -070072
73 # We don't support arch specific `versioned` tags.
Dan Albertaf7b36d2020-06-23 11:21:21 -070074 self.assertFalse(symbolfile.is_api_level_tag(Tag('versioned-arm=24')))
Dan Albert06f58af2020-06-22 15:10:31 -070075
Dan Albertaf7b36d2020-06-23 11:21:21 -070076 def test_decode_api_level_tags(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -070077 api_map = {
78 'O': 9000,
79 'P': 9001,
80 }
81
82 tags = [
Dan Albertead21552021-06-04 14:30:40 -070083 symbolfile.decode_api_level_tag(t, api_map) for t in (
84 Tag('introduced=9'),
85 Tag('introduced-arm=14'),
86 Tag('versioned=16'),
87 Tag('arm'),
88 Tag('introduced=O'),
89 Tag('introduced=P'),
90 )
Dan Albert06f58af2020-06-22 15:10:31 -070091 ]
92 expected_tags = [
Dan Albertaf7b36d2020-06-23 11:21:21 -070093 Tag('introduced=9'),
94 Tag('introduced-arm=14'),
95 Tag('versioned=16'),
96 Tag('arm'),
97 Tag('introduced=9000'),
98 Tag('introduced=9001'),
Dan Albert06f58af2020-06-22 15:10:31 -070099 ]
Dan Albertead21552021-06-04 14:30:40 -0700100 self.assertListEqual(expected_tags, tags)
Dan Albert06f58af2020-06-22 15:10:31 -0700101
102 with self.assertRaises(symbolfile.ParseError):
Dan Albertead21552021-06-04 14:30:40 -0700103 symbolfile.decode_api_level_tag(Tag('introduced=O'), {})
Dan Albert06f58af2020-06-22 15:10:31 -0700104
105
106class PrivateVersionTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -0700107 def test_version_is_private(self) -> None:
Dan Albertead21552021-06-04 14:30:40 -0700108 def mock_version(name: str) -> Version:
109 return Version(name, base=None, tags=Tags(), symbols=[])
Dan Albert06f58af2020-06-22 15:10:31 -0700110
Dan Albertead21552021-06-04 14:30:40 -0700111 self.assertFalse(mock_version('foo').is_private)
112 self.assertFalse(mock_version('PRIVATE').is_private)
113 self.assertFalse(mock_version('PLATFORM').is_private)
114 self.assertFalse(mock_version('foo_private').is_private)
115 self.assertFalse(mock_version('foo_platform').is_private)
116 self.assertFalse(mock_version('foo_PRIVATE_').is_private)
117 self.assertFalse(mock_version('foo_PLATFORM_').is_private)
118
119 self.assertTrue(mock_version('foo_PRIVATE').is_private)
120 self.assertTrue(mock_version('foo_PLATFORM').is_private)
Dan Albert06f58af2020-06-22 15:10:31 -0700121
122
123class SymbolPresenceTest(unittest.TestCase):
Dan Albertaf7b36d2020-06-23 11:21:21 -0700124 def test_symbol_in_arch(self) -> None:
Dan Albertead21552021-06-04 14:30:40 -0700125 self.assertTrue(symbolfile.symbol_in_arch(Tags(), Arch('arm')))
126 self.assertTrue(
127 symbolfile.symbol_in_arch(Tags.from_strs(['arm']), Arch('arm')))
Dan Albert06f58af2020-06-22 15:10:31 -0700128
Dan Albertead21552021-06-04 14:30:40 -0700129 self.assertFalse(
130 symbolfile.symbol_in_arch(Tags.from_strs(['x86']), Arch('arm')))
Dan Albert06f58af2020-06-22 15:10:31 -0700131
Dan Albertaf7b36d2020-06-23 11:21:21 -0700132 def test_symbol_in_api(self) -> None:
133 self.assertTrue(symbolfile.symbol_in_api([], Arch('arm'), 9))
134 self.assertTrue(
135 symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 9))
136 self.assertTrue(
137 symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 14))
138 self.assertTrue(
139 symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
140 14))
141 self.assertTrue(
142 symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
143 14))
144 self.assertTrue(
145 symbolfile.symbol_in_api([Tag('introduced-x86=14')], Arch('arm'),
146 9))
147 self.assertTrue(
148 symbolfile.symbol_in_api(
149 [Tag('introduced-arm=9'),
150 Tag('introduced-x86=21')], Arch('arm'), 14))
151 self.assertTrue(
152 symbolfile.symbol_in_api(
153 [Tag('introduced=9'),
154 Tag('introduced-x86=21')], Arch('arm'), 14))
155 self.assertTrue(
156 symbolfile.symbol_in_api(
157 [Tag('introduced=21'),
158 Tag('introduced-arm=9')], Arch('arm'), 14))
159 self.assertTrue(
160 symbolfile.symbol_in_api([Tag('future')], Arch('arm'),
161 symbolfile.FUTURE_API_LEVEL))
Dan Albert06f58af2020-06-22 15:10:31 -0700162
Dan Albertaf7b36d2020-06-23 11:21:21 -0700163 self.assertFalse(
164 symbolfile.symbol_in_api([Tag('introduced=14')], Arch('arm'), 9))
165 self.assertFalse(
166 symbolfile.symbol_in_api([Tag('introduced-arm=14')], Arch('arm'),
167 9))
168 self.assertFalse(
169 symbolfile.symbol_in_api([Tag('future')], Arch('arm'), 9))
170 self.assertFalse(
171 symbolfile.symbol_in_api(
172 [Tag('introduced=9'), Tag('future')], Arch('arm'), 14))
173 self.assertFalse(
174 symbolfile.symbol_in_api([Tag('introduced-arm=9'),
175 Tag('future')], Arch('arm'), 14))
176 self.assertFalse(
177 symbolfile.symbol_in_api(
178 [Tag('introduced-arm=21'),
179 Tag('introduced-x86=9')], Arch('arm'), 14))
180 self.assertFalse(
181 symbolfile.symbol_in_api(
182 [Tag('introduced=9'),
183 Tag('introduced-arm=21')], Arch('arm'), 14))
184 self.assertFalse(
185 symbolfile.symbol_in_api(
186 [Tag('introduced=21'),
187 Tag('introduced-x86=9')], Arch('arm'), 14))
Dan Albert06f58af2020-06-22 15:10:31 -0700188
189 # Interesting edge case: this symbol should be omitted from the
190 # library, but this call should still return true because none of the
191 # tags indiciate that it's not present in this API level.
Dan Albertaf7b36d2020-06-23 11:21:21 -0700192 self.assertTrue(symbolfile.symbol_in_api([Tag('x86')], Arch('arm'), 9))
Dan Albert06f58af2020-06-22 15:10:31 -0700193
Dan Albertaf7b36d2020-06-23 11:21:21 -0700194 def test_verioned_in_api(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700195 self.assertTrue(symbolfile.symbol_versioned_in_api([], 9))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700196 self.assertTrue(
197 symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 9))
198 self.assertTrue(
199 symbolfile.symbol_versioned_in_api([Tag('versioned=9')], 14))
Dan Albert06f58af2020-06-22 15:10:31 -0700200
Dan Albertaf7b36d2020-06-23 11:21:21 -0700201 self.assertFalse(
202 symbolfile.symbol_versioned_in_api([Tag('versioned=14')], 9))
Dan Albert06f58af2020-06-22 15:10:31 -0700203
204
205class OmitVersionTest(unittest.TestCase):
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900206 def setUp(self) -> None:
207 self.filter = Filter(arch = Arch('arm'), api = 9)
208 self.version = Version('foo', None, Tags(), [])
209
210 def assertOmit(self, f: Filter, v: Version) -> None:
211 self.assertTrue(f.should_omit_version(v))
212
213 def assertInclude(self, f: Filter, v: Version) -> None:
214 self.assertFalse(f.should_omit_version(v))
215
Dan Albertaf7b36d2020-06-23 11:21:21 -0700216 def test_omit_private(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900217 f = self.filter
218 v = self.version
Dan Albert06f58af2020-06-22 15:10:31 -0700219
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900220 self.assertInclude(f, v)
Dan Albert06f58af2020-06-22 15:10:31 -0700221
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900222 v.name = 'foo_PRIVATE'
223 self.assertOmit(f, v)
224
225 v.name = 'foo_PLATFORM'
226 self.assertOmit(f, v)
227
228 v.name = 'foo'
229 v.tags = Tags.from_strs(['platform-only'])
230 self.assertOmit(f, v)
Dan Albert06f58af2020-06-22 15:10:31 -0700231
Dan Albertaf7b36d2020-06-23 11:21:21 -0700232 def test_omit_llndk(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900233 f = self.filter
234 v = self.version
235 v_llndk = copy(v)
236 v_llndk.tags = Tags.from_strs(['llndk'])
Dan Albert06f58af2020-06-22 15:10:31 -0700237
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900238 self.assertOmit(f, v_llndk)
239
240 f.llndk = True
241 self.assertInclude(f, v)
242 self.assertInclude(f, v_llndk)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700243
244 def test_omit_apex(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900245 f = self.filter
246 v = self.version
247 v_apex = copy(v)
248 v_apex.tags = Tags.from_strs(['apex'])
Jiyong Park85cc35a2022-07-17 11:30:47 +0900249 v_systemapi = copy(v)
250 v_systemapi.tags = Tags.from_strs(['systemapi'])
Dan Albertaf7b36d2020-06-23 11:21:21 -0700251
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900252 self.assertOmit(f, v_apex)
253
254 f.apex = True
255 self.assertInclude(f, v)
256 self.assertInclude(f, v_apex)
Jiyong Park85cc35a2022-07-17 11:30:47 +0900257 self.assertOmit(f, v_systemapi)
Dan Albert06f58af2020-06-22 15:10:31 -0700258
Dan Albert56f52de2021-06-04 14:31:58 -0700259 def test_omit_systemapi(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900260 f = self.filter
261 v = self.version
Jiyong Park85cc35a2022-07-17 11:30:47 +0900262 v_apex = copy(v)
263 v_apex.tags = Tags.from_strs(['apex'])
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900264 v_systemapi = copy(v)
265 v_systemapi.tags = Tags.from_strs(['systemapi'])
Dan Albert56f52de2021-06-04 14:31:58 -0700266
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900267 self.assertOmit(f, v_systemapi)
268
Jiyong Park85cc35a2022-07-17 11:30:47 +0900269 f.systemapi = True
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900270 self.assertInclude(f, v)
271 self.assertInclude(f, v_systemapi)
Jiyong Park85cc35a2022-07-17 11:30:47 +0900272 self.assertOmit(f, v_apex)
Dan Albert56f52de2021-06-04 14:31:58 -0700273
Dan Albertaf7b36d2020-06-23 11:21:21 -0700274 def test_omit_arch(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900275 f_arm = self.filter
276 v_none = self.version
277 self.assertInclude(f_arm, v_none)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700278
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900279 v_arm = copy(v_none)
280 v_arm.tags = Tags.from_strs(['arm'])
281 self.assertInclude(f_arm, v_arm)
282
283 v_x86 = copy(v_none)
284 v_x86.tags = Tags.from_strs(['x86'])
285 self.assertOmit(f_arm, v_x86)
Dan Albertead21552021-06-04 14:30:40 -0700286
287 def test_omit_api(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900288 f_api9 = self.filter
289 v_none = self.version
290 self.assertInclude(f_api9, v_none)
Dan Albertead21552021-06-04 14:30:40 -0700291
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900292 v_api9 = copy(v_none)
293 v_api9.tags = Tags.from_strs(['introduced=9'])
294 self.assertInclude(f_api9, v_api9)
295
296 v_api14 = copy(v_none)
297 v_api14.tags = Tags.from_strs(['introduced=14'])
298 self.assertOmit(f_api9, v_api14)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700299
Dan Albert06f58af2020-06-22 15:10:31 -0700300
301class OmitSymbolTest(unittest.TestCase):
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900302 def setUp(self) -> None:
303 self.filter = Filter(arch = Arch('arm'), api = 9)
Dan Albert06f58af2020-06-22 15:10:31 -0700304
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900305 def assertOmit(self, f: Filter, s: Symbol) -> None:
306 self.assertTrue(f.should_omit_symbol(s))
307
308 def assertInclude(self, f: Filter, s: Symbol) -> None:
309 self.assertFalse(f.should_omit_symbol(s))
310
Jiyong Park4ecbdb62022-09-26 20:58:27 +0900311 def test_omit_ndk(self) -> None:
312 f_ndk = self.filter
313 f_nondk = copy(f_ndk)
314 f_nondk.ndk = False
315 f_nondk.apex = True
316
317 s_ndk = Symbol('foo', Tags())
318 s_nonndk = Symbol('foo', Tags.from_strs(['apex']))
319
320 self.assertInclude(f_ndk, s_ndk)
321 self.assertOmit(f_ndk, s_nonndk)
322 self.assertOmit(f_nondk, s_ndk)
323 self.assertInclude(f_nondk, s_nonndk)
324
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900325 def test_omit_llndk(self) -> None:
326 f_none = self.filter
327 f_llndk = copy(f_none)
328 f_llndk.llndk = True
329
330 s_none = Symbol('foo', Tags())
331 s_llndk = Symbol('foo', Tags.from_strs(['llndk']))
332
333 self.assertOmit(f_none, s_llndk)
334 self.assertInclude(f_llndk, s_none)
335 self.assertInclude(f_llndk, s_llndk)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700336
337 def test_omit_apex(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900338 f_none = self.filter
339 f_apex = copy(f_none)
340 f_apex.apex = True
Dan Albertaf7b36d2020-06-23 11:21:21 -0700341
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900342 s_none = Symbol('foo', Tags())
343 s_apex = Symbol('foo', Tags.from_strs(['apex']))
Jiyong Park85cc35a2022-07-17 11:30:47 +0900344 s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900345
346 self.assertOmit(f_none, s_apex)
347 self.assertInclude(f_apex, s_none)
348 self.assertInclude(f_apex, s_apex)
Jiyong Park85cc35a2022-07-17 11:30:47 +0900349 self.assertOmit(f_apex, s_systemapi)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700350
Dan Albert56f52de2021-06-04 14:31:58 -0700351 def test_omit_systemapi(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900352 f_none = self.filter
353 f_systemapi = copy(f_none)
Jiyong Park85cc35a2022-07-17 11:30:47 +0900354 f_systemapi.systemapi = True
Dan Albert56f52de2021-06-04 14:31:58 -0700355
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900356 s_none = Symbol('foo', Tags())
Jiyong Park85cc35a2022-07-17 11:30:47 +0900357 s_apex = Symbol('foo', Tags.from_strs(['apex']))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900358 s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
359
360 self.assertOmit(f_none, s_systemapi)
361 self.assertInclude(f_systemapi, s_none)
362 self.assertInclude(f_systemapi, s_systemapi)
Jiyong Park85cc35a2022-07-17 11:30:47 +0900363 self.assertOmit(f_systemapi, s_apex)
364
365 def test_omit_apex_and_systemapi(self) -> None:
366 f = self.filter
367 f.systemapi = True
368 f.apex = True
369
370 s_none = Symbol('foo', Tags())
371 s_apex = Symbol('foo', Tags.from_strs(['apex']))
372 s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
373 self.assertInclude(f, s_none)
374 self.assertInclude(f, s_apex)
375 self.assertInclude(f, s_systemapi)
Dan Albert56f52de2021-06-04 14:31:58 -0700376
Dan Albertaf7b36d2020-06-23 11:21:21 -0700377 def test_omit_arch(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900378 f_arm = self.filter
379 s_none = Symbol('foo', Tags())
380 s_arm = Symbol('foo', Tags.from_strs(['arm']))
381 s_x86 = Symbol('foo', Tags.from_strs(['x86']))
Dan Albert06f58af2020-06-22 15:10:31 -0700382
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900383 self.assertInclude(f_arm, s_none)
384 self.assertInclude(f_arm, s_arm)
385 self.assertOmit(f_arm, s_x86)
Dan Albert06f58af2020-06-22 15:10:31 -0700386
Dan Albertaf7b36d2020-06-23 11:21:21 -0700387 def test_omit_api(self) -> None:
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900388 f_api9 = self.filter
389 s_none = Symbol('foo', Tags())
390 s_api9 = Symbol('foo', Tags.from_strs(['introduced=9']))
391 s_api14 = Symbol('foo', Tags.from_strs(['introduced=14']))
Dan Albertaf7b36d2020-06-23 11:21:21 -0700392
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900393 self.assertInclude(f_api9, s_none)
394 self.assertInclude(f_api9, s_api9)
395 self.assertOmit(f_api9, s_api14)
Dan Albertaf7b36d2020-06-23 11:21:21 -0700396
Dan Albert06f58af2020-06-22 15:10:31 -0700397
398class SymbolFileParseTest(unittest.TestCase):
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900399 def setUp(self) -> None:
400 self.filter = Filter(arch = Arch('arm'), api = 16)
401
Dan Albertaf7b36d2020-06-23 11:21:21 -0700402 def test_next_line(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700403 input_file = io.StringIO(textwrap.dedent("""\
404 foo
405
406 bar
407 # baz
408 qux
409 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900410 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700411 self.assertIsNone(parser.current_line)
412
413 self.assertEqual('foo', parser.next_line().strip())
Dan Albertaf7b36d2020-06-23 11:21:21 -0700414 assert parser.current_line is not None
Dan Albert06f58af2020-06-22 15:10:31 -0700415 self.assertEqual('foo', parser.current_line.strip())
416
417 self.assertEqual('bar', parser.next_line().strip())
418 self.assertEqual('bar', parser.current_line.strip())
419
420 self.assertEqual('qux', parser.next_line().strip())
421 self.assertEqual('qux', parser.current_line.strip())
422
423 self.assertEqual('', parser.next_line())
424 self.assertEqual('', parser.current_line)
425
Dan Albertaf7b36d2020-06-23 11:21:21 -0700426 def test_parse_version(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700427 input_file = io.StringIO(textwrap.dedent("""\
428 VERSION_1 { # foo bar
429 baz;
430 qux; # woodly doodly
431 };
432
433 VERSION_2 {
434 } VERSION_1; # asdf
435 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900436 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700437
438 parser.next_line()
439 version = parser.parse_version()
440 self.assertEqual('VERSION_1', version.name)
441 self.assertIsNone(version.base)
Dan Albertead21552021-06-04 14:30:40 -0700442 self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags)
Dan Albert06f58af2020-06-22 15:10:31 -0700443
444 expected_symbols = [
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900445 Symbol('baz', Tags()),
446 Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
Dan Albert06f58af2020-06-22 15:10:31 -0700447 ]
448 self.assertEqual(expected_symbols, version.symbols)
449
450 parser.next_line()
451 version = parser.parse_version()
452 self.assertEqual('VERSION_2', version.name)
453 self.assertEqual('VERSION_1', version.base)
Dan Albertead21552021-06-04 14:30:40 -0700454 self.assertEqual(Tags(), version.tags)
Dan Albert06f58af2020-06-22 15:10:31 -0700455
Dan Albertaf7b36d2020-06-23 11:21:21 -0700456 def test_parse_version_eof(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700457 input_file = io.StringIO(textwrap.dedent("""\
458 VERSION_1 {
459 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900460 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700461 parser.next_line()
462 with self.assertRaises(symbolfile.ParseError):
463 parser.parse_version()
464
Dan Albertaf7b36d2020-06-23 11:21:21 -0700465 def test_unknown_scope_label(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700466 input_file = io.StringIO(textwrap.dedent("""\
467 VERSION_1 {
468 foo:
469 }
470 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900471 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700472 parser.next_line()
473 with self.assertRaises(symbolfile.ParseError):
474 parser.parse_version()
475
Dan Albertaf7b36d2020-06-23 11:21:21 -0700476 def test_parse_symbol(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700477 input_file = io.StringIO(textwrap.dedent("""\
478 foo;
479 bar; # baz qux
480 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900481 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700482
483 parser.next_line()
484 symbol = parser.parse_symbol()
485 self.assertEqual('foo', symbol.name)
Dan Albertead21552021-06-04 14:30:40 -0700486 self.assertEqual(Tags(), symbol.tags)
Dan Albert06f58af2020-06-22 15:10:31 -0700487
488 parser.next_line()
489 symbol = parser.parse_symbol()
490 self.assertEqual('bar', symbol.name)
Dan Albertead21552021-06-04 14:30:40 -0700491 self.assertEqual(Tags.from_strs(['baz', 'qux']), symbol.tags)
Dan Albert06f58af2020-06-22 15:10:31 -0700492
Dan Albertaf7b36d2020-06-23 11:21:21 -0700493 def test_wildcard_symbol_global(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700494 input_file = io.StringIO(textwrap.dedent("""\
495 VERSION_1 {
496 *;
497 };
498 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900499 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700500 parser.next_line()
501 with self.assertRaises(symbolfile.ParseError):
502 parser.parse_version()
503
Dan Albertaf7b36d2020-06-23 11:21:21 -0700504 def test_wildcard_symbol_local(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700505 input_file = io.StringIO(textwrap.dedent("""\
506 VERSION_1 {
507 local:
508 *;
509 };
510 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900511 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700512 parser.next_line()
513 version = parser.parse_version()
514 self.assertEqual([], version.symbols)
515
Dan Albertaf7b36d2020-06-23 11:21:21 -0700516 def test_missing_semicolon(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700517 input_file = io.StringIO(textwrap.dedent("""\
518 VERSION_1 {
519 foo
520 };
521 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900522 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700523 parser.next_line()
524 with self.assertRaises(symbolfile.ParseError):
525 parser.parse_version()
526
Dan Albertaf7b36d2020-06-23 11:21:21 -0700527 def test_parse_fails_invalid_input(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700528 with self.assertRaises(symbolfile.ParseError):
529 input_file = io.StringIO('foo')
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900530 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700531 parser.parse()
532
Dan Albertaf7b36d2020-06-23 11:21:21 -0700533 def test_parse(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700534 input_file = io.StringIO(textwrap.dedent("""\
535 VERSION_1 {
536 local:
537 hidden1;
538 global:
539 foo;
540 bar; # baz
541 };
542
543 VERSION_2 { # wasd
544 # Implicit global scope.
545 woodly;
546 doodly; # asdf
547 local:
548 qwerty;
549 } VERSION_1;
550 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900551 parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
Dan Albert06f58af2020-06-22 15:10:31 -0700552 versions = parser.parse()
553
554 expected = [
Dan Albertead21552021-06-04 14:30:40 -0700555 symbolfile.Version('VERSION_1', None, Tags(), [
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900556 Symbol('foo', Tags()),
557 Symbol('bar', Tags.from_strs(['baz'])),
Dan Albert06f58af2020-06-22 15:10:31 -0700558 ]),
Dan Albertead21552021-06-04 14:30:40 -0700559 symbolfile.Version(
560 'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900561 Symbol('woodly', Tags()),
562 Symbol('doodly', Tags.from_strs(['asdf'])),
Dan Albertead21552021-06-04 14:30:40 -0700563 ]),
Dan Albert06f58af2020-06-22 15:10:31 -0700564 ]
565
566 self.assertEqual(expected, versions)
567
Dan Albertaf7b36d2020-06-23 11:21:21 -0700568 def test_parse_llndk_apex_symbol(self) -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700569 input_file = io.StringIO(textwrap.dedent("""\
570 VERSION_1 {
571 foo;
572 bar; # llndk
573 baz; # llndk apex
574 qux; # apex
575 };
576 """))
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900577 f = copy(self.filter)
578 f.llndk = True
579 parser = symbolfile.SymbolFileParser(input_file, {}, f)
Dan Albert06f58af2020-06-22 15:10:31 -0700580
581 parser.next_line()
582 version = parser.parse_version()
583 self.assertEqual('VERSION_1', version.name)
584 self.assertIsNone(version.base)
585
586 expected_symbols = [
Jiyong Park3f9c41d2022-07-16 23:30:09 +0900587 Symbol('foo', Tags()),
588 Symbol('bar', Tags.from_strs(['llndk'])),
589 Symbol('baz', Tags.from_strs(['llndk', 'apex'])),
590 Symbol('qux', Tags.from_strs(['apex'])),
Dan Albert06f58af2020-06-22 15:10:31 -0700591 ]
592 self.assertEqual(expected_symbols, version.symbols)
593
594
Dan Albertaf7b36d2020-06-23 11:21:21 -0700595def main() -> None:
Dan Albert06f58af2020-06-22 15:10:31 -0700596 suite = unittest.TestLoader().loadTestsFromName(__name__)
597 unittest.TextTestRunner(verbosity=3).run(suite)
598
599
600if __name__ == '__main__':
601 main()