Add script to get prelim HAL VTS coverage.
See help message for example usage. Test: doctest Test: run with and without --csv Bug: 182810953 Change-Id: I6a4be9b543622618e2c594ba08a75534c60f3136
This commit is contained in:
parent
8548f574ee
commit
0077a9d530
1 changed files with 143 additions and 0 deletions
143
scripts/list_hal_vts.py
Executable file
143
scripts/list_hal_vts.py
Executable file
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
"""
|
||||
List VTS tests for each HAL by parsing module-info.json.
|
||||
|
||||
Example usage:
|
||||
|
||||
# First, build modules-info.json
|
||||
m -j "${ANDROID_PRODUCT_OUT#$ANDROID_BUILD_TOP/}/module-info.json"
|
||||
|
||||
# List with pretty-printed JSON. *IDL packages without a VTS module will show up
|
||||
# as keys with empty lists.
|
||||
./list_hals_vts.py | python3 -m json.tool
|
||||
|
||||
# List with CSV. *IDL packages without a VTS module will show up as a line with
|
||||
# empty value in the VTS module column.
|
||||
./list_hals_vts.py --csv
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import collections
|
||||
import csv
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
PATH_PACKAGE_PATTERN = re.compile(
|
||||
r'^hardware/interfaces/(?P<path>(?:\w+/)*?)(?:aidl|(?P<version>\d+\.\d+))/.*')
|
||||
|
||||
|
||||
class CriticalHandler(logging.StreamHandler):
|
||||
def emit(self, record):
|
||||
super(CriticalHandler, self).emit(record)
|
||||
if record.levelno >= logging.CRITICAL:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.addHandler(CriticalHandler())
|
||||
|
||||
|
||||
def default_json():
|
||||
out = os.environ.get('ANDROID_PRODUCT_OUT')
|
||||
if not out: return None
|
||||
return os.path.join(out, 'module-info.json')
|
||||
|
||||
|
||||
def infer_package(path):
|
||||
"""
|
||||
Infer package from a relative path from build top where a VTS module lives.
|
||||
|
||||
:param path: a path like 'hardware/interfaces/vibrator/aidl/vts'
|
||||
:return: The inferred *IDL package, e.g. 'android.hardware.vibrator'
|
||||
|
||||
>>> infer_package('hardware/interfaces/automotive/sv/1.0/vts/functional')
|
||||
'android.hardware.automotive.sv@1.0'
|
||||
>>> infer_package('hardware/interfaces/vibrator/aidl/vts')
|
||||
'android.hardware.vibrator'
|
||||
"""
|
||||
mo = re.match(PATH_PACKAGE_PATTERN, path)
|
||||
if not mo: return None
|
||||
package = 'android.hardware.' + ('.'.join(pathlib.Path(mo.group('path')).parts))
|
||||
if mo.group('version'):
|
||||
package += '@' + mo.group('version')
|
||||
return package
|
||||
|
||||
|
||||
def load_modules_info(json_file):
|
||||
"""
|
||||
:param json_file: The path to modules-info.json
|
||||
:return: a dictionary, where the keys are inferred *IDL package names, and
|
||||
values are a list of VTS modules with that inferred package name.
|
||||
"""
|
||||
with open(json_file) as fp:
|
||||
root = json.load(fp)
|
||||
ret = collections.defaultdict(list)
|
||||
for module_name, module_info in root.items():
|
||||
if 'vts' not in module_info.get('compatibility_suites', []):
|
||||
continue
|
||||
for path in module_info.get('path', []):
|
||||
inferred_package = infer_package(path)
|
||||
if not inferred_package:
|
||||
continue
|
||||
ret[inferred_package].append(module_name)
|
||||
return ret
|
||||
|
||||
|
||||
def add_missing_idl(vts_modules):
|
||||
top = os.environ.get("ANDROID_BUILD_TOP")
|
||||
interfaces = None
|
||||
if top:
|
||||
interfaces = os.path.join(top, "hardware", "interfaces")
|
||||
else:
|
||||
logger.warning("Missing ANDROID_BUILD_TOP")
|
||||
interfaces = "hardware/interfaces"
|
||||
if not os.path.isdir(interfaces):
|
||||
logger.error("Not adding missing *IDL modules because missing hardware/interfaces dir")
|
||||
return
|
||||
assert not interfaces.endswith(os.path.sep)
|
||||
for root, dirs, files in os.walk(interfaces):
|
||||
for dir in dirs:
|
||||
full_dir = os.path.join(root, dir)
|
||||
assert full_dir.startswith(interfaces)
|
||||
top_rel_dir = os.path.join('hardware', 'interfaces', full_dir[len(interfaces) + 1:])
|
||||
inferred_package = infer_package(top_rel_dir)
|
||||
if inferred_package is None:
|
||||
continue
|
||||
if inferred_package not in vts_modules:
|
||||
vts_modules[inferred_package] = []
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('json', metavar='module-info.json', default=default_json(), nargs='?')
|
||||
parser.add_argument('--csv', action='store_true', help='Print CSV. If not specified print JSON.')
|
||||
args = parser.parse_args()
|
||||
if not args.json:
|
||||
logger.critical('No module-info.json is specified or found.')
|
||||
vts_modules = load_modules_info(args.json)
|
||||
add_missing_idl(vts_modules)
|
||||
|
||||
if args.csv:
|
||||
out = io.StringIO()
|
||||
writer = csv.writer(out, )
|
||||
writer.writerow(["package", "vts_module"])
|
||||
for package, modules in vts_modules.items():
|
||||
if not modules:
|
||||
writer.writerow([package, ""])
|
||||
for module in modules:
|
||||
writer.writerow([package, module])
|
||||
result = out.getvalue()
|
||||
else:
|
||||
result = json.dumps(vts_modules)
|
||||
|
||||
print(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue