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