Пример #1
0
    def test_empty_stub(self) -> None:
        """Tests that empty stubs can be generated.

        This is not a common case, but libraries whose only behavior is to
        interpose symbols to alter existing behavior do not need to expose
        their interposing symbols as API, so it's possible for the stub to be
        empty while still needing a stub to link against. libsigchain is an
        example of this.
        """
        input_file = io.StringIO(textwrap.dedent("""\
            VERSION_1 {
                local:
                    *;
            };
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'),
                                             9, llndk=False, apex=True)
        versions = parser.parse()

        src_file = io.StringIO()
        version_file = io.StringIO()
        symbol_list_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file,
                                         version_file,
                                         symbol_list_file,
                                         Arch('arm'),
                                         9,
                                         llndk=False,
                                         apex=True)
        generator.write(versions)

        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())
    def test_symbol_in_arch(self) -> None:
        self.assertTrue(symbolfile.symbol_in_arch(Tags(), Arch('arm')))
        self.assertTrue(
            symbolfile.symbol_in_arch(Tags.from_strs(['arm']), Arch('arm')))

        self.assertFalse(
            symbolfile.symbol_in_arch(Tags.from_strs(['x86']), Arch('arm')))
Пример #3
0
    def test_omit_arch(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
                                          Arch('arm'), 9, False, False))
        self.assertFalse(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', [Tag('arm')]), Arch('arm'), 9, False,
                False))

        self.assertTrue(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', [Tag('x86')]), Arch('arm'), 9, False,
                False))
Пример #4
0
    def test_omit_api(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_symbol(symbolfile.Symbol('foo', []),
                                          Arch('arm'), 9, False, False))
        self.assertFalse(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', [Tag('introduced=9')]), Arch('arm'),
                9, False, False))

        self.assertTrue(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', [Tag('introduced=14')]), Arch('arm'),
                9, False, False))
    def test_omit_api(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()),
                                          Arch('arm'), 9, False, False))
        self.assertFalse(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', Tags.from_strs(['introduced=9'])),
                Arch('arm'), 9, False, False))

        self.assertTrue(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', Tags.from_strs(['introduced=14'])),
                Arch('arm'), 9, False, False))
    def test_omit_arch(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()),
                                          Arch('arm'), 9, False, False))
        self.assertFalse(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', Tags.from_strs(['arm'])), Arch('arm'),
                9, False, False))

        self.assertTrue(
            symbolfile.should_omit_symbol(
                symbolfile.Symbol('foo', Tags.from_strs(['x86'])), Arch('arm'),
                9, False, False))
Пример #7
0
    def test_omit_arch(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
                False))
        self.assertFalse(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, [Tag('arm')], []), Arch('arm'),
                9, False, False))

        self.assertTrue(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, [Tag('x86')], []), Arch('arm'),
                9, False, False))
Пример #8
0
    def test_integration_future_api(self) -> None:
        api_map = {
            'O': 9000,
            'P': 9001,
            'Q': 9002,
        }

        input_file = io.StringIO(textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo; # introduced=O
                    bar; # introduced=P
                    baz; # introduced=Q
                local:
                    *;
            };
        """))
        parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
                                             9001, False, False)
        versions = parser.parse()

        src_file = io.StringIO()
        version_file = io.StringIO()
        symbol_list_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file,
                                         version_file, symbol_list_file,
                                         Arch('arm'), 9001, False, False)
        generator.write(versions)

        expected_src = textwrap.dedent("""\
            void foo() {}
            void bar() {}
        """)
        self.assertEqual(expected_src, src_file.getvalue())

        expected_version = textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo;
                    bar;
            };
        """)
        self.assertEqual(expected_version, version_file.getvalue())

        expected_allowlist = textwrap.dedent("""\
            [abi_symbol_list]
            foo
            bar
        """)
        self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
    def test_omit_arch(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
                False, False))
        self.assertFalse(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, Tags.from_strs(['arm']), []),
                Arch('arm'), 9, False, False))

        self.assertTrue(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, Tags.from_strs(['x86']), []),
                Arch('arm'), 9, False, False))
Пример #10
0
    def test_parse(self) -> None:
        input_file = io.StringIO(textwrap.dedent("""\
            VERSION_1 {
                local:
                    hidden1;
                global:
                    foo;
                    bar; # baz
            };

            VERSION_2 { # wasd
                # Implicit global scope.
                    woodly;
                    doodly; # asdf
                local:
                    qwerty;
            } VERSION_1;
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, False)
        versions = parser.parse()

        expected = [
            symbolfile.Version('VERSION_1', None, [], [
                symbolfile.Symbol('foo', []),
                symbolfile.Symbol('bar', [Tag('baz')]),
            ]),
            symbolfile.Version('VERSION_2', 'VERSION_1', [Tag('wasd')], [
                symbolfile.Symbol('woodly', []),
                symbolfile.Symbol('doodly', [Tag('asdf')]),
            ]),
        ]

        self.assertEqual(expected, versions)
Пример #11
0
    def test_multiple_definition(self) -> None:
        input_file = io.StringIO(
            textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo;
                    foo;
                    bar;
                    baz;
                    qux; # arm
                local:
                    *;
            };

            VERSION_2 {
                global:
                    bar;
                    qux; # arm64
            } VERSION_1;

            VERSION_PRIVATE {
                global:
                    baz;
            } VERSION_2;

        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, False)

        with self.assertRaises(
                symbolfile.MultiplyDefinedSymbolError) as ex_context:
            parser.parse()
        self.assertEqual(['bar', 'foo'],
                         ex_context.exception.multiply_defined_symbols)
Пример #12
0
    def test_omit_version(self) -> None:
        # Thorough testing of the cases involved here is handled by
        # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
        src_file = io.StringIO()
        version_file = io.StringIO()
        symbol_list_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file,
                                         version_file, symbol_list_file,
                                         Arch('arm'), 9, False, False)

        version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [
            symbolfile.Symbol('foo', Tags()),
        ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())

        version = symbolfile.Version('VERSION', None, Tags.from_strs(['x86']),
                                     [
                                         symbolfile.Symbol('foo', Tags()),
                                     ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())

        version = symbolfile.Version('VERSION', None,
                                     Tags.from_strs(['introduced=14']), [
                                         symbolfile.Symbol('foo', Tags()),
                                     ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())
Пример #13
0
    def test_omit_symbol(self) -> None:
        # Thorough testing of the cases involved here is handled by
        # SymbolPresenceTest.
        src_file = io.StringIO()
        version_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
                                         9, False, False)

        version = symbolfile.Version('VERSION_1', None, [], [
            symbolfile.Symbol('foo', [Tag('x86')]),
        ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())

        version = symbolfile.Version('VERSION_1', None, [], [
            symbolfile.Symbol('foo', [Tag('introduced=14')]),
        ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())

        version = symbolfile.Version('VERSION_1', None, [], [
            symbolfile.Symbol('foo', [Tag('llndk')]),
        ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())

        version = symbolfile.Version('VERSION_1', None, [], [
            symbolfile.Symbol('foo', [Tag('apex')]),
        ])
        generator.write_version(version)
        self.assertEqual('', src_file.getvalue())
        self.assertEqual('', version_file.getvalue())
Пример #14
0
    def test_parse_version(self) -> None:
        input_file = io.StringIO(textwrap.dedent("""\
            VERSION_1 { # foo bar
                baz;
                qux; # woodly doodly
            };

            VERSION_2 {
            } VERSION_1; # asdf
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, False)

        parser.next_line()
        version = parser.parse_version()
        self.assertEqual('VERSION_1', version.name)
        self.assertIsNone(version.base)
        self.assertEqual(['foo', 'bar'], version.tags)

        expected_symbols = [
            symbolfile.Symbol('baz', []),
            symbolfile.Symbol('qux', [Tag('woodly'), Tag('doodly')]),
        ]
        self.assertEqual(expected_symbols, version.symbols)

        parser.next_line()
        version = parser.parse_version()
        self.assertEqual('VERSION_2', version.name)
        self.assertEqual('VERSION_1', version.base)
        self.assertEqual([], version.tags)
Пример #15
0
    def test_write(self) -> None:
        src_file = io.StringIO()
        version_file = io.StringIO()
        symbol_list_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file,
                                         version_file, symbol_list_file,
                                         Arch('arm'), 9, False, False)

        versions = [
            symbolfile.Version('VERSION_1', None, Tags(), [
                symbolfile.Symbol('foo', Tags()),
                symbolfile.Symbol('bar', Tags.from_strs(['var'])),
                symbolfile.Symbol('woodly', Tags.from_strs(['weak'])),
                symbolfile.Symbol('doodly', Tags.from_strs(['weak', 'var'])),
            ]),
            symbolfile.Version('VERSION_2', 'VERSION_1', Tags(), [
                symbolfile.Symbol('baz', Tags()),
            ]),
            symbolfile.Version('VERSION_3', 'VERSION_1', Tags(), [
                symbolfile.Symbol('qux', Tags.from_strs(['versioned=14'])),
            ]),
        ]

        generator.write(versions)
        expected_src = textwrap.dedent("""\
            void foo() {}
            int bar = 0;
            __attribute__((weak)) void woodly() {}
            __attribute__((weak)) int doodly = 0;
            void baz() {}
            void qux() {}
        """)
        self.assertEqual(expected_src, src_file.getvalue())

        expected_version = textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo;
                    bar;
                    woodly;
                    doodly;
            };
            VERSION_2 {
                global:
                    baz;
            } VERSION_1;
        """)
        self.assertEqual(expected_version, version_file.getvalue())

        expected_allowlist = textwrap.dedent("""\
            [abi_symbol_list]
            foo
            bar
            woodly
            doodly
            baz
            qux
        """)
        self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
Пример #16
0
 def test_parse_version_eof(self) -> None:
     input_file = io.StringIO(textwrap.dedent("""\
         VERSION_1 {
     """))
     parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                          False, False)
     parser.next_line()
     with self.assertRaises(symbolfile.ParseError):
         parser.parse_version()
Пример #17
0
    def test_omit_private(self) -> None:
        self.assertFalse(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, [], []), Arch('arm'), 9, False,
                False))

        self.assertTrue(
            symbolfile.should_omit_version(
                symbolfile.Version('foo_PRIVATE', None, [], []), Arch('arm'),
                9, False, False))
        self.assertTrue(
            symbolfile.should_omit_version(
                symbolfile.Version('foo_PLATFORM', None, [], []), Arch('arm'),
                9, False, False))

        self.assertTrue(
            symbolfile.should_omit_version(
                symbolfile.Version('foo', None, [Tag('platform-only')], []),
                Arch('arm'), 9, False, False))
Пример #18
0
 def test_wildcard_symbol_local(self) -> None:
     input_file = io.StringIO(textwrap.dedent("""\
         VERSION_1 {
             local:
                 *;
         };
     """))
     parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                          False, False)
     parser.next_line()
     version = parser.parse_version()
     self.assertEqual([], version.symbols)
Пример #19
0
    def test_parse_symbol(self) -> None:
        input_file = io.StringIO(textwrap.dedent("""\
            foo;
            bar; # baz qux
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, False)

        parser.next_line()
        symbol = parser.parse_symbol()
        self.assertEqual('foo', symbol.name)
        self.assertEqual([], symbol.tags)

        parser.next_line()
        symbol = parser.parse_symbol()
        self.assertEqual('bar', symbol.name)
        self.assertEqual(['baz', 'qux'], symbol.tags)
Пример #20
0
    def test_next_line(self) -> None:
        input_file = io.StringIO(textwrap.dedent("""\
            foo

            bar
            # baz
            qux
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, False)
        self.assertIsNone(parser.current_line)

        self.assertEqual('foo', parser.next_line().strip())
        assert parser.current_line is not None
        self.assertEqual('foo', parser.current_line.strip())

        self.assertEqual('bar', parser.next_line().strip())
        self.assertEqual('bar', parser.current_line.strip())

        self.assertEqual('qux', parser.next_line().strip())
        self.assertEqual('qux', parser.current_line.strip())

        self.assertEqual('', parser.next_line())
        self.assertEqual('', parser.current_line)
Пример #21
0
    def test_parse_llndk_apex_symbol(self) -> None:
        input_file = io.StringIO(textwrap.dedent("""\
            VERSION_1 {
                foo;
                bar; # llndk
                baz; # llndk apex
                qux; # apex
            };
        """))
        parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
                                             False, True)

        parser.next_line()
        version = parser.parse_version()
        self.assertEqual('VERSION_1', version.name)
        self.assertIsNone(version.base)

        expected_symbols = [
            symbolfile.Symbol('foo', []),
            symbolfile.Symbol('bar', [Tag('llndk')]),
            symbolfile.Symbol('baz', [Tag('llndk'), Tag('apex')]),
            symbolfile.Symbol('qux', [Tag('apex')]),
        ]
        self.assertEqual(expected_symbols, version.symbols)
Пример #22
0
    def test_symbol_in_api(self) -> None:
        self.assertTrue(symbolfile.symbol_in_api([], Arch('arm'), 9))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 9))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('introduced=9')], Arch('arm'), 14))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
                                     14))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('introduced-arm=9')], Arch('arm'),
                                     14))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('introduced-x86=14')], Arch('arm'),
                                     9))
        self.assertTrue(
            symbolfile.symbol_in_api(
                [Tag('introduced-arm=9'),
                 Tag('introduced-x86=21')], Arch('arm'), 14))
        self.assertTrue(
            symbolfile.symbol_in_api(
                [Tag('introduced=9'),
                 Tag('introduced-x86=21')], Arch('arm'), 14))
        self.assertTrue(
            symbolfile.symbol_in_api(
                [Tag('introduced=21'),
                 Tag('introduced-arm=9')], Arch('arm'), 14))
        self.assertTrue(
            symbolfile.symbol_in_api([Tag('future')], Arch('arm'),
                                     symbolfile.FUTURE_API_LEVEL))

        self.assertFalse(
            symbolfile.symbol_in_api([Tag('introduced=14')], Arch('arm'), 9))
        self.assertFalse(
            symbolfile.symbol_in_api([Tag('introduced-arm=14')], Arch('arm'),
                                     9))
        self.assertFalse(
            symbolfile.symbol_in_api([Tag('future')], Arch('arm'), 9))
        self.assertFalse(
            symbolfile.symbol_in_api(
                [Tag('introduced=9'), Tag('future')], Arch('arm'), 14))
        self.assertFalse(
            symbolfile.symbol_in_api([Tag('introduced-arm=9'),
                                      Tag('future')], Arch('arm'), 14))
        self.assertFalse(
            symbolfile.symbol_in_api(
                [Tag('introduced-arm=21'),
                 Tag('introduced-x86=9')], Arch('arm'), 14))
        self.assertFalse(
            symbolfile.symbol_in_api(
                [Tag('introduced=9'),
                 Tag('introduced-arm=21')], Arch('arm'), 14))
        self.assertFalse(
            symbolfile.symbol_in_api(
                [Tag('introduced=21'),
                 Tag('introduced-x86=9')], Arch('arm'), 14))

        # Interesting edge case: this symbol should be omitted from the
        # library, but this call should still return true because none of the
        # tags indiciate that it's not present in this API level.
        self.assertTrue(symbolfile.symbol_in_api([Tag('x86')], Arch('arm'), 9))
Пример #23
0
 def test_parse_fails_invalid_input(self) -> None:
     with self.assertRaises(symbolfile.ParseError):
         input_file = io.StringIO('foo')
         parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'),
                                              16, False, False)
         parser.parse()
Пример #24
0
    def test_integration_with_apex(self) -> None:
        api_map = {
            'O': 9000,
            'P': 9001,
        }

        input_file = io.StringIO(
            textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo; # var
                    bar; # x86
                    fizz; # introduced=O
                    buzz; # introduced=P
                local:
                    *;
            };

            VERSION_2 { # arm
                baz; # introduced=9
                qux; # versioned=14
            } VERSION_1;

            VERSION_3 { # introduced=14
                woodly;
                doodly; # var
            } VERSION_2;

            VERSION_4 { # versioned=9
                wibble;
                wizzes; # llndk
                waggle; # apex
                bubble; # apex llndk
                duddle; # llndk apex
            } VERSION_2;

            VERSION_5 { # versioned=14
                wobble;
            } VERSION_4;
        """))
        parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
                                             9, False, True)
        versions = parser.parse()

        src_file = io.StringIO()
        version_file = io.StringIO()
        generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
                                         9, False, True)
        generator.write(versions)

        expected_src = textwrap.dedent("""\
            int foo = 0;
            void baz() {}
            void qux() {}
            void wibble() {}
            void waggle() {}
            void bubble() {}
            void duddle() {}
            void wobble() {}
        """)
        self.assertEqual(expected_src, src_file.getvalue())

        expected_version = textwrap.dedent("""\
            VERSION_1 {
                global:
                    foo;
            };
            VERSION_2 {
                global:
                    baz;
            } VERSION_1;
            VERSION_4 {
                global:
                    wibble;
                    waggle;
                    bubble;
                    duddle;
            } VERSION_2;
        """)
        self.assertEqual(expected_version, version_file.getvalue())
Пример #25
0
    def test_symbol_in_arch(self) -> None:
        self.assertTrue(symbolfile.symbol_in_arch([], Arch('arm')))
        self.assertTrue(symbolfile.symbol_in_arch([Tag('arm')], Arch('arm')))

        self.assertFalse(symbolfile.symbol_in_arch([Tag('x86')], Arch('arm')))