blob: b5ca30c04311b0c53f7df44cdc3aa03d9313636b [file] [log] [blame]
Paul Duffindfa10832021-05-13 17:31:51 +01001#!/usr/bin/env python
2#
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16"""
17Verify that one set of hidden API flags is a subset of another.
18"""
19
20import argparse
21import csv
22
Paul Duffindfa10832021-05-13 17:31:51 +010023def dict_reader(input):
24 return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
25
Paul Duffin428c6512021-07-21 15:33:22 +010026def read_signature_csv_from_stream_as_dict(stream):
27 """
28 Read the csv contents from the stream into a dict. The first column is assumed to be the
29 signature and used as the key. The whole row is stored as the value.
30
31 :param stream: the csv contents to read
32 :return: the dict from signature to row.
33 """
34 dict = {}
35 reader = dict_reader(stream)
36 for row in reader:
Paul Duffindfa10832021-05-13 17:31:51 +010037 signature = row['signature']
Paul Duffin428c6512021-07-21 15:33:22 +010038 dict[signature] = row
39 return dict
Paul Duffindfa10832021-05-13 17:31:51 +010040
Paul Duffin428c6512021-07-21 15:33:22 +010041def read_signature_csv_from_file_as_dict(csvFile):
42 """
43 Read the csvFile into a dict. The first column is assumed to be the
44 signature and used as the key. The whole row is stored as the value.
45
46 :param csvFile: the csv file to read
47 :return: the dict from signature to row.
48 """
49 with open(csvFile, 'r') as f:
50 return read_signature_csv_from_stream_as_dict(f)
51
52def compare_signature_flags(monolithicFlagsDict, modularFlagsDict):
53 """
54 Compare the signature flags between the two dicts.
55
56 :param monolithicFlagsDict: the dict containing the subset of the monolithic
57 flags that should be equal to the modular flags.
58 :param modularFlagsDict:the dict containing the flags produced by a single
59 bootclasspath_fragment module.
60 :return: list of mismatches., each mismatch is a tuple where the first item
61 is the signature, and the second and third items are lists of the flags from
62 modular dict, and monolithic dict respectively.
63 """
Paul Duffindfa10832021-05-13 17:31:51 +010064 mismatchingSignatures = []
Paul Duffin428c6512021-07-21 15:33:22 +010065 for signature, modularRow in modularFlagsDict.items():
66 modularFlags = modularRow.get(None, [])
67 monolithicRow = monolithicFlagsDict.get(signature, {})
68 monolithicFlags = monolithicRow.get(None, [])
69 if monolithicFlags != modularFlags:
70 mismatchingSignatures.append((signature, modularFlags, monolithicFlags))
71 return mismatchingSignatures
Paul Duffindfa10832021-05-13 17:31:51 +010072
Paul Duffin428c6512021-07-21 15:33:22 +010073def main(argv):
Paul Duffin7be96332021-07-21 16:13:03 +010074 args_parser = argparse.ArgumentParser(description='Verify that sets of hidden API flags are each a subset of the monolithic flag file.')
75 args_parser.add_argument('monolithicFlags', help='The monolithic flag file')
76 args_parser.add_argument('modularFlags', nargs=argparse.REMAINDER, help='Flags produced by individual bootclasspath_fragment modules')
Paul Duffin428c6512021-07-21 15:33:22 +010077 args = args_parser.parse_args(argv[1:])
Paul Duffindfa10832021-05-13 17:31:51 +010078
Paul Duffin7be96332021-07-21 16:13:03 +010079 # Read in the monolithic flags into a dict indexed by signature
80 monolithicFlagsPath = args.monolithicFlags
81 monolithicFlagsDict = read_signature_csv_from_file_as_dict(monolithicFlagsPath)
Paul Duffindfa10832021-05-13 17:31:51 +010082
Paul Duffin428c6512021-07-21 15:33:22 +010083 failed = False
Paul Duffin7be96332021-07-21 16:13:03 +010084 for modularFlagsPath in args.modularFlags:
85 modularFlagsDict = read_signature_csv_from_file_as_dict(modularFlagsPath)
86 mismatchingSignatures = compare_signature_flags(monolithicFlagsDict, modularFlagsDict)
Paul Duffin428c6512021-07-21 15:33:22 +010087 if mismatchingSignatures:
88 failed = True
89 print("ERROR: Hidden API flags are inconsistent:")
Paul Duffin7be96332021-07-21 16:13:03 +010090 print("< " + modularFlagsPath)
91 print("> " + monolithicFlagsPath)
Paul Duffin428c6512021-07-21 15:33:22 +010092 for mismatch in mismatchingSignatures:
93 signature = mismatch[0]
94 print()
95 print("< " + ",".join([signature]+ mismatch[1]))
96 print("> " + ",".join([signature]+ mismatch[2]))
97
98 if failed:
99 sys.exit(1)
100
101if __name__ == "__main__":
102 main(sys.argv)