1 #!/usr/bin/python 2 3 # Copyright (c) 2015 The Chromium OS Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 """Method to add or modify ATTRIBUTES in the test control files whose 8 ATTRIBUTES either not match to SUITE or not in the attribute whitelist.""" 9 10 import argparse 11 import logging 12 import os 13 import sys 14 15 import common 16 from autotest_lib.client.common_lib import control_data 17 from autotest_lib.server.cros.dynamic_suite.suite import Suite 18 19 20 def main(argv): 21 """main scripts to seed attributes in test control files. 22 23 Args: 24 @param argv: Command line arguments including `sys.argv[0]`. 25 """ 26 # Parse execution cmd 27 parser = argparse.ArgumentParser( 28 description='Seed ATTRIBUTES in test control files.') 29 parser.add_argument('--execute', action='store_true', default=False, 30 help='Execute the script to seed attributes in all ' 31 'test control files.') 32 args = parser.parse_args(argv) 33 34 # When execute is True, run the script to seed attributes in control files. 35 if args.execute: 36 # Get the whitelist path, hardcode the path currently 37 path_whitelist = os.path.join(common.autotest_dir, 38 'site_utils/attribute_whitelist.txt') 39 40 # Go through all control file, check whether attribute matches suite. Return 41 # a changelist which contains the paths to the control files not match. 42 fs_getter = Suite.create_fs_getter(common.autotest_dir) 43 changelist = AttrSuiteMatch( 44 fs_getter.get_control_file_list(), path_whitelist) 45 count = len(changelist) 46 47 logging.info('Starting to seed attributes in %d control files...' % count) 48 # Modify attributes based on suite for the control files not match. 49 for path in changelist: 50 logging.info('Seeding ATTRIBUTES in %s' % path) 51 count = count - 1 52 logging.info('%d files remaining...' % count) 53 SeedAttributes(path) 54 55 logging.info('Finished seeding attributes.') 56 57 # When not specify 'execute' in cmd, not modify control files. 58 else: 59 logging.info('No files are modified. To seed attributes in control files, ' 60 'please add \'--execute\' argument when run the script.') 61 62 63 def AttrSuiteMatch(path_list, path_whitelist): 64 """Check whether attributes are in the attribute whitelist and match with the 65 suites in the control files. 66 67 Args: 68 @param path_list: a list of path to the control files to be checked. 69 @param path_whitelist: path to the attribute whitelist. 70 71 Returns: 72 A list of paths to the control files that failed at checking. 73 """ 74 unmatch_pathlist = [] 75 76 # Read the whitelist to a set, if path is invalid, throw IOError. 77 with open(path_whitelist, 'r') as f: 78 whitelist = {line.strip() for line in f.readlines() if line.strip()} 79 80 # Read the attr in the control files, check with whitelist and suite. 81 for path in path_list: 82 cd = control_data.parse_control(path, True) 83 cd_attrs = cd.attributes 84 85 # Test whether attributes in the whitelist 86 if not (whitelist >= cd_attrs): 87 unmatch_pathlist.append(path) 88 # Test when suite exists, whether attributes match suites 89 if hasattr(cd, 'suite'): 90 target_attrs = set( 91 'suite:' + x.strip() for x in cd.suite.split(',') if x.strip()) 92 if cd_attrs != target_attrs: 93 unmatch_pathlist.append(path) 94 # Test when suite not exists, whether attributes is empty 95 elif not hasattr(cd, 'suite') and cd_attrs: 96 unmatch_pathlist.append(path) 97 98 return unmatch_pathlist 99 100 101 def SeedAttributes(path_controlfile): 102 """Seed attributes in a control file. 103 104 Read and re-write a control file with modified contents with attributes added. 105 106 Args: 107 @param path_controlfile: path to control file 108 109 Returns: 110 None 111 """ 112 # Parse attribute from suite, and prepare ATTRIBUTES line. 113 cd = control_data.parse_control(path_controlfile, True) 114 suite = cd.suite 115 116 attr_items = set( 117 'suite:' + x.strip() for x in suite.split(',') if x.strip()) 118 attr_items = list(attr_items) 119 attr_items.sort(key = str.lower) 120 attr_line = ', '.join(attr_items) 121 attr_line = 'ATTRIBUTES = \"' + attr_line + '\"\n' 122 123 # Read control file and modify the suite line with attribute added. 124 with open(path_controlfile, 'r') as f: 125 lines = f.readlines() 126 index = [i for i, val in enumerate(lines) if val.startswith('SUITE =') or 127 val.startswith('SUITE=')][0] 128 suite_line = lines[index] 129 lines[index] = attr_line + suite_line 130 131 # Write the modified contents back to file 132 with open(path_controlfile, 'w') as f: 133 f.writelines(lines) 134 135 136 if __name__ == '__main__': 137 sys.exit(main(sys.argv[1:])) 138