#!/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 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:]))
