Merge "Extract a subset of the monolithic flags for comparison" am: 47c456228c

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

Change-Id: I21426be644f76009449b39d270e9c7ed45ea41eb
This commit is contained in:
Paul Duffin
2021-08-06 09:18:04 +00:00
committed by Automerger Merge Worker
2 changed files with 59 additions and 17 deletions

View File

@@ -19,10 +19,24 @@ Verify that one set of hidden API flags is a subset of another.
import argparse import argparse
import csv import csv
from itertools import chain
def dict_reader(input): def dict_reader(input):
return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature']) return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
def extract_subset_from_monolithic_flags_as_dict(monolithicFlagsDict, signatures):
"""
Extract a subset of flags from the dict containing all the monolithic flags.
:param monolithicFlagsDict: the dict containing all the monolithic flags.
:param signatures: a list of signature that define the subset.
:return: the dict from signature to row.
"""
dict = {}
for signature in signatures:
dict[signature] = monolithicFlagsDict.get(signature, {})
return dict
def read_signature_csv_from_stream_as_dict(stream): def read_signature_csv_from_stream_as_dict(stream):
""" """
Read the csv contents from the stream into a dict. The first column is assumed to be the Read the csv contents from the stream into a dict. The first column is assumed to be the
@@ -62,10 +76,14 @@ def compare_signature_flags(monolithicFlagsDict, modularFlagsDict):
modular dict, and monolithic dict respectively. modular dict, and monolithic dict respectively.
""" """
mismatchingSignatures = [] mismatchingSignatures = []
for signature, modularRow in modularFlagsDict.items(): # Create a sorted set of all the signatures from both the monolithic and
modularFlags = modularRow.get(None, []) # modular dicts.
allSignatures = sorted(set(chain(monolithicFlagsDict.keys(), modularFlagsDict.keys())))
for signature in allSignatures:
monolithicRow = monolithicFlagsDict.get(signature, {}) monolithicRow = monolithicFlagsDict.get(signature, {})
monolithicFlags = monolithicRow.get(None, []) monolithicFlags = monolithicRow.get(None, [])
modularRow = modularFlagsDict.get(signature, {})
modularFlags = modularRow.get(None, [])
if monolithicFlags != modularFlags: if monolithicFlags != modularFlags:
mismatchingSignatures.append((signature, modularFlags, monolithicFlags)) mismatchingSignatures.append((signature, modularFlags, monolithicFlags))
return mismatchingSignatures return mismatchingSignatures
@@ -80,10 +98,14 @@ def main(argv):
monolithicFlagsPath = args.monolithicFlags monolithicFlagsPath = args.monolithicFlags
monolithicFlagsDict = read_signature_csv_from_file_as_dict(monolithicFlagsPath) monolithicFlagsDict = read_signature_csv_from_file_as_dict(monolithicFlagsPath)
# For each subset specified on the command line, create dicts for the flags
# provided by the subset and the corresponding flags from the complete set of
# flags and compare them.
failed = False failed = False
for modularFlagsPath in args.modularFlags: for modularFlagsPath in args.modularFlags:
modularFlagsDict = read_signature_csv_from_file_as_dict(modularFlagsPath) modularFlagsDict = read_signature_csv_from_file_as_dict(modularFlagsPath)
mismatchingSignatures = compare_signature_flags(monolithicFlagsDict, modularFlagsDict) monolithicFlagsSubsetDict = extract_subset_from_monolithic_flags_as_dict(monolithicFlagsDict, modularFlagsDict.keys())
mismatchingSignatures = compare_signature_flags(monolithicFlagsSubsetDict, modularFlagsDict)
if mismatchingSignatures: if mismatchingSignatures:
failed = True failed = True
print("ERROR: Hidden API flags are inconsistent:") print("ERROR: Hidden API flags are inconsistent:")

View File

@@ -26,10 +26,28 @@ class TestDetectOverlaps(unittest.TestCase):
with io.StringIO(csv) as f: with io.StringIO(csv) as f:
return read_signature_csv_from_stream_as_dict(f) return read_signature_csv_from_stream_as_dict(f)
extractInput = '''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
'''
def test_extract_subset(self):
monolithic = self.read_signature_csv_from_string_as_dict(TestDetectOverlaps.extractInput)
modular = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
''')
subset = extract_subset_from_monolithic_flags_as_dict(monolithic, modular.keys())
expected = {
'Ljava/lang/Object;->hashCode()I': {
None: ['public-api', 'system-api', 'test-api'],
'signature': 'Ljava/lang/Object;->hashCode()I',
},
}
self.assertEqual(expected, subset)
def test_match(self): def test_match(self):
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
''') ''')
modular = self.read_signature_csv_from_string_as_dict(''' modular = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
@@ -58,7 +76,6 @@ Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
def test_mismatch_monolithic_blocked(self): def test_mismatch_monolithic_blocked(self):
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
''') ''')
modular = self.read_signature_csv_from_string_as_dict(''' modular = self.read_signature_csv_from_string_as_dict('''
@@ -76,7 +93,6 @@ Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
def test_mismatch_modular_blocked(self): def test_mismatch_modular_blocked(self):
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
''') ''')
modular = self.read_signature_csv_from_string_as_dict(''' modular = self.read_signature_csv_from_string_as_dict('''
@@ -93,9 +109,7 @@ Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
self.assertEqual(expected, mismatches) self.assertEqual(expected, mismatches)
def test_missing_from_monolithic(self): def test_missing_from_monolithic(self):
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('')
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
''')
modular = self.read_signature_csv_from_string_as_dict(''' modular = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
''') ''')
@@ -110,27 +124,33 @@ Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
self.assertEqual(expected, mismatches) self.assertEqual(expected, mismatches)
def test_missing_from_modular(self): def test_missing_from_modular(self):
# The modular dict defines the set of signatures to compare so an entry
# in the monolithic dict that does not have a corresponding entry in the
# modular dict is ignored.
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
''') ''')
modular = {} modular = {}
mismatches = compare_signature_flags(monolithic, modular) mismatches = compare_signature_flags(monolithic, modular)
expected = [] expected = [
(
'Ljava/lang/Object;->hashCode()I',
[],
['public-api', 'system-api', 'test-api'],
),
]
self.assertEqual(expected, mismatches) self.assertEqual(expected, mismatches)
def test_blocked_missing_from_modular(self): def test_blocked_missing_from_modular(self):
# The modular dict defines the set of signatures to compare so an entry
# in the monolithic dict that does not have a corresponding entry in the
# modular dict is ignored.
monolithic = self.read_signature_csv_from_string_as_dict(''' monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,blocked Ljava/lang/Object;->hashCode()I,blocked
''') ''')
modular = {} modular = {}
mismatches = compare_signature_flags(monolithic, modular) mismatches = compare_signature_flags(monolithic, modular)
expected = [] expected = [
(
'Ljava/lang/Object;->hashCode()I',
[],
['blocked'],
),
]
self.assertEqual(expected, mismatches) self.assertEqual(expected, mismatches)
if __name__ == '__main__': if __name__ == '__main__':