blob: 758776ff8f6803338f31e2cfccc0f2c4730acaf5 [file] [log] [blame]
#!/usr/bin/python3
# Copyright 2015 The ChromiumOS Authors
# 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:]))