Merge changes I0484ea34,I188e4824 am: b3f18a9f9f am: 03c590b4e1 am: bc5a0199e9

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2153678

Change-Id: I36e34aa54cc8995e9224d8b015ff6a4e32f246d3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2022-07-19 07:27:41 +00:00
committed by Automerger Merge Worker
8 changed files with 294 additions and 271 deletions

View File

@@ -949,8 +949,10 @@ func TestApexWithStubs(t *testing.T) {
// mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] // mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
// ensureNotContains(t, mylib2Cflags, "-include ") // ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --apex // Ensure that genstub for platform-provided lib is invoked with --systemapi
ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"]) ensureContains(t, ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
// Ensure that genstub for apex-provided lib is invoked with --apex
ensureContains(t, ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"lib64/mylib.so", "lib64/mylib.so",
@@ -1134,8 +1136,8 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"] mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylib2Cflags, "-include ") ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --apex // Ensure that genstub is invoked with --systemapi
ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"]) ensureContains(t, ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"], "--systemapi")
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"lib64/mylib.so", "lib64/mylib.so",

View File

@@ -1032,9 +1032,19 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile) ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile)
return Objects{} return Objects{}
} }
// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
// systemapi, respectively. The former is for symbols defined in platform libraries
// and the latter is for symbols defined in APEXes.
var flag string
if ctx.Module().(android.ApexModule).NotInPlatform() {
flag = "--apex"
} else {
// TODO(b/239274367) drop --apex when #apex is replaced with #systemapi
// in the map.txt files of platform libraries
flag = "--systemapi --apex"
}
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
"--apex")
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc) objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
library.versionScriptPath = android.OptionalPathForPath( library.versionScriptPath = android.OptionalPathForPath(
nativeAbiResult.versionScript) nativeAbiResult.versionScript)

View File

@@ -23,6 +23,7 @@ import sys
from xml.etree.ElementTree import Element, SubElement, tostring from xml.etree.ElementTree import Element, SubElement, tostring
from symbolfile import ( from symbolfile import (
ALL_ARCHITECTURES, ALL_ARCHITECTURES,
Filter,
FUTURE_API_LEVEL, FUTURE_API_LEVEL,
MultiplyDefinedSymbolError, MultiplyDefinedSymbolError,
SymbolFileParser, SymbolFileParser,
@@ -139,9 +140,8 @@ def main():
with open(args.symbol_file) as symbol_file: with open(args.symbol_file) as symbol_file:
try: try:
versions = SymbolFileParser( filt = Filter("", FUTURE_API_LEVEL, True, True, True)
symbol_file, api_map, "", FUTURE_API_LEVEL, True, True versions = SymbolFileParser(symbol_file, api_map, filt).parse()
).parse()
except MultiplyDefinedSymbolError as ex: except MultiplyDefinedSymbolError as ex:
sys.exit('{}: error: {}'.format(args.symbol_file, ex)) sys.exit('{}: error: {}'.format(args.symbol_file, ex))

View File

@@ -20,7 +20,7 @@ import textwrap
import unittest import unittest
from xml.etree.ElementTree import fromstring 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 import ndk_api_coverage_parser as nparser
@@ -78,9 +78,8 @@ class ApiCoverageSymbolFileParserTest(unittest.TestCase):
""" """
) )
) )
parser = SymbolFileParser( filt = Filter("", FUTURE_API_LEVEL, True, True, True)
input_file, {}, "", FUTURE_API_LEVEL, True, True parser = SymbolFileParser(input_file, {}, filt)
)
generator = nparser.XmlGenerator(io.StringIO()) generator = nparser.XmlGenerator(io.StringIO())
result = generator.convertToXml(parser.parse()) result = generator.convertToXml(parser.parse())
expected = fromstring( expected = fromstring(

View File

@@ -29,15 +29,12 @@ from symbolfile import Arch, Version
class Generator: class Generator:
"""Output generator that writes stub source files and version scripts.""" """Output generator that writes stub source files and version scripts."""
def __init__(self, src_file: TextIO, version_script: TextIO, def __init__(self, src_file: TextIO, version_script: TextIO,
symbol_list: TextIO, arch: Arch, api: int, llndk: bool, symbol_list: TextIO, filt: symbolfile.Filter) -> None:
apex: bool) -> None:
self.src_file = src_file self.src_file = src_file
self.version_script = version_script self.version_script = version_script
self.symbol_list = symbol_list self.symbol_list = symbol_list
self.arch = arch self.filter = filt
self.api = api self.api = filt.api
self.llndk = llndk
self.apex = apex
def write(self, versions: Iterable[Version]) -> None: def write(self, versions: Iterable[Version]) -> None:
"""Writes all symbol data to the output files.""" """Writes all symbol data to the output files."""
@@ -47,8 +44,7 @@ class Generator:
def write_version(self, version: Version) -> None: def write_version(self, version: Version) -> None:
"""Writes a single version block's data to the output files.""" """Writes a single version block's data to the output files."""
if symbolfile.should_omit_version(version, self.arch, self.api, if self.filter.should_omit_version(version):
self.llndk, self.apex):
return return
section_versioned = symbolfile.symbol_versioned_in_api( section_versioned = symbolfile.symbol_versioned_in_api(
@@ -56,8 +52,7 @@ class Generator:
version_empty = True version_empty = True
pruned_symbols = [] pruned_symbols = []
for symbol in version.symbols: for symbol in version.symbols:
if symbolfile.should_omit_symbol(symbol, self.arch, self.api, if self.filter.should_omit_symbol(symbol):
self.llndk, self.apex):
continue continue
if symbolfile.symbol_versioned_in_api(symbol.tags, self.api): if symbolfile.symbol_versioned_in_api(symbol.tags, self.api):
@@ -110,12 +105,12 @@ def parse_args() -> argparse.Namespace:
parser.add_argument( parser.add_argument(
'--apex', '--apex',
action='store_true', action='store_true',
help='Use the APEX variant. Note: equivalent to --system-api.') help='Use the APEX variant.')
parser.add_argument( parser.add_argument(
'--system-api', '--systemapi',
action='store_true', action='store_true',
dest='apex', dest='systemapi',
help='Use the SystemAPI variant. Note: equivalent to --apex.') help='Use the SystemAPI variant.')
parser.add_argument('--api-map', parser.add_argument('--api-map',
type=resolved_path, type=resolved_path,
@@ -152,11 +147,10 @@ def main() -> None:
verbosity = 2 verbosity = 2
logging.basicConfig(level=verbose_map[verbosity]) logging.basicConfig(level=verbose_map[verbosity])
filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex, args.systemapi)
with args.symbol_file.open() as symbol_file: with args.symbol_file.open() as symbol_file:
try: try:
versions = symbolfile.SymbolFileParser(symbol_file, api_map, versions = symbolfile.SymbolFileParser(symbol_file, api_map, filt).parse()
args.arch, api, args.llndk,
args.apex).parse()
except symbolfile.MultiplyDefinedSymbolError as ex: except symbolfile.MultiplyDefinedSymbolError as ex:
sys.exit(f'{args.symbol_file}: error: {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.version_script.open('w') as version_script:
with args.symbol_list.open('w') as symbol_list: with args.symbol_list.open('w') as symbol_list:
generator = Generator(src_file, version_script, symbol_list, generator = Generator(src_file, version_script, symbol_list,
args.arch, api, args.llndk, args.apex) filt)
generator.write(versions) generator.write(versions)

View File

@@ -18,6 +18,7 @@
import io import io
import textwrap import textwrap
import unittest import unittest
from copy import copy
import symbolfile import symbolfile
from symbolfile import Arch, Tags from symbolfile import Arch, Tags
@@ -29,6 +30,9 @@ import ndkstubgen
class GeneratorTest(unittest.TestCase): class GeneratorTest(unittest.TestCase):
def setUp(self) -> None:
self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
def test_omit_version(self) -> None: def test_omit_version(self) -> None:
# Thorough testing of the cases involved here is handled by # Thorough testing of the cases involved here is handled by
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest. # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
@@ -37,7 +41,7 @@ class GeneratorTest(unittest.TestCase):
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file,
Arch('arm'), 9, False, False) self.filter)
version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [ version = symbolfile.Version('VERSION_PRIVATE', None, Tags(), [
symbolfile.Symbol('foo', Tags()), symbolfile.Symbol('foo', Tags()),
@@ -70,7 +74,7 @@ class GeneratorTest(unittest.TestCase):
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file,
Arch('arm'), 9, False, False) self.filter)
version = symbolfile.Version('VERSION_1', None, Tags(), [ version = symbolfile.Version('VERSION_1', None, Tags(), [
symbolfile.Symbol('foo', Tags.from_strs(['x86'])), symbolfile.Symbol('foo', Tags.from_strs(['x86'])),
@@ -106,7 +110,7 @@ class GeneratorTest(unittest.TestCase):
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file,
Arch('arm'), 9, False, False) self.filter)
versions = [ versions = [
symbolfile.Version('VERSION_1', None, Tags(), [ symbolfile.Version('VERSION_1', None, Tags(), [
@@ -162,6 +166,9 @@ class GeneratorTest(unittest.TestCase):
class IntegrationTest(unittest.TestCase): class IntegrationTest(unittest.TestCase):
def setUp(self) -> None:
self.filter = symbolfile.Filter(Arch('arm'), 9, False, False)
def test_integration(self) -> None: def test_integration(self) -> None:
api_map = { api_map = {
'O': 9000, 'O': 9000,
@@ -199,8 +206,7 @@ class IntegrationTest(unittest.TestCase):
wobble; wobble;
} VERSION_4; } VERSION_4;
""")) """))
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), parser = symbolfile.SymbolFileParser(input_file, api_map, self.filter)
9, False, False)
versions = parser.parse() versions = parser.parse()
src_file = io.StringIO() src_file = io.StringIO()
@@ -208,7 +214,7 @@ class IntegrationTest(unittest.TestCase):
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file,
Arch('arm'), 9, False, False) self.filter)
generator.write(versions) generator.write(versions)
expected_src = textwrap.dedent("""\ expected_src = textwrap.dedent("""\
@@ -263,16 +269,18 @@ class IntegrationTest(unittest.TestCase):
*; *;
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), f = copy(self.filter)
9001, False, False) f.api = 9001
parser = symbolfile.SymbolFileParser(input_file, api_map, f)
versions = parser.parse() versions = parser.parse()
src_file = io.StringIO() src_file = io.StringIO()
version_file = io.StringIO() version_file = io.StringIO()
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
f = copy(self.filter)
f.api = 9001
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file, f)
Arch('arm'), 9001, False, False)
generator.write(versions) generator.write(versions)
expected_src = textwrap.dedent("""\ expected_src = textwrap.dedent("""\
@@ -322,8 +330,9 @@ class IntegrationTest(unittest.TestCase):
} VERSION_2; } VERSION_2;
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, f = copy(self.filter)
False, False) f.api = 16
parser = symbolfile.SymbolFileParser(input_file, {}, f)
with self.assertRaises( with self.assertRaises(
symbolfile.MultiplyDefinedSymbolError) as ex_context: symbolfile.MultiplyDefinedSymbolError) as ex_context:
@@ -370,16 +379,18 @@ class IntegrationTest(unittest.TestCase):
wobble; wobble;
} VERSION_4; } VERSION_4;
""")) """))
parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), f = copy(self.filter)
9, False, True) f.apex = True
parser = symbolfile.SymbolFileParser(input_file, api_map, f)
versions = parser.parse() versions = parser.parse()
src_file = io.StringIO() src_file = io.StringIO()
version_file = io.StringIO() version_file = io.StringIO()
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
f = copy(self.filter)
f.apex = True
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, symbol_list_file, version_file, symbol_list_file, f)
Arch('arm'), 9, False, True)
generator.write(versions) generator.write(versions)
expected_src = textwrap.dedent("""\ expected_src = textwrap.dedent("""\
@@ -428,20 +439,19 @@ class IntegrationTest(unittest.TestCase):
*; *;
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), f = copy(self.filter)
9, llndk=False, apex=True) f.apex = True
parser = symbolfile.SymbolFileParser(input_file, {}, f)
versions = parser.parse() versions = parser.parse()
src_file = io.StringIO() src_file = io.StringIO()
version_file = io.StringIO() version_file = io.StringIO()
symbol_list_file = io.StringIO() symbol_list_file = io.StringIO()
f = copy(self.filter)
f.apex = True
generator = ndkstubgen.Generator(src_file, generator = ndkstubgen.Generator(src_file,
version_file, version_file,
symbol_list_file, symbol_list_file, f)
Arch('arm'),
9,
llndk=False,
apex=True)
generator.write(versions) generator.write(versions)
self.assertEqual('', src_file.getvalue()) self.assertEqual('', src_file.getvalue())

View File

@@ -78,12 +78,17 @@ class Tags:
@property @property
def has_mode_tags(self) -> bool: def has_mode_tags(self) -> bool:
"""Returns True if any mode tags (apex, llndk, etc) are set.""" """Returns True if any mode tags (apex, llndk, etc) are set."""
return self.has_apex_tags or self.has_llndk_tags return self.has_apex_tags or self.has_llndk_tags or self.has_systemapi_tags
@property @property
def has_apex_tags(self) -> bool: def has_apex_tags(self) -> bool:
"""Returns True if any APEX tags are set.""" """Returns True if any APEX tags are set."""
return 'apex' in self.tags or 'systemapi' in self.tags return 'apex' in self.tags
@property
def has_systemapi_tags(self) -> bool:
"""Returns True if any APEX tags are set."""
return 'systemapi' in self.tags
@property @property
def has_llndk_tags(self) -> bool: def has_llndk_tags(self) -> bool:
@@ -198,50 +203,57 @@ def get_tag_value(tag: Tag) -> str:
""" """
return split_tag(tag)[1] return split_tag(tag)[1]
class Filter:
"""A filter encapsulates a condition that tells whether a version or a
symbol should be omitted or not
"""
def _should_omit_tags(tags: Tags, arch: Arch, api: int, llndk: bool, def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False, systemapi: bool = False):
apex: bool) -> bool: self.arch = arch
self.api = api
self.llndk = llndk
self.apex = apex
self.systemapi = systemapi
def _should_omit_tags(self, tags: Tags) -> bool:
"""Returns True if the tagged object should be omitted. """Returns True if the tagged object should be omitted.
This defines the rules shared between version tagging and symbol tagging. 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 # 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 # 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 # default behavior because all NDK symbols are implicitly available to
# and LLNDK. # APEX and LLNDK.
if tags.has_mode_tags: if tags.has_mode_tags:
if not apex and not llndk: if self.apex and tags.has_apex_tags:
return False
if self.llndk and tags.has_llndk_tags:
return False
if self.systemapi and tags.has_systemapi_tags:
return False
return True return True
if apex and not tags.has_apex_tags: if not symbol_in_arch(tags, self.arch):
return True return True
if llndk and not tags.has_llndk_tags: if not symbol_in_api(tags, self.arch, self.api):
return True
if not symbol_in_arch(tags, arch):
return True
if not symbol_in_api(tags, arch, api):
return True return True
return False return False
def should_omit_version(self, version: Version) -> bool:
def should_omit_version(version: Version, arch: Arch, api: int, llndk: bool,
apex: bool) -> bool:
"""Returns True if the version section should be omitted. """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 We want to omit any sections that do not have any symbols we'll have in
stub library. Sections that contain entirely future symbols or only symbols the stub library. Sections that contain entirely future symbols or only
for certain architectures. symbols for certain architectures.
""" """
if version.is_private: if version.is_private:
return True return True
if version.tags.has_platform_only_tags: if version.tags.has_platform_only_tags:
return True return True
return _should_omit_tags(version.tags, arch, api, llndk, apex) return self._should_omit_tags(version.tags)
def should_omit_symbol(self, symbol: Symbol) -> bool:
def should_omit_symbol(symbol: Symbol, arch: Arch, api: int, llndk: bool,
apex: bool) -> bool:
"""Returns True if the symbol should be omitted.""" """Returns True if the symbol should be omitted."""
return _should_omit_tags(symbol.tags, arch, api, llndk, apex) return self._should_omit_tags(symbol.tags)
def symbol_in_arch(tags: Tags, arch: Arch) -> bool: def symbol_in_arch(tags: Tags, arch: Arch) -> bool:
@@ -316,14 +328,10 @@ class MultiplyDefinedSymbolError(RuntimeError):
class SymbolFileParser: class SymbolFileParser:
"""Parses NDK symbol files.""" """Parses NDK symbol files."""
def __init__(self, input_file: TextIO, api_map: ApiMap, arch: Arch, def __init__(self, input_file: TextIO, api_map: ApiMap, filt: Filter) -> None:
api: int, llndk: bool, apex: bool) -> None:
self.input_file = input_file self.input_file = input_file
self.api_map = api_map self.api_map = api_map
self.arch = arch self.filter = filt
self.api = api
self.llndk = llndk
self.apex = apex
self.current_line: Optional[str] = None self.current_line: Optional[str] = None
def parse(self) -> List[Version]: def parse(self) -> List[Version]:
@@ -352,13 +360,11 @@ class SymbolFileParser:
symbol_names = set() symbol_names = set()
multiply_defined_symbols = set() multiply_defined_symbols = set()
for version in versions: for version in versions:
if should_omit_version(version, self.arch, self.api, self.llndk, if self.filter.should_omit_version(version):
self.apex):
continue continue
for symbol in version.symbols: for symbol in version.symbols:
if should_omit_symbol(symbol, self.arch, self.api, self.llndk, if self.filter.should_omit_symbol(symbol):
self.apex):
continue continue
if symbol.name in symbol_names: if symbol.name in symbol_names:

View File

@@ -19,7 +19,8 @@ import textwrap
import unittest import unittest
import symbolfile 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 # pylint: disable=missing-docstring
@@ -202,178 +203,188 @@ class SymbolPresenceTest(unittest.TestCase):
class OmitVersionTest(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: def test_omit_private(self) -> None:
self.assertFalse( f = self.filter
symbolfile.should_omit_version( v = self.version
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9,
False, False))
self.assertTrue( self.assertInclude(f, v)
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.assertTrue( v.name = 'foo_PRIVATE'
symbolfile.should_omit_version( self.assertOmit(f, v)
symbolfile.Version('foo', None,
Tags.from_strs(['platform-only']), []), v.name = 'foo_PLATFORM'
Arch('arm'), 9, False, False)) self.assertOmit(f, v)
v.name = 'foo'
v.tags = Tags.from_strs(['platform-only'])
self.assertOmit(f, v)
def test_omit_llndk(self) -> None: def test_omit_llndk(self) -> None:
self.assertTrue( f = self.filter
symbolfile.should_omit_version( v = self.version
symbolfile.Version('foo', None, Tags.from_strs(['llndk']), []), v_llndk = copy(v)
Arch('arm'), 9, False, False)) v_llndk.tags = Tags.from_strs(['llndk'])
self.assertFalse( self.assertOmit(f, v_llndk)
symbolfile.should_omit_version(
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9, f.llndk = True
True, False)) self.assertInclude(f, v)
self.assertFalse( self.assertInclude(f, v_llndk)
symbolfile.should_omit_version(
symbolfile.Version('foo', None, Tags.from_strs(['llndk']), []),
Arch('arm'), 9, True, False))
def test_omit_apex(self) -> None: def test_omit_apex(self) -> None:
self.assertTrue( f = self.filter
symbolfile.should_omit_version( v = self.version
symbolfile.Version('foo', None, Tags.from_strs(['apex']), []), v_apex = copy(v)
Arch('arm'), 9, False, False)) v_apex.tags = Tags.from_strs(['apex'])
v_systemapi = copy(v)
v_systemapi.tags = Tags.from_strs(['systemapi'])
self.assertFalse( self.assertOmit(f, v_apex)
symbolfile.should_omit_version(
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9, f.apex = True
False, True)) self.assertInclude(f, v)
self.assertFalse( self.assertInclude(f, v_apex)
symbolfile.should_omit_version( self.assertOmit(f, v_systemapi)
symbolfile.Version('foo', None, Tags.from_strs(['apex']), []),
Arch('arm'), 9, False, True))
def test_omit_systemapi(self) -> None: def test_omit_systemapi(self) -> None:
self.assertTrue( f = self.filter
symbolfile.should_omit_version( v = self.version
symbolfile.Version('foo', None, Tags.from_strs(['systemapi']), v_apex = copy(v)
[]), Arch('arm'), 9, False, False)) v_apex.tags = Tags.from_strs(['apex'])
v_systemapi = copy(v)
v_systemapi.tags = Tags.from_strs(['systemapi'])
self.assertFalse( self.assertOmit(f, v_systemapi)
symbolfile.should_omit_version(
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9, f.systemapi = True
False, True)) self.assertInclude(f, v)
self.assertFalse( self.assertInclude(f, v_systemapi)
symbolfile.should_omit_version( self.assertOmit(f, v_apex)
symbolfile.Version('foo', None, Tags.from_strs(['systemapi']),
[]), Arch('arm'), 9, False, True))
def test_omit_arch(self) -> None: def test_omit_arch(self) -> None:
self.assertFalse( f_arm = self.filter
symbolfile.should_omit_version( v_none = self.version
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9, self.assertInclude(f_arm, v_none)
False, False))
self.assertFalse(
symbolfile.should_omit_version(
symbolfile.Version('foo', None, Tags.from_strs(['arm']), []),
Arch('arm'), 9, False, False))
self.assertTrue( v_arm = copy(v_none)
symbolfile.should_omit_version( v_arm.tags = Tags.from_strs(['arm'])
symbolfile.Version('foo', None, Tags.from_strs(['x86']), []), self.assertInclude(f_arm, v_arm)
Arch('arm'), 9, False, False))
v_x86 = copy(v_none)
v_x86.tags = Tags.from_strs(['x86'])
self.assertOmit(f_arm, v_x86)
def test_omit_api(self) -> None: def test_omit_api(self) -> None:
self.assertFalse( f_api9 = self.filter
symbolfile.should_omit_version( v_none = self.version
symbolfile.Version('foo', None, Tags(), []), Arch('arm'), 9, self.assertInclude(f_api9, v_none)
False, False))
self.assertFalse(
symbolfile.should_omit_version(
symbolfile.Version('foo', None,
Tags.from_strs(['introduced=9']), []),
Arch('arm'), 9, False, False))
self.assertTrue( v_api9 = copy(v_none)
symbolfile.should_omit_version( v_api9.tags = Tags.from_strs(['introduced=9'])
symbolfile.Version('foo', None, self.assertInclude(f_api9, v_api9)
Tags.from_strs(['introduced=14']), []),
Arch('arm'), 9, False, False)) v_api14 = copy(v_none)
v_api14.tags = Tags.from_strs(['introduced=14'])
self.assertOmit(f_api9, v_api14)
class OmitSymbolTest(unittest.TestCase): class OmitSymbolTest(unittest.TestCase):
def test_omit_llndk(self) -> None: def setUp(self) -> None:
self.assertTrue( self.filter = Filter(arch = Arch('arm'), api = 9)
symbolfile.should_omit_symbol(
symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
Arch('arm'), 9, False, False))
self.assertFalse( def assertOmit(self, f: Filter, s: Symbol) -> None:
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()), self.assertTrue(f.should_omit_symbol(s))
Arch('arm'), 9, True, False))
self.assertFalse( def assertInclude(self, f: Filter, s: Symbol) -> None:
symbolfile.should_omit_symbol( self.assertFalse(f.should_omit_symbol(s))
symbolfile.Symbol('foo', Tags.from_strs(['llndk'])),
Arch('arm'), 9, True, False)) 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: def test_omit_apex(self) -> None:
self.assertTrue( f_none = self.filter
symbolfile.should_omit_symbol( f_apex = copy(f_none)
symbolfile.Symbol('foo', Tags.from_strs(['apex'])), f_apex.apex = True
Arch('arm'), 9, False, False))
self.assertFalse( s_none = Symbol('foo', Tags())
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()), s_apex = Symbol('foo', Tags.from_strs(['apex']))
Arch('arm'), 9, False, True)) s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
self.assertFalse(
symbolfile.should_omit_symbol( self.assertOmit(f_none, s_apex)
symbolfile.Symbol('foo', Tags.from_strs(['apex'])), self.assertInclude(f_apex, s_none)
Arch('arm'), 9, False, True)) self.assertInclude(f_apex, s_apex)
self.assertOmit(f_apex, s_systemapi)
def test_omit_systemapi(self) -> None: def test_omit_systemapi(self) -> None:
self.assertTrue( f_none = self.filter
symbolfile.should_omit_symbol( f_systemapi = copy(f_none)
symbolfile.Symbol('foo', Tags.from_strs(['systemapi'])), f_systemapi.systemapi = True
Arch('arm'), 9, False, False))
self.assertFalse( s_none = Symbol('foo', Tags())
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()), s_apex = Symbol('foo', Tags.from_strs(['apex']))
Arch('arm'), 9, False, True)) s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
self.assertFalse(
symbolfile.should_omit_symbol( self.assertOmit(f_none, s_systemapi)
symbolfile.Symbol('foo', Tags.from_strs(['systemapi'])), self.assertInclude(f_systemapi, s_none)
Arch('arm'), 9, False, True)) self.assertInclude(f_systemapi, s_systemapi)
self.assertOmit(f_systemapi, s_apex)
def test_omit_apex_and_systemapi(self) -> None:
f = self.filter
f.systemapi = True
f.apex = True
s_none = Symbol('foo', Tags())
s_apex = Symbol('foo', Tags.from_strs(['apex']))
s_systemapi = Symbol('foo', Tags.from_strs(['systemapi']))
self.assertInclude(f, s_none)
self.assertInclude(f, s_apex)
self.assertInclude(f, s_systemapi)
def test_omit_arch(self) -> None: def test_omit_arch(self) -> None:
self.assertFalse( f_arm = self.filter
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()), s_none = Symbol('foo', Tags())
Arch('arm'), 9, False, False)) s_arm = Symbol('foo', Tags.from_strs(['arm']))
self.assertFalse( s_x86 = Symbol('foo', Tags.from_strs(['x86']))
symbolfile.should_omit_symbol(
symbolfile.Symbol('foo', Tags.from_strs(['arm'])), Arch('arm'),
9, False, False))
self.assertTrue( self.assertInclude(f_arm, s_none)
symbolfile.should_omit_symbol( self.assertInclude(f_arm, s_arm)
symbolfile.Symbol('foo', Tags.from_strs(['x86'])), Arch('arm'), self.assertOmit(f_arm, s_x86)
9, False, False))
def test_omit_api(self) -> None: def test_omit_api(self) -> None:
self.assertFalse( f_api9 = self.filter
symbolfile.should_omit_symbol(symbolfile.Symbol('foo', Tags()), s_none = Symbol('foo', Tags())
Arch('arm'), 9, False, False)) s_api9 = Symbol('foo', Tags.from_strs(['introduced=9']))
self.assertFalse( s_api14 = Symbol('foo', Tags.from_strs(['introduced=14']))
symbolfile.should_omit_symbol(
symbolfile.Symbol('foo', Tags.from_strs(['introduced=9'])),
Arch('arm'), 9, False, False))
self.assertTrue( self.assertInclude(f_api9, s_none)
symbolfile.should_omit_symbol( self.assertInclude(f_api9, s_api9)
symbolfile.Symbol('foo', Tags.from_strs(['introduced=14'])), self.assertOmit(f_api9, s_api14)
Arch('arm'), 9, False, False))
class SymbolFileParseTest(unittest.TestCase): class SymbolFileParseTest(unittest.TestCase):
def setUp(self) -> None:
self.filter = Filter(arch = Arch('arm'), api = 16)
def test_next_line(self) -> None: def test_next_line(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\ input_file = io.StringIO(textwrap.dedent("""\
foo foo
@@ -382,8 +393,7 @@ class SymbolFileParseTest(unittest.TestCase):
# baz # baz
qux qux
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
self.assertIsNone(parser.current_line) self.assertIsNone(parser.current_line)
self.assertEqual('foo', parser.next_line().strip()) self.assertEqual('foo', parser.next_line().strip())
@@ -409,8 +419,7 @@ class SymbolFileParseTest(unittest.TestCase):
VERSION_2 { VERSION_2 {
} VERSION_1; # asdf } VERSION_1; # asdf
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
version = parser.parse_version() version = parser.parse_version()
@@ -419,8 +428,8 @@ class SymbolFileParseTest(unittest.TestCase):
self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags) self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags)
expected_symbols = [ expected_symbols = [
symbolfile.Symbol('baz', Tags()), Symbol('baz', Tags()),
symbolfile.Symbol('qux', Tags.from_strs(['woodly', 'doodly'])), Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
] ]
self.assertEqual(expected_symbols, version.symbols) self.assertEqual(expected_symbols, version.symbols)
@@ -434,8 +443,7 @@ class SymbolFileParseTest(unittest.TestCase):
input_file = io.StringIO(textwrap.dedent("""\ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 { VERSION_1 {
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
with self.assertRaises(symbolfile.ParseError): with self.assertRaises(symbolfile.ParseError):
parser.parse_version() parser.parse_version()
@@ -446,8 +454,7 @@ class SymbolFileParseTest(unittest.TestCase):
foo: foo:
} }
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
with self.assertRaises(symbolfile.ParseError): with self.assertRaises(symbolfile.ParseError):
parser.parse_version() parser.parse_version()
@@ -457,8 +464,7 @@ class SymbolFileParseTest(unittest.TestCase):
foo; foo;
bar; # baz qux bar; # baz qux
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
symbol = parser.parse_symbol() symbol = parser.parse_symbol()
@@ -476,8 +482,7 @@ class SymbolFileParseTest(unittest.TestCase):
*; *;
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
with self.assertRaises(symbolfile.ParseError): with self.assertRaises(symbolfile.ParseError):
parser.parse_version() parser.parse_version()
@@ -489,8 +494,7 @@ class SymbolFileParseTest(unittest.TestCase):
*; *;
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
version = parser.parse_version() version = parser.parse_version()
self.assertEqual([], version.symbols) self.assertEqual([], version.symbols)
@@ -501,8 +505,7 @@ class SymbolFileParseTest(unittest.TestCase):
foo foo
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
parser.next_line() parser.next_line()
with self.assertRaises(symbolfile.ParseError): with self.assertRaises(symbolfile.ParseError):
parser.parse_version() parser.parse_version()
@@ -510,8 +513,7 @@ class SymbolFileParseTest(unittest.TestCase):
def test_parse_fails_invalid_input(self) -> None: def test_parse_fails_invalid_input(self) -> None:
with self.assertRaises(symbolfile.ParseError): with self.assertRaises(symbolfile.ParseError):
input_file = io.StringIO('foo') input_file = io.StringIO('foo')
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
16, False, False)
parser.parse() parser.parse()
def test_parse(self) -> None: def test_parse(self) -> None:
@@ -532,19 +534,18 @@ class SymbolFileParseTest(unittest.TestCase):
qwerty; qwerty;
} VERSION_1; } VERSION_1;
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
False, False)
versions = parser.parse() versions = parser.parse()
expected = [ expected = [
symbolfile.Version('VERSION_1', None, Tags(), [ symbolfile.Version('VERSION_1', None, Tags(), [
symbolfile.Symbol('foo', Tags()), Symbol('foo', Tags()),
symbolfile.Symbol('bar', Tags.from_strs(['baz'])), Symbol('bar', Tags.from_strs(['baz'])),
]), ]),
symbolfile.Version( symbolfile.Version(
'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [ 'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [
symbolfile.Symbol('woodly', Tags()), Symbol('woodly', Tags()),
symbolfile.Symbol('doodly', Tags.from_strs(['asdf'])), Symbol('doodly', Tags.from_strs(['asdf'])),
]), ]),
] ]
@@ -559,8 +560,9 @@ class SymbolFileParseTest(unittest.TestCase):
qux; # apex qux; # apex
}; };
""")) """))
parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, f = copy(self.filter)
False, True) f.llndk = True
parser = symbolfile.SymbolFileParser(input_file, {}, f)
parser.next_line() parser.next_line()
version = parser.parse_version() version = parser.parse_version()
@@ -568,10 +570,10 @@ class SymbolFileParseTest(unittest.TestCase):
self.assertIsNone(version.base) self.assertIsNone(version.base)
expected_symbols = [ expected_symbols = [
symbolfile.Symbol('foo', Tags()), Symbol('foo', Tags()),
symbolfile.Symbol('bar', Tags.from_strs(['llndk'])), Symbol('bar', Tags.from_strs(['llndk'])),
symbolfile.Symbol('baz', Tags.from_strs(['llndk', 'apex'])), Symbol('baz', Tags.from_strs(['llndk', 'apex'])),
symbolfile.Symbol('qux', Tags.from_strs(['apex'])), Symbol('qux', Tags.from_strs(['apex'])),
] ]
self.assertEqual(expected_symbols, version.symbols) self.assertEqual(expected_symbols, version.symbols)