Apply pylint to scripts/hiddenapi/generate_hiddenapi_lists*

1. Run pyformat scripts/hiddenapi/generate_hiddenapi_lists.py -s 4
--force_quote_type none -i to fix formatting. Some double quotes change
to single quotes since pyformat enforces consistent quotes
2. change map/filter to list comprehension to fix pylint's bad-builtin
warning
3. use pylint: disable=<X> where fixes are not obvious

Test: m generate_hiddenapi_lists_test
Test: pylint --rcfile tools/repohooks/tools/pylintrc <file1>
<file1_test>
Bug: 195738175

Change-Id: I15e71d8d81f0e3fa66d84e6e62eb1848963136e6
This commit is contained in:
Spandan Das
2021-08-25 17:35:37 +00:00
parent 7c16dabfa5
commit c2c31b13dc
2 changed files with 167 additions and 110 deletions

View File

@@ -16,8 +16,6 @@
"""Generate API lists for non-SDK API enforcement.""" """Generate API lists for non-SDK API enforcement."""
import argparse import argparse
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
import functools
import os
import re import re
import sys import sys
@@ -60,15 +58,15 @@ ALL_FLAGS_SET = set(ALL_FLAGS)
# For example, the max-target-P list is checked in as it was in P, # For example, the max-target-P list is checked in as it was in P,
# but signatures have changes since then. The flag instructs this # but signatures have changes since then. The flag instructs this
# script to skip any entries which do not exist any more. # script to skip any entries which do not exist any more.
FLAG_IGNORE_CONFLICTS = "ignore-conflicts" FLAG_IGNORE_CONFLICTS = 'ignore-conflicts'
# Option specified after one of FLAGS_API_LIST to express that all # Option specified after one of FLAGS_API_LIST to express that all
# apis within a given set of packages should be assign the given flag. # apis within a given set of packages should be assign the given flag.
FLAG_PACKAGES = "packages" FLAG_PACKAGES = 'packages'
# Option specified after one of FLAGS_API_LIST to indicate an extra # Option specified after one of FLAGS_API_LIST to indicate an extra
# tag that should be added to the matching APIs. # tag that should be added to the matching APIs.
FLAG_TAG = "tag" FLAG_TAG = 'tag'
# Regex patterns of fields/methods used in serialization. These are # Regex patterns of fields/methods used in serialization. These are
# considered public API despite being hidden. # considered public API despite being hidden.
@@ -84,24 +82,30 @@ SERIALIZATION_PATTERNS = [
# Single regex used to match serialization API. It combines all the # Single regex used to match serialization API. It combines all the
# SERIALIZATION_PATTERNS into a single regular expression. # SERIALIZATION_PATTERNS into a single regular expression.
SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r')$') SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) +
r')$')
# Predicates to be used with filter_apis. # Predicates to be used with filter_apis.
HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags) HAS_NO_API_LIST_ASSIGNED = \
lambda api,flags: not FLAGS_API_LIST_SET.intersection(flags)
IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api)
class StoreOrderedOptions(argparse.Action): class StoreOrderedOptions(argparse.Action):
"""An argparse action that stores a number of option arguments in the order that """An argparse action that stores a number of option arguments in the order
they were specified.
that they were specified.
""" """
def __call__(self, parser, args, values, option_string = None):
def __call__(self, parser, args, values, option_string=None):
items = getattr(args, self.dest, None) items = getattr(args, self.dest, None)
if items is None: if items is None:
items = [] items = []
items.append([option_string.lstrip('-'), values]) items.append([option_string.lstrip('-'), values])
setattr(args, self.dest, items) setattr(args, self.dest, items)
def get_args(): def get_args():
"""Parses command line arguments. """Parses command line arguments.
@@ -110,22 +114,43 @@ def get_args():
""" """
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--output', required=True) parser.add_argument('--output', required=True)
parser.add_argument('--csv', nargs='*', default=[], metavar='CSV_FILE', parser.add_argument(
'--csv',
nargs='*',
default=[],
metavar='CSV_FILE',
help='CSV files to be merged into output') help='CSV files to be merged into output')
for flag in ALL_FLAGS: for flag in ALL_FLAGS:
parser.add_argument('--' + flag, dest='ordered_flags', metavar='TXT_FILE', parser.add_argument(
action=StoreOrderedOptions, help='lists of entries with flag "' + flag + '"') '--' + flag,
parser.add_argument('--' + FLAG_IGNORE_CONFLICTS, dest='ordered_flags', nargs=0, dest='ordered_flags',
action=StoreOrderedOptions, help='Indicates that only known and otherwise unassigned ' metavar='TXT_FILE',
'entries should be assign the given flag. Must follow a list of entries and applies ' action=StoreOrderedOptions,
'to the preceding such list.') help='lists of entries with flag "' + flag + '"')
parser.add_argument('--' + FLAG_PACKAGES, dest='ordered_flags', nargs=0, parser.add_argument(
action=StoreOrderedOptions, help='Indicates that the previous list of entries ' '--' + FLAG_IGNORE_CONFLICTS,
'is a list of packages. All members in those packages will be given the flag. ' dest='ordered_flags',
'Must follow a list of entries and applies to the preceding such list.') nargs=0,
parser.add_argument('--' + FLAG_TAG, dest='ordered_flags', nargs=1, action=StoreOrderedOptions,
action=StoreOrderedOptions, help='Adds an extra tag to the previous list of entries. ' help='Indicates that only known and otherwise unassigned '
'entries should be assign the given flag. Must follow a list of '
'entries and applies to the preceding such list.')
parser.add_argument(
'--' + FLAG_PACKAGES,
dest='ordered_flags',
nargs=0,
action=StoreOrderedOptions,
help='Indicates that the previous list of entries '
'is a list of packages. All members in those packages will be given '
'the flag. Must follow a list of entries and applies to the preceding '
'such list.')
parser.add_argument(
'--' + FLAG_TAG,
dest='ordered_flags',
nargs=1,
action=StoreOrderedOptions,
help='Adds an extra tag to the previous list of entries. '
'Must follow a list of entries and applies to the preceding such list.') 'Must follow a list of entries and applies to the preceding such list.')
return parser.parse_args() return parser.parse_args()
@@ -143,9 +168,9 @@ def read_lines(filename):
Lines of the file as a list of string. Lines of the file as a list of string.
""" """
with open(filename, 'r') as f: with open(filename, 'r') as f:
lines = f.readlines(); lines = f.readlines()
lines = filter(lambda line: not line.startswith('#'), lines) lines = [line for line in lines if not line.startswith('#')]
lines = map(lambda line: line.strip(), lines) lines = [line.strip() for line in lines]
return set(lines) return set(lines)
@@ -156,7 +181,7 @@ def write_lines(filename, lines):
filename (string): Path to the file to be writing into. filename (string): Path to the file to be writing into.
lines (list): List of strings to write into the file. lines (list): List of strings to write into the file.
""" """
lines = map(lambda line: line + '\n', lines) lines = [line + '\n' for line in lines]
with open(filename, 'w') as f: with open(filename, 'w') as f:
f.writelines(lines) f.writelines(lines)
@@ -170,17 +195,19 @@ def extract_package(signature):
Returns: Returns:
The package name of the class containing the field/method. The package name of the class containing the field/method.
""" """
full_class_name = signature.split(";->")[0] full_class_name = signature.split(';->')[0]
# Example: Landroid/hardware/radio/V1_2/IRadio$Proxy # Example: Landroid/hardware/radio/V1_2/IRadio$Proxy
if (full_class_name[0] != "L"): if full_class_name[0] != 'L':
raise ValueError("Expected to start with 'L': %s" % full_class_name) raise ValueError("Expected to start with 'L': %s"
% full_class_name)
full_class_name = full_class_name[1:] full_class_name = full_class_name[1:]
# If full_class_name doesn't contain '/', then package_name will be ''. # If full_class_name doesn't contain '/', then package_name will be ''.
package_name = full_class_name.rpartition("/")[0] package_name = full_class_name.rpartition('/')[0]
return package_name.replace('/', '.') return package_name.replace('/', '.')
class FlagsDict: class FlagsDict:
def __init__(self): def __init__(self):
self._dict_keyset = set() self._dict_keyset = set()
self._dict = defaultdict(set) self._dict = defaultdict(set)
@@ -188,37 +215,43 @@ class FlagsDict:
def _check_entries_set(self, keys_subset, source): def _check_entries_set(self, keys_subset, source):
assert isinstance(keys_subset, set) assert isinstance(keys_subset, set)
assert keys_subset.issubset(self._dict_keyset), ( assert keys_subset.issubset(self._dict_keyset), (
"Error: {} specifies signatures not present in code:\n" 'Error: {} specifies signatures not present in code:\n'
"{}" '{}'
"Please visit go/hiddenapi for more information.").format( 'Please visit go/hiddenapi for more information.').format(
source, "".join(map(lambda x: " " + str(x) + "\n", keys_subset - self._dict_keyset))) source, ''.join(
[' ' + str(x) + '\n' for x in
keys_subset - self._dict_keyset]))
def _check_flags_set(self, flags_subset, source): def _check_flags_set(self, flags_subset, source):
assert isinstance(flags_subset, set) assert isinstance(flags_subset, set)
assert flags_subset.issubset(ALL_FLAGS_SET), ( assert flags_subset.issubset(ALL_FLAGS_SET), (
"Error processing: {}\n" 'Error processing: {}\n'
"The following flags were not recognized: \n" 'The following flags were not recognized: \n'
"{}\n" '{}\n'
"Please visit go/hiddenapi for more information.").format( 'Please visit go/hiddenapi for more information.').format(
source, "\n".join(flags_subset - ALL_FLAGS_SET)) source, '\n'.join(flags_subset - ALL_FLAGS_SET))
def filter_apis(self, filter_fn): def filter_apis(self, filter_fn):
"""Returns APIs which match a given predicate. """Returns APIs which match a given predicate.
This is a helper function which allows to filter on both signatures (keys) and This is a helper function which allows to filter on both signatures
flags (values). The built-in filter() invokes the lambda only with dict's keys. (keys) and
flags (values). The built-in filter() invokes the lambda only with
dict's keys.
Args: Args:
filter_fn : Function which takes two arguments (signature/flags) and returns a boolean. filter_fn : Function which takes two arguments (signature/flags) and
returns a boolean.
Returns: Returns:
A set of APIs which match the predicate. A set of APIs which match the predicate.
""" """
return set(filter(lambda x: filter_fn(x, self._dict[x]), self._dict_keyset)) return {x for x in self._dict_keyset if filter_fn(x, self._dict[x])}
def get_valid_subset_of_unassigned_apis(self, api_subset): def get_valid_subset_of_unassigned_apis(self, api_subset):
"""Sanitizes a key set input to only include keys which exist in the dictionary """Sanitizes a key set input to only include keys which exist in the
and have not been assigned any API list flags.
dictionary and have not been assigned any API list flags.
Args: Args:
entries_subset (set/list): Key set to be sanitized. entries_subset (set/list): Key set to be sanitized.
@@ -227,7 +260,8 @@ class FlagsDict:
Sanitized key set. Sanitized key set.
""" """
assert isinstance(api_subset, set) assert isinstance(api_subset, set)
return api_subset.intersection(self.filter_apis(HAS_NO_API_LIST_ASSIGNED)) return api_subset.intersection(
self.filter_apis(HAS_NO_API_LIST_ASSIGNED))
def generate_csv(self): def generate_csv(self):
"""Constructs CSV entries from a dictionary. """Constructs CSV entries from a dictionary.
@@ -235,15 +269,16 @@ class FlagsDict:
Old versions of flags are used to generate the file. Old versions of flags are used to generate the file.
Returns: Returns:
List of lines comprising a CSV file. See "parse_and_merge_csv" for format description. List of lines comprising a CSV file. See "parse_and_merge_csv" for
format description.
""" """
lines = [] lines = []
for api in self._dict: for api in self._dict:
flags = sorted(self._dict[api]) flags = sorted(self._dict[api])
lines.append(",".join([api] + flags)) lines.append(','.join([api] + flags))
return sorted(lines) return sorted(lines)
def parse_and_merge_csv(self, csv_lines, source = "<unknown>"): def parse_and_merge_csv(self, csv_lines, source='<unknown>'):
"""Parses CSV entries and merges them into a given dictionary. """Parses CSV entries and merges them into a given dictionary.
The expected CSV format is: The expected CSV format is:
@@ -251,16 +286,15 @@ class FlagsDict:
Args: Args:
csv_lines (list of strings): Lines read from a CSV file. csv_lines (list of strings): Lines read from a CSV file.
source (string): Origin of `csv_lines`. Will be printed in error messages. source (string): Origin of `csv_lines`. Will be printed in error
messages.
Throws: Throws: AssertionError if parsed flags are invalid.
AssertionError if parsed flags are invalid.
""" """
# Split CSV lines into arrays of values. # Split CSV lines into arrays of values.
csv_values = [ line.split(',') for line in csv_lines ] csv_values = [line.split(',') for line in csv_lines]
# Update the full set of API signatures. # Update the full set of API signatures.
self._dict_keyset.update([ csv[0] for csv in csv_values ]) self._dict_keyset.update([csv[0] for csv in csv_values])
# Check that all flags are known. # Check that all flags are known.
csv_flags = set() csv_flags = set()
@@ -275,47 +309,53 @@ class FlagsDict:
flags.append(FLAG_SDK) flags.append(FLAG_SDK)
self._dict[csv[0]].update(flags) self._dict[csv[0]].update(flags)
def assign_flag(self, flag, apis, source="<unknown>", tag = None): def assign_flag(self, flag, apis, source='<unknown>', tag=None):
"""Assigns a flag to given subset of entries. """Assigns a flag to given subset of entries.
Args: Args:
flag (string): One of ALL_FLAGS. flag (string): One of ALL_FLAGS.
apis (set): Subset of APIs to receive the flag. apis (set): Subset of APIs to receive the flag.
source (string): Origin of `entries_subset`. Will be printed in error messages. source (string): Origin of `entries_subset`. Will be printed in
error messages.
Throws: Throws: AssertionError if parsed API signatures of flags are invalid.
AssertionError if parsed API signatures of flags are invalid.
""" """
# Check that all APIs exist in the dict. # Check that all APIs exist in the dict.
self._check_entries_set(apis, source) self._check_entries_set(apis, source)
# Check that the flag is known. # Check that the flag is known.
self._check_flags_set(set([ flag ]), source) self._check_flags_set(set([flag]), source)
# Iterate over the API subset, find each entry in dict and assign the flag to it. # Iterate over the API subset, find each entry in dict and assign the
# flag to it.
for api in apis: for api in apis:
self._dict[api].add(flag) self._dict[api].add(flag)
if tag: if tag:
self._dict[api].add(tag) self._dict[api].add(tag)
FlagFile = namedtuple('FlagFile', ('flag', 'file', 'ignore_conflicts', 'packages', 'tag')) FlagFile = namedtuple('FlagFile',
('flag', 'file', 'ignore_conflicts', 'packages', 'tag'))
def parse_ordered_flags(ordered_flags): def parse_ordered_flags(ordered_flags):
r = [] r = []
currentflag, file, ignore_conflicts, packages, tag = None, None, False, False, None currentflag, file, ignore_conflicts, packages, tag = None, None, False, \
False, None
for flag_value in ordered_flags: for flag_value in ordered_flags:
flag, value = flag_value[0], flag_value[1] flag, value = flag_value[0], flag_value[1]
if flag in ALL_FLAGS_SET: if flag in ALL_FLAGS_SET:
if currentflag: if currentflag:
r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) r.append(
FlagFile(currentflag, file, ignore_conflicts, packages,
tag))
ignore_conflicts, packages, tag = False, False, None ignore_conflicts, packages, tag = False, False, None
currentflag = flag currentflag = flag
file = value file = value
else: else:
if currentflag is None: if currentflag is None:
raise argparse.ArgumentError('--%s is only allowed after one of %s' % ( raise argparse.ArgumentError( #pylint: disable=no-value-for-parameter
flag, ' '.join(['--%s' % f for f in ALL_FLAGS_SET]))) '--%s is only allowed after one of %s' %
(flag, ' '.join(['--%s' % f for f in ALL_FLAGS_SET])))
if flag == FLAG_IGNORE_CONFLICTS: if flag == FLAG_IGNORE_CONFLICTS:
ignore_conflicts = True ignore_conflicts = True
elif flag == FLAG_PACKAGES: elif flag == FLAG_PACKAGES:
@@ -323,13 +363,12 @@ def parse_ordered_flags(ordered_flags):
elif flag == FLAG_TAG: elif flag == FLAG_TAG:
tag = value[0] tag = value[0]
if currentflag: if currentflag:
r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag)) r.append(FlagFile(currentflag, file, ignore_conflicts, packages, tag))
return r return r
def main(argv): def main(argv): #pylint: disable=unused-argument
# Parse arguments. # Parse arguments.
args = vars(get_args()) args = vars(get_args())
flagfiles = parse_ordered_flags(args['ordered_flags'] or []) flagfiles = parse_ordered_flags(args['ordered_flags'] or [])
@@ -342,7 +381,7 @@ def main(argv):
# contain the full set of APIs. Subsequent additions from text files # contain the full set of APIs. Subsequent additions from text files
# will be able to detect invalid entries, and/or filter all as-yet # will be able to detect invalid entries, and/or filter all as-yet
# unassigned entries. # unassigned entries.
for filename in args["csv"]: for filename in args['csv']:
flags.parse_and_merge_csv(read_lines(filename), filename) flags.parse_and_merge_csv(read_lines(filename), filename)
# Combine inputs which do not require any particular order. # Combine inputs which do not require any particular order.
@@ -352,24 +391,28 @@ def main(argv):
# (2) Merge text files with a known flag into the dictionary. # (2) Merge text files with a known flag into the dictionary.
for info in flagfiles: for info in flagfiles:
if (not info.ignore_conflicts) and (not info.packages): if (not info.ignore_conflicts) and (not info.packages):
flags.assign_flag(info.flag, read_lines(info.file), info.file, info.tag) flags.assign_flag(info.flag, read_lines(info.file), info.file,
info.tag)
# Merge text files where conflicts should be ignored. # Merge text files where conflicts should be ignored.
# This will only assign the given flag if: # This will only assign the given flag if:
# (a) the entry exists, and # (a) the entry exists, and
# (b) it has not been assigned any other flag. # (b) it has not been assigned any other flag.
# Because of (b), this must run after all strict assignments have been performed. # Because of (b), this must run after all strict assignments have been
# performed.
for info in flagfiles: for info in flagfiles:
if info.ignore_conflicts: if info.ignore_conflicts:
valid_entries = flags.get_valid_subset_of_unassigned_apis(read_lines(info.file)) valid_entries = flags.get_valid_subset_of_unassigned_apis(
flags.assign_flag(info.flag, valid_entries, filename, info.tag) read_lines(info.file))
flags.assign_flag(info.flag, valid_entries, filename, info.tag) #pylint: disable=undefined-loop-variable
# All members in the specified packages will be assigned the appropriate flag. # All members in the specified packages will be assigned the appropriate
# flag.
for info in flagfiles: for info in flagfiles:
if info.packages: if info.packages:
packages_needing_list = set(read_lines(info.file)) packages_needing_list = set(read_lines(info.file))
should_add_signature_to_list = lambda sig,lists: extract_package( should_add_signature_to_list = lambda sig, lists: extract_package(
sig) in packages_needing_list and not lists sig) in packages_needing_list and not lists #pylint: disable=cell-var-from-loop
valid_entries = flags.filter_apis(should_add_signature_to_list) valid_entries = flags.filter_apis(should_add_signature_to_list)
flags.assign_flag(info.flag, valid_entries, info.file, info.tag) flags.assign_flag(info.flag, valid_entries, info.file, info.tag)
@@ -377,7 +420,8 @@ def main(argv):
flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED))
# Write output. # Write output.
write_lines(args["output"], flags.generate_csv()) write_lines(args['output'], flags.generate_csv())
if __name__ == "__main__":
if __name__ == '__main__':
main(sys.argv) main(sys.argv)

View File

@@ -15,34 +15,39 @@
# limitations under the License. # limitations under the License.
"""Unit tests for Hidden API list generation.""" """Unit tests for Hidden API list generation."""
import unittest import unittest
from generate_hiddenapi_lists import * from generate_hiddenapi_lists import * # pylint: disable=wildcard-import,unused-wildcard-import
class TestHiddenapiListGeneration(unittest.TestCase): class TestHiddenapiListGeneration(unittest.TestCase):
def test_filter_apis(self): def test_filter_apis(self):
# Initialize flags so that A and B are put on the allow list and # Initialize flags so that A and B are put on the allow list and
# C, D, E are left unassigned. Try filtering for the unassigned ones. # C, D, E are left unassigned. Try filtering for the unassigned ones.
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK, flags.parse_and_merge_csv(
'C', 'D', 'E']) ['A,' + FLAG_SDK, 'B,' + FLAG_SDK, 'C', 'D', 'E']
)
filter_set = flags.filter_apis(lambda api, flags: not flags) filter_set = flags.filter_apis(lambda api, flags: not flags)
self.assertTrue(isinstance(filter_set, set)) self.assertTrue(isinstance(filter_set, set))
self.assertEqual(filter_set, set([ 'C', 'D', 'E' ])) self.assertEqual(filter_set, set(['C', 'D', 'E']))
def test_get_valid_subset_of_unassigned_keys(self): def test_get_valid_subset_of_unassigned_keys(self):
# Create flags where only A is unassigned. # Create flags where only A is unassigned.
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C']) flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C'])
flags.assign_flag(FLAG_UNSUPPORTED, set(['C'])) flags.assign_flag(FLAG_UNSUPPORTED, set(['C']))
self.assertEqual(flags.generate_csv(), self.assertEqual(
[ 'A,' + FLAG_SDK, 'B', 'C,' + FLAG_UNSUPPORTED ]) flags.generate_csv(),
['A,' + FLAG_SDK, 'B', 'C,' + FLAG_UNSUPPORTED],
)
# Check three things: # Check three things:
# (1) B is selected as valid unassigned # (1) B is selected as valid unassigned
# (2) A is not selected because it is assigned to the allow list # (2) A is not selected because it is assigned to the allow list
# (3) D is not selected because it is not a valid key # (3) D is not selected because it is not a valid key
self.assertEqual( self.assertEqual(
flags.get_valid_subset_of_unassigned_apis(set(['A', 'B', 'D'])), set([ 'B' ])) flags.get_valid_subset_of_unassigned_apis(set(['A', 'B', 'D'])),
set(['B']),
)
def test_parse_and_merge_csv(self): def test_parse_and_merge_csv(self):
flags = FlagsDict() flags = FlagsDict()
@@ -51,41 +56,48 @@ class TestHiddenapiListGeneration(unittest.TestCase):
self.assertEqual(flags.generate_csv(), []) self.assertEqual(flags.generate_csv(), [])
# Test new additions. # Test new additions.
flags.parse_and_merge_csv([ flags.parse_and_merge_csv(
[
'A,' + FLAG_UNSUPPORTED, 'A,' + FLAG_UNSUPPORTED,
'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O, 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O,
'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API, 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API,
'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API, 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API,
'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API,
]) ]
self.assertEqual(flags.generate_csv(), [ )
self.assertEqual(
flags.generate_csv(),
[
'A,' + FLAG_UNSUPPORTED, 'A,' + FLAG_UNSUPPORTED,
'B,' + FLAG_BLOCKED + "," + FLAG_MAX_TARGET_O, 'B,' + FLAG_BLOCKED + "," + FLAG_MAX_TARGET_O,
'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API, 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API,
'D,' + FLAG_TEST_API + ',' + FLAG_UNSUPPORTED, 'D,' + FLAG_TEST_API + ',' + FLAG_UNSUPPORTED,
'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API, 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API,
]) ],
)
# Test unknown flag. # Test unknown flag.
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
flags.parse_and_merge_csv([ 'Z,foo' ]) flags.parse_and_merge_csv(['Z,foo'])
def test_assign_flag(self): def test_assign_flag(self):
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B']) flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B'])
# Test new additions. # Test new additions.
flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ])) flags.assign_flag(FLAG_UNSUPPORTED, set(['A', 'B']))
self.assertEqual(flags.generate_csv(), self.assertEqual(
[ 'A,' + FLAG_SDK + "," + FLAG_UNSUPPORTED, 'B,' + FLAG_UNSUPPORTED ]) flags.generate_csv(),
['A,' + FLAG_SDK + "," + FLAG_UNSUPPORTED, 'B,' + FLAG_UNSUPPORTED],
)
# Test invalid API signature. # Test invalid API signature.
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
flags.assign_flag(FLAG_SDK, set([ 'C' ])) flags.assign_flag(FLAG_SDK, set(['C']))
# Test invalid flag. # Test invalid flag.
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
flags.assign_flag('foo', set([ 'A' ])) flags.assign_flag('foo', set(['A']))
def test_extract_package(self): def test_extract_package(self):
signature = 'Lcom/foo/bar/Baz;->method1()Lcom/bar/Baz;' signature = 'Lcom/foo/bar/Baz;->method1()Lcom/bar/Baz;'
@@ -100,5 +112,6 @@ class TestHiddenapiListGeneration(unittest.TestCase):
expected_package = 'com.foo_bar.baz' expected_package = 'com.foo_bar.baz'
self.assertEqual(extract_package(signature), expected_package) self.assertEqual(extract_package(signature), expected_package)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main(verbosity=2) unittest.main(verbosity=2)