lin
2025-07-30 fcd736bf35fd93b563e9bbf594f2aa7b62028cc9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/python
 
# 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 whitelist."""
 
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 whitelist path, hardcode the path currently
    path_whitelist = os.path.join(common.autotest_dir,
                                  'site_utils/attribute_whitelist.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_whitelist)
    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_whitelist):
  """Check whether attributes are in the attribute whitelist 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_whitelist: path to the attribute whitelist.
 
  Returns:
    A list of paths to the control files that failed at checking.
  """
  unmatch_pathlist = []
 
  # Read the whitelist to a set, if path is invalid, throw IOError.
  with open(path_whitelist, 'r') as f:
    whitelist = {line.strip() for line in f.readlines() if line.strip()}
 
  # Read the attr in the control files, check with whitelist and suite.
  for path in path_list:
    cd = control_data.parse_control(path, True)
    cd_attrs = cd.attributes
 
    # Test whether attributes in the whitelist
    if not (whitelist >= 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:]))