#!/usr/bin/env python
#
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Creates a script that runs a CrOS VM test by delegating to
build/chromeos/test_runner.py.
"""

import argparse
import os
import sys


SCRIPT_TEMPLATE = """\
#!/usr/bin/env python
#
# This file was generated by build/chromeos/create_test_runner_script.py

import os
import sys

def main():
  script_directory = os.path.dirname(__file__)
  def ResolvePath(path):
    return os.path.abspath(os.path.join(script_directory, path))

  vm_test_script = os.path.abspath(
      os.path.join(script_directory, '{vm_test_script}'))

  vm_args = {vm_test_args}
  path_args = {vm_test_path_args}
  for arg, path in path_args:
    vm_args.extend([arg, ResolvePath(path)])

  os.execv(vm_test_script,
           [vm_test_script] + vm_args + sys.argv[1:])

if __name__ == '__main__':
  sys.exit(main())
"""


def main(args):
  parser = argparse.ArgumentParser()
  parser.add_argument('--script-output-path')
  parser.add_argument('--output-directory')
  parser.add_argument('--test-exe')
  parser.add_argument('--runtime-deps-path')
  parser.add_argument('--cros-cache')
  parser.add_argument('--board')
  parser.add_argument('--use-vm', action='store_true')
  parser.add_argument('--deploy-chrome', action='store_true')
  parser.add_argument('--suite-name')
  parser.add_argument('--tast-attr-expr')
  parser.add_argument('--tast-tests', action='append')
  args = parser.parse_args(args)

  def RelativizePathToScript(path):
    return os.path.relpath(path, os.path.dirname(args.script_output_path))

  run_test_path = RelativizePathToScript(
      os.path.join(os.path.dirname(__file__), 'test_runner.py'))

  vm_test_args = [
      '--board', args.board,
      '-v',
  ]
  if args.use_vm:
    vm_test_args += ['--use-vm']

  if args.test_exe:
    vm_test_args.extend([
        'vm-test',
        '--test-exe',
        args.test_exe,
    ])
  elif args.tast_attr_expr or args.tast_tests:
    vm_test_args.extend([
        'tast',
        '--suite-name',
        args.suite_name,
    ])
    if args.tast_attr_expr:
      vm_test_args.extend([
          '--attr-expr',
          args.tast_attr_expr,
      ])
    else:
      for t in args.tast_tests:
        vm_test_args.extend(['-t', t])
  else:
    vm_test_args.append('host-cmd')
    if args.deploy_chrome:
      vm_test_args.append('--deploy-chrome')

  vm_test_path_args = [
      ('--cros-cache', RelativizePathToScript(args.cros_cache)),
  ]
  if args.runtime_deps_path:
    vm_test_path_args.append(
        ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path)))
  if args.output_directory:
    vm_test_path_args.append(
        ('--path-to-outdir', RelativizePathToScript(args.output_directory)))

  with open(args.script_output_path, 'w') as script:
    script.write(SCRIPT_TEMPLATE.format(
        vm_test_script=run_test_path,
        vm_test_args=str(vm_test_args),
        vm_test_path_args=str(vm_test_path_args)))

  os.chmod(args.script_output_path, 0750)


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
