Refactor symbolfile script
Introduce the class `Filter` which encapsulates conditions (architecture, api level, whether llndk is included, etc.) so that we don't need to touch many places everytime a new condition is added. In addition, refactor test_symbolfile to reduce duplications This CL doesn't add a new functionality. Bug: 239274367 Test: run test_ndkstubgen and test_symbolfile Change-Id: I188e482492d39ec18134ecc5c908f0d288a754a9
This commit is contained in:
parent
70019a90be
commit
3f9c41d2f5
6 changed files with 243 additions and 261 deletions
|
@ -23,6 +23,7 @@ import sys
|
|||
from xml.etree.ElementTree import Element, SubElement, tostring
|
||||
from symbolfile import (
|
||||
ALL_ARCHITECTURES,
|
||||
Filter,
|
||||
FUTURE_API_LEVEL,
|
||||
MultiplyDefinedSymbolError,
|
||||
SymbolFileParser,
|
||||
|
@ -139,9 +140,8 @@ def main():
|
|||
|
||||
with open(args.symbol_file) as symbol_file:
|
||||
try:
|
||||
versions = SymbolFileParser(
|
||||
symbol_file, api_map, "", FUTURE_API_LEVEL, True, True
|
||||
).parse()
|
||||
filt = Filter("", FUTURE_API_LEVEL, True, True)
|
||||
versions = SymbolFileParser(symbol_file, api_map, filt).parse()
|
||||
except MultiplyDefinedSymbolError as ex:
|
||||
sys.exit('{}: error: {}'.format(args.symbol_file, ex))
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import textwrap
|
|||
import unittest
|
||||
|
||||
from xml.etree.ElementTree import fromstring
|
||||
from symbolfile import FUTURE_API_LEVEL, SymbolFileParser
|
||||
from symbolfile import Filter, FUTURE_API_LEVEL, SymbolFileParser
|
||||
import ndk_api_coverage_parser as nparser
|
||||
|
||||
|
||||
|
@ -78,9 +78,8 @@ class ApiCoverageSymbolFileParserTest(unittest.TestCase):
|
|||
"""
|
||||
)
|
||||
)
|
||||
parser = SymbolFileParser(
|
||||
input_file, {}, "", FUTURE_API_LEVEL, True, True
|
||||
)
|
||||
filt = Filter("", FUTURE_API_LEVEL, True, True)
|
||||
parser = SymbolFileParser(input_file, {}, filt)
|
||||
generator = nparser.XmlGenerator(io.StringIO())
|
||||
result = generator.convertToXml(parser.parse())
|
||||
expected = fromstring(
|
||||
|
|
|
@ -29,15 +29,12 @@ from symbolfile import Arch, Version
|
|||
class Generator:
|
||||
"""Output generator that writes stub source files and version scripts."""
|
||||
def __init__(self, src_file: TextIO, version_script: TextIO,
|
||||
symbol_list: TextIO, arch: Arch, api: int, llndk: bool,
|
||||
apex: bool) -> None:
|
||||
symbol_list: TextIO, filt: symbolfile.Filter) -> None:
|
||||
self.src_file = src_file
|
||||
self.version_script = version_script
|
||||
self.symbol_list = symbol_list
|
||||
self.arch = arch
|
||||
self.api = api
|
||||
self.llndk = llndk
|
||||
self.apex = apex
|
||||
self.filter = filt
|
||||
self.api = filt.api
|
||||
|
||||
def write(self, versions: Iterable[Version]) -> None:
|
||||
"""Writes all symbol data to the output files."""
|
||||
|
@ -47,8 +44,7 @@ class Generator:
|
|||
|
||||
def write_version(self, version: Version) -> None:
|
||||
"""Writes a single version block's data to the output files."""
|
||||
if symbolfile.should_omit_version(version, self.arch, self.api,
|
||||
self.llndk, self.apex):
|
||||
if self.filter.should_omit_version(version):
|
||||
return
|
||||
|
||||
section_versioned = symbolfile.symbol_versioned_in_api(
|
||||
|
@ -56,8 +52,7 @@ class Generator:
|
|||
version_empty = True
|
||||
pruned_symbols = []
|
||||
for symbol in version.symbols:
|
||||
if symbolfile.should_omit_symbol(symbol, self.arch, self.api,
|
||||
self.llndk, self.apex):
|
||||
if self.filter.should_omit_symbol(symbol):
|
||||
continue
|
||||
|
||||
if symbolfile.symbol_versioned_in_api(symbol.tags, self.api):
|
||||
|
@ -152,11 +147,10 @@ def main() -> None:
|
|||
verbosity = 2
|
||||
logging.basicConfig(level=verbose_map[verbosity])
|
||||
|
||||
filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex)
|
||||
with args.symbol_file.open() as symbol_file:
|
||||
try:
|
||||
versions = symbolfile.SymbolFileParser(symbol_file, api_map,
|
||||
args.arch, api, args.llndk,
|
||||
args.apex).parse()
|
||||
versions = symbolfile.SymbolFileParser(symbol_file, api_map, filt).parse()
|
||||
except symbolfile.MultiplyDefinedSymbolError as ex:
|
||||
sys.exit(f'{args.symbol_file}: error: {ex}')
|
||||
|
||||
|
@ -164,7 +158,7 @@ def main() -> None:
|
|||
with args.version_script.open('w') as version_script:
|
||||
with args.symbol_list.open('w') as symbol_list:
|
||||
generator = Generator(src_file, version_script, symbol_list,
|
||||
args.arch, api, args.llndk, args.apex)
|
||||
filt)
|
||||
generator.write(versions)
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
import io
|
||||
import textwrap
|
||||
import unittest
|
||||
from copy import copy
|
||||
|
||||
import symbolfile
|
||||
from symbolfile import Arch, Tags
|
||||
|
@ -29,6 +30,9 @@ import ndkstubgen
|
|||
|
||||
|
||||
class GeneratorTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
|
||||
|
||||
def test_omit_version(self) -> None:
|
||||
# Thorough testing of the cases involved here is handled by
|
||||
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
|
||||
|
@ -37,7 +41,7 @@ class GeneratorTest(unittest.TestCase):
|
|||
symbol_list_file = io.StringIO()
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9, False, False)
|
||||
self.filter)
|
||||
|
||||
version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [
|
||||
symbolfile.Symbol('foo', Tags()),
|
||||
|
@ -70,7 +74,7 @@ class GeneratorTest(unittest.TestCase):
|
|||
symbol_list_file = io.StringIO()
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9, False, False)
|
||||
self.filter)
|
||||
|
||||
version = symbolfile.Version('VERSION_1', None, Tags(), [
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['x86'])),
|
||||
|
@ -106,7 +110,7 @@ class GeneratorTest(unittest.TestCase):
|
|||
symbol_list_file = io.StringIO()
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9, False, False)
|
||||
self.filter)
|
||||
|
||||
versions = [
|
||||
symbolfile.Version('VERSION_1', None, Tags(), [
|
||||
|
@ -162,6 +166,9 @@ class GeneratorTest(unittest.TestCase):
|
|||
|
||||
|
||||
class IntegrationTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
|
||||
|
||||
def test_integration(self) -> None:
|
||||
api_map = {
|
||||
'O': 9000,
|
||||
|
@ -199,8 +206,7 @@ class IntegrationTest(unittest.TestCase):
|
|||
wobble;
|
||||
} VERSION_4;
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
|
||||
9, False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, self.filter)
|
||||
versions = parser.parse()
|
||||
|
||||
src_file = io.StringIO()
|
||||
|
@ -208,7 +214,7 @@ class IntegrationTest(unittest.TestCase):
|
|||
symbol_list_file = io.StringIO()
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9, False, False)
|
||||
self.filter)
|
||||
generator.write(versions)
|
||||
|
||||
expected_src = textwrap.dedent("""\
|
||||
|
@ -263,16 +269,18 @@ class IntegrationTest(unittest.TestCase):
|
|||
*;
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
|
||||
9001, False, False)
|
||||
f = copy(self.filter)
|
||||
f.api = 9001
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, f)
|
||||
versions = parser.parse()
|
||||
|
||||
src_file = io.StringIO()
|
||||
version_file = io.StringIO()
|
||||
symbol_list_file = io.StringIO()
|
||||
f = copy(self.filter)
|
||||
f.api = 9001
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9001, False, False)
|
||||
version_file, symbol_list_file, f)
|
||||
generator.write(versions)
|
||||
|
||||
expected_src = textwrap.dedent("""\
|
||||
|
@ -322,8 +330,9 @@ class IntegrationTest(unittest.TestCase):
|
|||
} VERSION_2;
|
||||
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
f = copy(self.filter)
|
||||
f.api = 16
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, f)
|
||||
|
||||
with self.assertRaises(
|
||||
symbolfile.MultiplyDefinedSymbolError) as ex_context:
|
||||
|
@ -370,16 +379,18 @@ class IntegrationTest(unittest.TestCase):
|
|||
wobble;
|
||||
} VERSION_4;
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'),
|
||||
9, False, True)
|
||||
f = copy(self.filter)
|
||||
f.apex = True
|
||||
parser = symbolfile.SymbolFileParser(input_file, api_map, f)
|
||||
versions = parser.parse()
|
||||
|
||||
src_file = io.StringIO()
|
||||
version_file = io.StringIO()
|
||||
symbol_list_file = io.StringIO()
|
||||
f = copy(self.filter)
|
||||
f.apex = True
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file, symbol_list_file,
|
||||
Arch('arm'), 9, False, True)
|
||||
version_file, symbol_list_file, f)
|
||||
generator.write(versions)
|
||||
|
||||
expected_src = textwrap.dedent("""\
|
||||
|
@ -428,20 +439,19 @@ class IntegrationTest(unittest.TestCase):
|
|||
*;
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'),
|
||||
9, llndk=False, apex=True)
|
||||
f = copy(self.filter)
|
||||
f.apex = True
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, f)
|
||||
versions = parser.parse()
|
||||
|
||||
src_file = io.StringIO()
|
||||
version_file = io.StringIO()
|
||||
symbol_list_file = io.StringIO()
|
||||
f = copy(self.filter)
|
||||
f.apex = True
|
||||
generator = ndkstubgen.Generator(src_file,
|
||||
version_file,
|
||||
symbol_list_file,
|
||||
Arch('arm'),
|
||||
9,
|
||||
llndk=False,
|
||||
apex=True)
|
||||
symbol_list_file, f)
|
||||
generator.write(versions)
|
||||
|
||||
self.assertEqual('', src_file.getvalue())
|
||||
|
|
|
@ -198,50 +198,55 @@ def get_tag_value(tag: Tag) -> str:
|
|||
"""
|
||||
return split_tag(tag)[1]
|
||||
|
||||
|
||||
def _should_omit_tags(tags: Tags, arch: Arch, api: int, llndk: bool,
|
||||
apex: bool) -> bool:
|
||||
"""Returns True if the tagged object should be omitted.
|
||||
|
||||
This defines the rules shared between version tagging and symbol tagging.
|
||||
class Filter:
|
||||
"""A filter encapsulates a condition that tells whether a version or a
|
||||
symbol should be omitted or not
|
||||
"""
|
||||
# The apex and llndk tags will only exclude APIs from other modes. If in
|
||||
# APEX or LLNDK mode and neither tag is provided, we fall back to the
|
||||
# default behavior because all NDK symbols are implicitly available to APEX
|
||||
# and LLNDK.
|
||||
if tags.has_mode_tags:
|
||||
if not apex and not llndk:
|
||||
|
||||
def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False):
|
||||
self.arch = arch
|
||||
self.api = api
|
||||
self.llndk = llndk
|
||||
self.apex = apex
|
||||
|
||||
def _should_omit_tags(self, tags: Tags) -> bool:
|
||||
"""Returns True if the tagged object should be omitted.
|
||||
|
||||
This defines the rules shared between version tagging and symbol tagging.
|
||||
"""
|
||||
# The apex and llndk tags will only exclude APIs from other modes. If in
|
||||
# APEX or LLNDK mode and neither tag is provided, we fall back to the
|
||||
# default behavior because all NDK symbols are implicitly available to
|
||||
# APEX and LLNDK.
|
||||
if tags.has_mode_tags:
|
||||
if not self.apex and not self.llndk:
|
||||
return True
|
||||
if self.apex and not tags.has_apex_tags:
|
||||
return True
|
||||
if self.llndk and not tags.has_llndk_tags:
|
||||
return True
|
||||
if not symbol_in_arch(tags, self.arch):
|
||||
return True
|
||||
if apex and not tags.has_apex_tags:
|
||||
if not symbol_in_api(tags, self.arch, self.api):
|
||||
return True
|
||||
if llndk and not tags.has_llndk_tags:
|
||||
return False
|
||||
|
||||
def should_omit_version(self, version: Version) -> bool:
|
||||
"""Returns True if the version section should be omitted.
|
||||
|
||||
We want to omit any sections that do not have any symbols we'll have in
|
||||
the stub library. Sections that contain entirely future symbols or only
|
||||
symbols for certain architectures.
|
||||
"""
|
||||
if version.is_private:
|
||||
return True
|
||||
if not symbol_in_arch(tags, arch):
|
||||
return True
|
||||
if not symbol_in_api(tags, arch, api):
|
||||
return True
|
||||
return False
|
||||
if version.tags.has_platform_only_tags:
|
||||
return True
|
||||
return self._should_omit_tags(version.tags)
|
||||
|
||||
|
||||
def should_omit_version(version: Version, arch: Arch, api: int, llndk: bool,
|
||||
apex: bool) -> bool:
|
||||
"""Returns True if the version section should be omitted.
|
||||
|
||||
We want to omit any sections that do not have any symbols we'll have in the
|
||||
stub library. Sections that contain entirely future symbols or only symbols
|
||||
for certain architectures.
|
||||
"""
|
||||
if version.is_private:
|
||||
return True
|
||||
if version.tags.has_platform_only_tags:
|
||||
return True
|
||||
return _should_omit_tags(version.tags, arch, api, llndk, apex)
|
||||
|
||||
|
||||
def should_omit_symbol(symbol: Symbol, arch: Arch, api: int, llndk: bool,
|
||||
apex: bool) -> bool:
|
||||
"""Returns True if the symbol should be omitted."""
|
||||
return _should_omit_tags(symbol.tags, arch, api, llndk, apex)
|
||||
def should_omit_symbol(self, symbol: Symbol) -> bool:
|
||||
"""Returns True if the symbol should be omitted."""
|
||||
return self._should_omit_tags(symbol.tags)
|
||||
|
||||
|
||||
def symbol_in_arch(tags: Tags, arch: Arch) -> bool:
|
||||
|
@ -316,14 +321,10 @@ class MultiplyDefinedSymbolError(RuntimeError):
|
|||
|
||||
class SymbolFileParser:
|
||||
"""Parses NDK symbol files."""
|
||||
def __init__(self, input_file: TextIO, api_map: ApiMap, arch: Arch,
|
||||
api: int, llndk: bool, apex: bool) -> None:
|
||||
def __init__(self, input_file: TextIO, api_map: ApiMap, filt: Filter) -> None:
|
||||
self.input_file = input_file
|
||||
self.api_map = api_map
|
||||
self.arch = arch
|
||||
self.api = api
|
||||
self.llndk = llndk
|
||||
self.apex = apex
|
||||
self.filter = filt
|
||||
self.current_line: Optional[str] = None
|
||||
|
||||
def parse(self) -> List[Version]:
|
||||
|
@ -352,13 +353,11 @@ class SymbolFileParser:
|
|||
symbol_names = set()
|
||||
multiply_defined_symbols = set()
|
||||
for version in versions:
|
||||
if should_omit_version(version, self.arch, self.api, self.llndk,
|
||||
self.apex):
|
||||
if self.filter.should_omit_version(version):
|
||||
continue
|
||||
|
||||
for symbol in version.symbols:
|
||||
if should_omit_symbol(symbol, self.arch, self.api, self.llndk,
|
||||
self.apex):
|
||||
if self.filter.should_omit_symbol(symbol):
|
||||
continue
|
||||
|
||||
if symbol.name in symbol_names:
|
||||
|
|
|
@ -19,7 +19,8 @@ import textwrap
|
|||
import unittest
|
||||
|
||||
import symbolfile
|
||||
from symbolfile import Arch, Tag, Tags, Version
|
||||
from symbolfile import Arch, Tag, Tags, Version, Symbol, Filter
|
||||
from copy import copy
|
||||
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
|
@ -202,178 +203,166 @@ class SymbolPresenceTest(unittest.TestCase):
|
|||
|
||||
|
||||
class OmitVersionTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.filter = Filter(arch = Arch('arm'), api = 9)
|
||||
self.version = Version('foo', None, Tags(), [])
|
||||
|
||||
def assertOmit(self, f: Filter, v: Version) -> None:
|
||||
self.assertTrue(f.should_omit_version(v))
|
||||
|
||||
def assertInclude(self, f: Filter, v: Version) -> None:
|
||||
self.assertFalse(f.should_omit_version(v))
|
||||
|
||||
def test_omit_private(self) -> None:
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
|
||||
False, False))
|
||||
f = self.filter
|
||||
v = self.version
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo_PRIVATE', None, Tags(), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo_PLATFORM', None, Tags(), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
self.assertInclude(f, v)
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None,
|
||||
Tags.from_strs(['platform-only']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
v.name = 'foo_PRIVATE'
|
||||
self.assertOmit(f, v)
|
||||
|
||||
v.name = 'foo_PLATFORM'
|
||||
self.assertOmit(f, v)
|
||||
|
||||
v.name = 'foo'
|
||||
v.tags = Tags.from_strs(['platform-only'])
|
||||
self.assertOmit(f, v)
|
||||
|
||||
def test_omit_llndk(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['llndk']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
f = self.filter
|
||||
v = self.version
|
||||
v_llndk = copy(v)
|
||||
v_llndk.tags = Tags.from_strs(['llndk'])
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
|
||||
True, False))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['llndk']), []),
|
||||
Arch('arm'), 9, True, False))
|
||||
self.assertOmit(f, v_llndk)
|
||||
|
||||
f.llndk = True
|
||||
self.assertInclude(f, v)
|
||||
self.assertInclude(f, v_llndk)
|
||||
|
||||
def test_omit_apex(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['apex']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
f = self.filter
|
||||
v = self.version
|
||||
v_apex = copy(v)
|
||||
v_apex.tags = Tags.from_strs(['apex'])
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
|
||||
False, True))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['apex']), []),
|
||||
Arch('arm'), 9, False, True))
|
||||
self.assertOmit(f, v_apex)
|
||||
|
||||
f.apex = True
|
||||
self.assertInclude(f, v)
|
||||
self.assertInclude(f, v_apex)
|
||||
|
||||
def test_omit_systemapi(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['systemapi']),
|
||||
[]), Arch('arm'), 9, False, False))
|
||||
f = self.filter
|
||||
v = self.version
|
||||
v_systemapi = copy(v)
|
||||
v_systemapi.tags = Tags.from_strs(['systemapi'])
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
|
||||
False, True))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['systemapi']),
|
||||
[]), Arch('arm'), 9, False, True))
|
||||
self.assertOmit(f, v_systemapi)
|
||||
|
||||
f.apex = True
|
||||
self.assertInclude(f, v)
|
||||
self.assertInclude(f, v_systemapi)
|
||||
|
||||
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))
|
||||
f_arm = self.filter
|
||||
v_none = self.version
|
||||
self.assertInclude(f_arm, v_none)
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None, Tags.from_strs(['x86']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
v_arm = copy(v_none)
|
||||
v_arm.tags = Tags.from_strs(['arm'])
|
||||
self.assertInclude(f_arm, v_arm)
|
||||
|
||||
v_x86 = copy(v_none)
|
||||
v_x86.tags = Tags.from_strs(['x86'])
|
||||
self.assertOmit(f_arm, v_x86)
|
||||
|
||||
def test_omit_api(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(['introduced=9']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
f_api9 = self.filter
|
||||
v_none = self.version
|
||||
self.assertInclude(f_api9, v_none)
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_version(
|
||||
symbolfile.Version('foo', None,
|
||||
Tags.from_strs(['introduced=14']), []),
|
||||
Arch('arm'), 9, False, False))
|
||||
v_api9 = copy(v_none)
|
||||
v_api9.tags = Tags.from_strs(['introduced=9'])
|
||||
self.assertInclude(f_api9, v_api9)
|
||||
|
||||
v_api14 = copy(v_none)
|
||||
v_api14.tags = Tags.from_strs(['introduced=14'])
|
||||
self.assertOmit(f_api9, v_api14)
|
||||
|
||||
|
||||
class OmitSymbolTest(unittest.TestCase):
|
||||
def test_omit_llndk(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
|
||||
Arch('arm'), 9, False, False))
|
||||
def setUp(self) -> None:
|
||||
self.filter = Filter(arch = Arch('arm'), api = 9)
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()),
|
||||
Arch('arm'), 9, True, False))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
|
||||
Arch('arm'), 9, True, False))
|
||||
def assertOmit(self, f: Filter, s: Symbol) -> None:
|
||||
self.assertTrue(f.should_omit_symbol(s))
|
||||
|
||||
def assertInclude(self, f: Filter, s: Symbol) -> None:
|
||||
self.assertFalse(f.should_omit_symbol(s))
|
||||
|
||||
def test_omit_llndk(self) -> None:
|
||||
f_none = self.filter
|
||||
f_llndk = copy(f_none)
|
||||
f_llndk.llndk = True
|
||||
|
||||
s_none = Symbol('foo', Tags())
|
||||
s_llndk = Symbol('foo', Tags.from_strs(['llndk']))
|
||||
|
||||
self.assertOmit(f_none, s_llndk)
|
||||
self.assertInclude(f_llndk, s_none)
|
||||
self.assertInclude(f_llndk, s_llndk)
|
||||
|
||||
def test_omit_apex(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['apex'])),
|
||||
Arch('arm'), 9, False, False))
|
||||
f_none = self.filter
|
||||
f_apex = copy(f_none)
|
||||
f_apex.apex = True
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()),
|
||||
Arch('arm'), 9, False, True))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['apex'])),
|
||||
Arch('arm'), 9, False, True))
|
||||
s_none = Symbol('foo', Tags())
|
||||
s_apex = Symbol('foo', Tags.from_strs(['apex']))
|
||||
|
||||
self.assertOmit(f_none, s_apex)
|
||||
self.assertInclude(f_apex, s_none)
|
||||
self.assertInclude(f_apex, s_apex)
|
||||
|
||||
def test_omit_systemapi(self) -> None:
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['systemapi'])),
|
||||
Arch('arm'), 9, False, False))
|
||||
f_none = self.filter
|
||||
f_systemapi = copy(f_none)
|
||||
f_systemapi.apex = True
|
||||
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()),
|
||||
Arch('arm'), 9, False, True))
|
||||
self.assertFalse(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['systemapi'])),
|
||||
Arch('arm'), 9, False, True))
|
||||
s_none = Symbol('foo', Tags())
|
||||
s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
|
||||
|
||||
self.assertOmit(f_none, s_systemapi)
|
||||
self.assertInclude(f_systemapi, s_none)
|
||||
self.assertInclude(f_systemapi, s_systemapi)
|
||||
|
||||
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))
|
||||
f_arm = self.filter
|
||||
s_none = Symbol('foo', Tags())
|
||||
s_arm = Symbol('foo', Tags.from_strs(['arm']))
|
||||
s_x86 = Symbol('foo', Tags.from_strs(['x86']))
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['x86'])), Arch('arm'),
|
||||
9, False, False))
|
||||
self.assertInclude(f_arm, s_none)
|
||||
self.assertInclude(f_arm, s_arm)
|
||||
self.assertOmit(f_arm, s_x86)
|
||||
|
||||
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))
|
||||
f_api9 = self.filter
|
||||
s_none = Symbol('foo', Tags())
|
||||
s_api9 = Symbol('foo', Tags.from_strs(['introduced=9']))
|
||||
s_api14 = Symbol('foo', Tags.from_strs(['introduced=14']))
|
||||
|
||||
self.assertTrue(
|
||||
symbolfile.should_omit_symbol(
|
||||
symbolfile.Symbol('foo', Tags.from_strs(['introduced=14'])),
|
||||
Arch('arm'), 9, False, False))
|
||||
self.assertInclude(f_api9, s_none)
|
||||
self.assertInclude(f_api9, s_api9)
|
||||
self.assertOmit(f_api9, s_api14)
|
||||
|
||||
|
||||
class SymbolFileParseTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.filter = Filter(arch = Arch('arm'), api = 16)
|
||||
|
||||
def test_next_line(self) -> None:
|
||||
input_file = io.StringIO(textwrap.dedent("""\
|
||||
foo
|
||||
|
@ -382,8 +371,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
# baz
|
||||
qux
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
self.assertIsNone(parser.current_line)
|
||||
|
||||
self.assertEqual('foo', parser.next_line().strip())
|
||||
|
@ -409,8 +397,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
VERSION_2 {
|
||||
} VERSION_1; # asdf
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
|
||||
parser.next_line()
|
||||
version = parser.parse_version()
|
||||
|
@ -419,8 +406,8 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags)
|
||||
|
||||
expected_symbols = [
|
||||
symbolfile.Symbol('baz', Tags()),
|
||||
symbolfile.Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
|
||||
Symbol('baz', Tags()),
|
||||
Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
|
||||
]
|
||||
self.assertEqual(expected_symbols, version.symbols)
|
||||
|
||||
|
@ -434,8 +421,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
input_file = io.StringIO(textwrap.dedent("""\
|
||||
VERSION_1 {
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.next_line()
|
||||
with self.assertRaises(symbolfile.ParseError):
|
||||
parser.parse_version()
|
||||
|
@ -446,8 +432,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
foo:
|
||||
}
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.next_line()
|
||||
with self.assertRaises(symbolfile.ParseError):
|
||||
parser.parse_version()
|
||||
|
@ -457,8 +442,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
foo;
|
||||
bar; # baz qux
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
|
||||
parser.next_line()
|
||||
symbol = parser.parse_symbol()
|
||||
|
@ -476,8 +460,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
*;
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.next_line()
|
||||
with self.assertRaises(symbolfile.ParseError):
|
||||
parser.parse_version()
|
||||
|
@ -489,8 +472,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
*;
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.next_line()
|
||||
version = parser.parse_version()
|
||||
self.assertEqual([], version.symbols)
|
||||
|
@ -501,8 +483,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
foo
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.next_line()
|
||||
with self.assertRaises(symbolfile.ParseError):
|
||||
parser.parse_version()
|
||||
|
@ -510,8 +491,7 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
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 = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
parser.parse()
|
||||
|
||||
def test_parse(self) -> None:
|
||||
|
@ -532,19 +512,18 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
qwerty;
|
||||
} VERSION_1;
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, False)
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
|
||||
versions = parser.parse()
|
||||
|
||||
expected = [
|
||||
symbolfile.Version('VERSION_1', None, Tags(), [
|
||||
symbolfile.Symbol('foo', Tags()),
|
||||
symbolfile.Symbol('bar', Tags.from_strs(['baz'])),
|
||||
Symbol('foo', Tags()),
|
||||
Symbol('bar', Tags.from_strs(['baz'])),
|
||||
]),
|
||||
symbolfile.Version(
|
||||
'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [
|
||||
symbolfile.Symbol('woodly', Tags()),
|
||||
symbolfile.Symbol('doodly', Tags.from_strs(['asdf'])),
|
||||
Symbol('woodly', Tags()),
|
||||
Symbol('doodly', Tags.from_strs(['asdf'])),
|
||||
]),
|
||||
]
|
||||
|
||||
|
@ -559,8 +538,9 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
qux; # apex
|
||||
};
|
||||
"""))
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16,
|
||||
False, True)
|
||||
f = copy(self.filter)
|
||||
f.llndk = True
|
||||
parser = symbolfile.SymbolFileParser(input_file, {}, f)
|
||||
|
||||
parser.next_line()
|
||||
version = parser.parse_version()
|
||||
|
@ -568,10 +548,10 @@ class SymbolFileParseTest(unittest.TestCase):
|
|||
self.assertIsNone(version.base)
|
||||
|
||||
expected_symbols = [
|
||||
symbolfile.Symbol('foo', Tags()),
|
||||
symbolfile.Symbol('bar', Tags.from_strs(['llndk'])),
|
||||
symbolfile.Symbol('baz', Tags.from_strs(['llndk', 'apex'])),
|
||||
symbolfile.Symbol('qux', Tags.from_strs(['apex'])),
|
||||
Symbol('foo', Tags()),
|
||||
Symbol('bar', Tags.from_strs(['llndk'])),
|
||||
Symbol('baz', Tags.from_strs(['llndk', 'apex'])),
|
||||
Symbol('qux', Tags.from_strs(['apex'])),
|
||||
]
|
||||
self.assertEqual(expected_symbols, version.symbols)
|
||||
|
||||
|
|
Loading…
Reference in a new issue