github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/test_gen_stub_libs.py (about) 1 #!/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 gen_stub_libs.py.""" 18 import cStringIO 19 import textwrap 20 import unittest 21 22 import gen_stub_libs as gsl 23 24 25 # pylint: disable=missing-docstring 26 27 28 class DecodeApiLevelTest(unittest.TestCase): 29 def test_decode_api_level(self): 30 self.assertEqual(9, gsl.decode_api_level('9', {})) 31 self.assertEqual(9000, gsl.decode_api_level('O', {'O': 9000})) 32 33 with self.assertRaises(KeyError): 34 gsl.decode_api_level('O', {}) 35 36 37 class TagsTest(unittest.TestCase): 38 def test_get_tags_no_tags(self): 39 self.assertEqual([], gsl.get_tags('')) 40 self.assertEqual([], gsl.get_tags('foo bar baz')) 41 42 def test_get_tags(self): 43 self.assertEqual(['foo', 'bar'], gsl.get_tags('# foo bar')) 44 self.assertEqual(['bar', 'baz'], gsl.get_tags('foo # bar baz')) 45 46 def test_split_tag(self): 47 self.assertTupleEqual(('foo', 'bar'), gsl.split_tag('foo=bar')) 48 self.assertTupleEqual(('foo', 'bar=baz'), gsl.split_tag('foo=bar=baz')) 49 with self.assertRaises(ValueError): 50 gsl.split_tag('foo') 51 52 def test_get_tag_value(self): 53 self.assertEqual('bar', gsl.get_tag_value('foo=bar')) 54 self.assertEqual('bar=baz', gsl.get_tag_value('foo=bar=baz')) 55 with self.assertRaises(ValueError): 56 gsl.get_tag_value('foo') 57 58 def test_is_api_level_tag(self): 59 self.assertTrue(gsl.is_api_level_tag('introduced=24')) 60 self.assertTrue(gsl.is_api_level_tag('introduced-arm=24')) 61 self.assertTrue(gsl.is_api_level_tag('versioned=24')) 62 63 # Shouldn't try to process things that aren't a key/value tag. 64 self.assertFalse(gsl.is_api_level_tag('arm')) 65 self.assertFalse(gsl.is_api_level_tag('introduced')) 66 self.assertFalse(gsl.is_api_level_tag('versioned')) 67 68 # We don't support arch specific `versioned` tags. 69 self.assertFalse(gsl.is_api_level_tag('versioned-arm=24')) 70 71 def test_decode_api_level_tags(self): 72 api_map = { 73 'O': 9000, 74 'P': 9001, 75 } 76 77 tags = [ 78 'introduced=9', 79 'introduced-arm=14', 80 'versioned=16', 81 'arm', 82 'introduced=O', 83 'introduced=P', 84 ] 85 expected_tags = [ 86 'introduced=9', 87 'introduced-arm=14', 88 'versioned=16', 89 'arm', 90 'introduced=9000', 91 'introduced=9001', 92 ] 93 self.assertListEqual( 94 expected_tags, gsl.decode_api_level_tags(tags, api_map)) 95 96 with self.assertRaises(gsl.ParseError): 97 gsl.decode_api_level_tags(['introduced=O'], {}) 98 99 100 class PrivateVersionTest(unittest.TestCase): 101 def test_version_is_private(self): 102 self.assertFalse(gsl.version_is_private('foo')) 103 self.assertFalse(gsl.version_is_private('PRIVATE')) 104 self.assertFalse(gsl.version_is_private('PLATFORM')) 105 self.assertFalse(gsl.version_is_private('foo_private')) 106 self.assertFalse(gsl.version_is_private('foo_platform')) 107 self.assertFalse(gsl.version_is_private('foo_PRIVATE_')) 108 self.assertFalse(gsl.version_is_private('foo_PLATFORM_')) 109 110 self.assertTrue(gsl.version_is_private('foo_PRIVATE')) 111 self.assertTrue(gsl.version_is_private('foo_PLATFORM')) 112 113 114 class SymbolPresenceTest(unittest.TestCase): 115 def test_symbol_in_arch(self): 116 self.assertTrue(gsl.symbol_in_arch([], 'arm')) 117 self.assertTrue(gsl.symbol_in_arch(['arm'], 'arm')) 118 119 self.assertFalse(gsl.symbol_in_arch(['x86'], 'arm')) 120 121 def test_symbol_in_api(self): 122 self.assertTrue(gsl.symbol_in_api([], 'arm', 9)) 123 self.assertTrue(gsl.symbol_in_api(['introduced=9'], 'arm', 9)) 124 self.assertTrue(gsl.symbol_in_api(['introduced=9'], 'arm', 14)) 125 self.assertTrue(gsl.symbol_in_api(['introduced-arm=9'], 'arm', 14)) 126 self.assertTrue(gsl.symbol_in_api(['introduced-arm=9'], 'arm', 14)) 127 self.assertTrue(gsl.symbol_in_api(['introduced-x86=14'], 'arm', 9)) 128 self.assertTrue(gsl.symbol_in_api( 129 ['introduced-arm=9', 'introduced-x86=21'], 'arm', 14)) 130 self.assertTrue(gsl.symbol_in_api( 131 ['introduced=9', 'introduced-x86=21'], 'arm', 14)) 132 self.assertTrue(gsl.symbol_in_api( 133 ['introduced=21', 'introduced-arm=9'], 'arm', 14)) 134 self.assertTrue(gsl.symbol_in_api( 135 ['future'], 'arm', gsl.FUTURE_API_LEVEL)) 136 137 self.assertFalse(gsl.symbol_in_api(['introduced=14'], 'arm', 9)) 138 self.assertFalse(gsl.symbol_in_api(['introduced-arm=14'], 'arm', 9)) 139 self.assertFalse(gsl.symbol_in_api(['future'], 'arm', 9)) 140 self.assertFalse(gsl.symbol_in_api( 141 ['introduced=9', 'future'], 'arm', 14)) 142 self.assertFalse(gsl.symbol_in_api( 143 ['introduced-arm=9', 'future'], 'arm', 14)) 144 self.assertFalse(gsl.symbol_in_api( 145 ['introduced-arm=21', 'introduced-x86=9'], 'arm', 14)) 146 self.assertFalse(gsl.symbol_in_api( 147 ['introduced=9', 'introduced-arm=21'], 'arm', 14)) 148 self.assertFalse(gsl.symbol_in_api( 149 ['introduced=21', 'introduced-x86=9'], 'arm', 14)) 150 151 # Interesting edge case: this symbol should be omitted from the 152 # library, but this call should still return true because none of the 153 # tags indiciate that it's not present in this API level. 154 self.assertTrue(gsl.symbol_in_api(['x86'], 'arm', 9)) 155 156 def test_verioned_in_api(self): 157 self.assertTrue(gsl.symbol_versioned_in_api([], 9)) 158 self.assertTrue(gsl.symbol_versioned_in_api(['versioned=9'], 9)) 159 self.assertTrue(gsl.symbol_versioned_in_api(['versioned=9'], 14)) 160 161 self.assertFalse(gsl.symbol_versioned_in_api(['versioned=14'], 9)) 162 163 164 class OmitVersionTest(unittest.TestCase): 165 def test_omit_private(self): 166 self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False)) 167 168 self.assertTrue(gsl.should_omit_version( 169 'foo_PRIVATE', [], 'arm', 9, False)) 170 self.assertTrue(gsl.should_omit_version( 171 'foo_PLATFORM', [], 'arm', 9, False)) 172 173 self.assertTrue(gsl.should_omit_version( 174 'foo', ['platform-only'], 'arm', 9, False)) 175 176 def test_omit_vndk(self): 177 self.assertTrue(gsl.should_omit_version( 178 'foo', ['vndk'], 'arm', 9, False)) 179 180 self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, True)) 181 self.assertFalse(gsl.should_omit_version( 182 'foo', ['vndk'], 'arm', 9, True)) 183 184 def test_omit_arch(self): 185 self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False)) 186 self.assertFalse(gsl.should_omit_version( 187 'foo', ['arm'], 'arm', 9, False)) 188 189 self.assertTrue(gsl.should_omit_version( 190 'foo', ['x86'], 'arm', 9, False)) 191 192 def test_omit_api(self): 193 self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False)) 194 self.assertFalse( 195 gsl.should_omit_version('foo', ['introduced=9'], 'arm', 9, False)) 196 197 self.assertTrue( 198 gsl.should_omit_version('foo', ['introduced=14'], 'arm', 9, False)) 199 200 201 class SymbolFileParseTest(unittest.TestCase): 202 def test_next_line(self): 203 input_file = cStringIO.StringIO(textwrap.dedent("""\ 204 foo 205 206 bar 207 # baz 208 qux 209 """)) 210 parser = gsl.SymbolFileParser(input_file, {}) 211 self.assertIsNone(parser.current_line) 212 213 self.assertEqual('foo', parser.next_line().strip()) 214 self.assertEqual('foo', parser.current_line.strip()) 215 216 self.assertEqual('bar', parser.next_line().strip()) 217 self.assertEqual('bar', parser.current_line.strip()) 218 219 self.assertEqual('qux', parser.next_line().strip()) 220 self.assertEqual('qux', parser.current_line.strip()) 221 222 self.assertEqual('', parser.next_line()) 223 self.assertEqual('', parser.current_line) 224 225 def test_parse_version(self): 226 input_file = cStringIO.StringIO(textwrap.dedent("""\ 227 VERSION_1 { # foo bar 228 baz; 229 qux; # woodly doodly 230 }; 231 232 VERSION_2 { 233 } VERSION_1; # asdf 234 """)) 235 parser = gsl.SymbolFileParser(input_file, {}) 236 237 parser.next_line() 238 version = parser.parse_version() 239 self.assertEqual('VERSION_1', version.name) 240 self.assertIsNone(version.base) 241 self.assertEqual(['foo', 'bar'], version.tags) 242 243 expected_symbols = [ 244 gsl.Symbol('baz', []), 245 gsl.Symbol('qux', ['woodly', 'doodly']), 246 ] 247 self.assertEqual(expected_symbols, version.symbols) 248 249 parser.next_line() 250 version = parser.parse_version() 251 self.assertEqual('VERSION_2', version.name) 252 self.assertEqual('VERSION_1', version.base) 253 self.assertEqual([], version.tags) 254 255 def test_parse_version_eof(self): 256 input_file = cStringIO.StringIO(textwrap.dedent("""\ 257 VERSION_1 { 258 """)) 259 parser = gsl.SymbolFileParser(input_file, {}) 260 parser.next_line() 261 with self.assertRaises(gsl.ParseError): 262 parser.parse_version() 263 264 def test_unknown_scope_label(self): 265 input_file = cStringIO.StringIO(textwrap.dedent("""\ 266 VERSION_1 { 267 foo: 268 } 269 """)) 270 parser = gsl.SymbolFileParser(input_file, {}) 271 parser.next_line() 272 with self.assertRaises(gsl.ParseError): 273 parser.parse_version() 274 275 def test_parse_symbol(self): 276 input_file = cStringIO.StringIO(textwrap.dedent("""\ 277 foo; 278 bar; # baz qux 279 """)) 280 parser = gsl.SymbolFileParser(input_file, {}) 281 282 parser.next_line() 283 symbol = parser.parse_symbol() 284 self.assertEqual('foo', symbol.name) 285 self.assertEqual([], symbol.tags) 286 287 parser.next_line() 288 symbol = parser.parse_symbol() 289 self.assertEqual('bar', symbol.name) 290 self.assertEqual(['baz', 'qux'], symbol.tags) 291 292 def test_wildcard_symbol_global(self): 293 input_file = cStringIO.StringIO(textwrap.dedent("""\ 294 VERSION_1 { 295 *; 296 }; 297 """)) 298 parser = gsl.SymbolFileParser(input_file, {}) 299 parser.next_line() 300 with self.assertRaises(gsl.ParseError): 301 parser.parse_version() 302 303 def test_wildcard_symbol_local(self): 304 input_file = cStringIO.StringIO(textwrap.dedent("""\ 305 VERSION_1 { 306 local: 307 *; 308 }; 309 """)) 310 parser = gsl.SymbolFileParser(input_file, {}) 311 parser.next_line() 312 version = parser.parse_version() 313 self.assertEqual([], version.symbols) 314 315 def test_missing_semicolon(self): 316 input_file = cStringIO.StringIO(textwrap.dedent("""\ 317 VERSION_1 { 318 foo 319 }; 320 """)) 321 parser = gsl.SymbolFileParser(input_file, {}) 322 parser.next_line() 323 with self.assertRaises(gsl.ParseError): 324 parser.parse_version() 325 326 def test_parse_fails_invalid_input(self): 327 with self.assertRaises(gsl.ParseError): 328 input_file = cStringIO.StringIO('foo') 329 parser = gsl.SymbolFileParser(input_file, {}) 330 parser.parse() 331 332 def test_parse(self): 333 input_file = cStringIO.StringIO(textwrap.dedent("""\ 334 VERSION_1 { 335 local: 336 hidden1; 337 global: 338 foo; 339 bar; # baz 340 }; 341 342 VERSION_2 { # wasd 343 # Implicit global scope. 344 woodly; 345 doodly; # asdf 346 local: 347 qwerty; 348 } VERSION_1; 349 """)) 350 parser = gsl.SymbolFileParser(input_file, {}) 351 versions = parser.parse() 352 353 expected = [ 354 gsl.Version('VERSION_1', None, [], [ 355 gsl.Symbol('foo', []), 356 gsl.Symbol('bar', ['baz']), 357 ]), 358 gsl.Version('VERSION_2', 'VERSION_1', ['wasd'], [ 359 gsl.Symbol('woodly', []), 360 gsl.Symbol('doodly', ['asdf']), 361 ]), 362 ] 363 364 self.assertEqual(expected, versions) 365 366 367 class GeneratorTest(unittest.TestCase): 368 def test_omit_version(self): 369 # Thorough testing of the cases involved here is handled by 370 # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest. 371 src_file = cStringIO.StringIO() 372 version_file = cStringIO.StringIO() 373 generator = gsl.Generator(src_file, version_file, 'arm', 9, False) 374 375 version = gsl.Version('VERSION_PRIVATE', None, [], [ 376 gsl.Symbol('foo', []), 377 ]) 378 generator.write_version(version) 379 self.assertEqual('', src_file.getvalue()) 380 self.assertEqual('', version_file.getvalue()) 381 382 version = gsl.Version('VERSION', None, ['x86'], [ 383 gsl.Symbol('foo', []), 384 ]) 385 generator.write_version(version) 386 self.assertEqual('', src_file.getvalue()) 387 self.assertEqual('', version_file.getvalue()) 388 389 version = gsl.Version('VERSION', None, ['introduced=14'], [ 390 gsl.Symbol('foo', []), 391 ]) 392 generator.write_version(version) 393 self.assertEqual('', src_file.getvalue()) 394 self.assertEqual('', version_file.getvalue()) 395 396 def test_omit_symbol(self): 397 # Thorough testing of the cases involved here is handled by 398 # SymbolPresenceTest. 399 src_file = cStringIO.StringIO() 400 version_file = cStringIO.StringIO() 401 generator = gsl.Generator(src_file, version_file, 'arm', 9, False) 402 403 version = gsl.Version('VERSION_1', None, [], [ 404 gsl.Symbol('foo', ['x86']), 405 ]) 406 generator.write_version(version) 407 self.assertEqual('', src_file.getvalue()) 408 self.assertEqual('', version_file.getvalue()) 409 410 version = gsl.Version('VERSION_1', None, [], [ 411 gsl.Symbol('foo', ['introduced=14']), 412 ]) 413 generator.write_version(version) 414 self.assertEqual('', src_file.getvalue()) 415 self.assertEqual('', version_file.getvalue()) 416 417 version = gsl.Version('VERSION_1', None, [], [ 418 gsl.Symbol('foo', ['vndk']), 419 ]) 420 generator.write_version(version) 421 self.assertEqual('', src_file.getvalue()) 422 self.assertEqual('', version_file.getvalue()) 423 424 def test_write(self): 425 src_file = cStringIO.StringIO() 426 version_file = cStringIO.StringIO() 427 generator = gsl.Generator(src_file, version_file, 'arm', 9, False) 428 429 versions = [ 430 gsl.Version('VERSION_1', None, [], [ 431 gsl.Symbol('foo', []), 432 gsl.Symbol('bar', ['var']), 433 gsl.Symbol('woodly', ['weak']), 434 gsl.Symbol('doodly', ['weak', 'var']), 435 ]), 436 gsl.Version('VERSION_2', 'VERSION_1', [], [ 437 gsl.Symbol('baz', []), 438 ]), 439 gsl.Version('VERSION_3', 'VERSION_1', [], [ 440 gsl.Symbol('qux', ['versioned=14']), 441 ]), 442 ] 443 444 generator.write(versions) 445 expected_src = textwrap.dedent("""\ 446 void foo() {} 447 int bar = 0; 448 __attribute__((weak)) void woodly() {} 449 __attribute__((weak)) int doodly = 0; 450 void baz() {} 451 void qux() {} 452 """) 453 self.assertEqual(expected_src, src_file.getvalue()) 454 455 expected_version = textwrap.dedent("""\ 456 VERSION_1 { 457 global: 458 foo; 459 bar; 460 woodly; 461 doodly; 462 }; 463 VERSION_2 { 464 global: 465 baz; 466 } VERSION_1; 467 """) 468 self.assertEqual(expected_version, version_file.getvalue()) 469 470 471 class IntegrationTest(unittest.TestCase): 472 def test_integration(self): 473 api_map = { 474 'O': 9000, 475 'P': 9001, 476 } 477 478 input_file = cStringIO.StringIO(textwrap.dedent("""\ 479 VERSION_1 { 480 global: 481 foo; # var 482 bar; # x86 483 fizz; # introduced=O 484 buzz; # introduced=P 485 local: 486 *; 487 }; 488 489 VERSION_2 { # arm 490 baz; # introduced=9 491 qux; # versioned=14 492 } VERSION_1; 493 494 VERSION_3 { # introduced=14 495 woodly; 496 doodly; # var 497 } VERSION_2; 498 499 VERSION_4 { # versioned=9 500 wibble; 501 wizzes; # vndk 502 } VERSION_2; 503 504 VERSION_5 { # versioned=14 505 wobble; 506 } VERSION_4; 507 """)) 508 parser = gsl.SymbolFileParser(input_file, api_map) 509 versions = parser.parse() 510 511 src_file = cStringIO.StringIO() 512 version_file = cStringIO.StringIO() 513 generator = gsl.Generator(src_file, version_file, 'arm', 9, False) 514 generator.write(versions) 515 516 expected_src = textwrap.dedent("""\ 517 int foo = 0; 518 void baz() {} 519 void qux() {} 520 void wibble() {} 521 void wobble() {} 522 """) 523 self.assertEqual(expected_src, src_file.getvalue()) 524 525 expected_version = textwrap.dedent("""\ 526 VERSION_1 { 527 global: 528 foo; 529 }; 530 VERSION_2 { 531 global: 532 baz; 533 } VERSION_1; 534 VERSION_4 { 535 global: 536 wibble; 537 } VERSION_2; 538 """) 539 self.assertEqual(expected_version, version_file.getvalue()) 540 541 def test_integration_future_api(self): 542 api_map = { 543 'O': 9000, 544 'P': 9001, 545 'Q': 9002, 546 } 547 548 input_file = cStringIO.StringIO(textwrap.dedent("""\ 549 VERSION_1 { 550 global: 551 foo; # introduced=O 552 bar; # introduced=P 553 baz; # introduced=Q 554 local: 555 *; 556 }; 557 """)) 558 parser = gsl.SymbolFileParser(input_file, api_map) 559 versions = parser.parse() 560 561 src_file = cStringIO.StringIO() 562 version_file = cStringIO.StringIO() 563 generator = gsl.Generator(src_file, version_file, 'arm', 9001, False) 564 generator.write(versions) 565 566 expected_src = textwrap.dedent("""\ 567 void foo() {} 568 void bar() {} 569 """) 570 self.assertEqual(expected_src, src_file.getvalue()) 571 572 expected_version = textwrap.dedent("""\ 573 VERSION_1 { 574 global: 575 foo; 576 bar; 577 }; 578 """) 579 self.assertEqual(expected_version, version_file.getvalue()) 580 581 582 def main(): 583 suite = unittest.TestLoader().loadTestsFromName(__name__) 584 unittest.TextTestRunner(verbosity=3).run(suite) 585 586 587 if __name__ == '__main__': 588 main()