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()