| #!/usr/bin/python2 |
| |
| # Copyright (c) 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Method to add or modify ATTRIBUTES in the test control files whose |
| ATTRIBUTES either not match to SUITE or not in the attribute allowlist.""" |
| |
| import argparse |
| import logging |
| import os |
| import sys |
| |
| import common |
| from autotest_lib.client.common_lib import control_data |
| from autotest_lib.server.cros.dynamic_suite.suite import Suite |
| |
| |
| def main(argv): |
| """main scripts to seed attributes in test control files. |
| |
| Args: |
| @param argv: Command line arguments including `sys.argv[0]`. |
| """ |
| # Parse execution cmd |
| parser = argparse.ArgumentParser( |
| description='Seed ATTRIBUTES in test control files.') |
| parser.add_argument('--execute', |
| action='store_true', |
| default=False, |
| help='Execute the script to seed attributes in all ' |
| 'test control files.') |
| args = parser.parse_args(argv) |
| |
| # When execute is True, run the script to seed attributes in control files. |
| if args.execute: |
| # Get the allowlist path, hardcode the path currently |
| path_allowlist = os.path.join(common.autotest_dir, |
| 'site_utils/attribute_allowlist.txt') |
| |
| # Go through all control file, check whether attribute matches suite. Return |
| # a changelist which contains the paths to the control files not match. |
| fs_getter = Suite.create_fs_getter(common.autotest_dir) |
| changelist = AttrSuiteMatch(fs_getter.get_control_file_list(), |
| path_allowlist) |
| count = len(changelist) |
| |
| logging.info('Starting to seed attributes in %d control files...', |
| count) |
| # Modify attributes based on suite for the control files not match. |
| for path in changelist: |
| logging.info('Seeding ATTRIBUTES in %s', path) |
| count = count - 1 |
| logging.info('%d files remaining...', count) |
| SeedAttributes(path) |
| |
| logging.info('Finished seeding attributes.') |
| |
| # When not specify 'execute' in cmd, not modify control files. |
| else: |
| logging.info( |
| 'No files are modified. To seed attributes in control files, ' |
| 'please add \'--execute\' argument when run the script.') |
| |
| |
| def AttrSuiteMatch(path_list, path_allowlist): |
| """Check whether attributes are in the attribute allowlist and match with the |
| suites in the control files. |
| |
| Args: |
| @param path_list: a list of path to the control files to be checked. |
| @param path_allowlist: path to the attribute allowlist. |
| |
| Returns: |
| A list of paths to the control files that failed at checking. |
| """ |
| unmatch_pathlist = [] |
| |
| # Read the allowlist to a set, if path is invalid, throw IOError. |
| with open(path_allowlist, 'r') as f: |
| allowlist = {line.strip() for line in f.readlines() if line.strip()} |
| |
| # Read the attr in the control files, check with allowlist and suite. |
| for path in path_list: |
| cd = control_data.parse_control(path, True) |
| cd_attrs = cd.attributes |
| |
| # Test whether attributes in the allowlist |
| if not (allowlist >= cd_attrs): |
| unmatch_pathlist.append(path) |
| # Test when suite exists, whether attributes match suites |
| if hasattr(cd, 'suite'): |
| target_attrs = set('suite:' + x.strip() |
| for x in cd.suite.split(',') if x.strip()) |
| if cd_attrs != target_attrs: |
| unmatch_pathlist.append(path) |
| # Test when suite not exists, whether attributes is empty |
| elif not hasattr(cd, 'suite') and cd_attrs: |
| unmatch_pathlist.append(path) |
| |
| return unmatch_pathlist |
| |
| |
| def SeedAttributes(path_controlfile): |
| """Seed attributes in a control file. |
| |
| Read and re-write a control file with modified contents with attributes added. |
| |
| Args: |
| @param path_controlfile: path to control file |
| |
| Returns: |
| None |
| """ |
| # Parse attribute from suite, and prepare ATTRIBUTES line. |
| cd = control_data.parse_control(path_controlfile, True) |
| suite = cd.suite |
| |
| attr_items = set('suite:' + x.strip() for x in suite.split(',') |
| if x.strip()) |
| attr_items = list(attr_items) |
| attr_items.sort(key=str.lower) |
| attr_line = ', '.join(attr_items) |
| attr_line = 'ATTRIBUTES = \"' + attr_line + '\"\n' |
| |
| # Read control file and modify the suite line with attribute added. |
| with open(path_controlfile, 'r') as f: |
| lines = f.readlines() |
| index = [ |
| i for i, val in enumerate(lines) |
| if val.startswith('SUITE =') or val.startswith('SUITE=') |
| ][0] |
| suite_line = lines[index] |
| lines[index] = attr_line + suite_line |
| |
| # Write the modified contents back to file |
| with open(path_controlfile, 'w') as f: |
| f.writelines(lines) |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |