#!/usr/bin/env python2
#
# Copyright 2017 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.
#
# pylint: disable=cros-logging-import

# This is the script to run specified benchmark with different toolchain
# settings. It includes the process of building benchmark locally and running
# benchmark on DUT.

"""Main script to run the benchmark suite from building to testing."""
from __future__ import print_function

import argparse
import config
import ConfigParser
import logging
import os
import subprocess
import sys

logging.basicConfig(level=logging.INFO)

def _parse_arguments(argv):
  parser = argparse.ArgumentParser(description='Build and run specific '
                                   'benchamrk')
  parser.add_argument(
      '-b',
      '--bench',
      action='append',
      default=[],
      help='Select which benchmark to run')

  # Only one of compiler directory and llvm prebuilts version can be indicated
  # at the beginning, so set -c and -l into a exclusive group.
  group = parser.add_mutually_exclusive_group()

  # The toolchain setting arguments has action of 'append', so that users
  # could compare performance with several toolchain settings together.
  group.add_argument(
      '-c',
      '--compiler_dir',
      metavar='DIR',
      action='append',
      default=[],
      help='Specify path to the compiler\'s bin directory. '
      'You shall give several paths, each with a -c, to '
      'compare performance differences in '
      'each compiler.')

  parser.add_argument(
      '-o',
      '--build_os',
      action='append',
      default=[],
      help='Specify the host OS to build the benchmark.')

  group.add_argument(
      '-l',
      '--llvm_prebuilts_version',
      action='append',
      default=[],
      help='Specify the version of prebuilt LLVM. When '
      'specific prebuilt version of LLVM already '
      'exists, no need to pass the path to compiler '
      'directory.')

  parser.add_argument(
      '-f',
      '--cflags',
      action='append',
      default=[],
      help='Specify the cflags options for the toolchain. '
      'Be sure to quote all the cflags with quotation '
      'mark("") or use equal(=).')
  parser.add_argument(
      '--ldflags',
      action='append',
      default=[],
      help='Specify linker flags for the toolchain.')

  parser.add_argument(
      '-i',
      '--iterations',
      type=int,
      default=1,
      help='Specify how many iterations does the test '
      'take.')

  # Arguments -s and -r are for connecting to DUT.
  parser.add_argument(
      '-s',
      '--serials',
      help='Comma separate list of device serials under '
      'test.')

  parser.add_argument(
      '-r',
      '--remote',
      default='localhost',
      help='hostname[:port] if the ADB device is connected '
      'to a remote machine. Ensure this workstation '
      'is configured for passwordless ssh access as '
      'users "root" or "adb"')

  # Arguments -frequency and -m are for device settings
  parser.add_argument(
      '--frequency',
      type=int,
      default=960000,
      help='Specify the CPU frequency of the device. The '
      'unit is KHZ. The available value is defined in'
      'cpufreq/scaling_available_frequency file in '
      'device\'s each core directory. '
      'The default value is 960000, which shows a '
      'balance in noise and performance. Lower '
      'frequency will slow down the performance but '
      'reduce noise.')

  parser.add_argument(
      '-m',
      '--mode',
      default='little',
      help='User can specify whether \'little\' or \'big\' '
      'mode to use. The default one is little mode. '
      'The little mode runs on a single core of '
      'Cortex-A53, while big mode runs on single core '
      'of Cortex-A57.')

  # Configure file for benchmark test
  parser.add_argument(
      '-t',
      '--test',
      help='Specify the test settings with configuration '
      'file.')

  # Whether to keep old json result or not
  parser.add_argument(
      '-k',
      '--keep',
      default='False',
      help='User can specify whether to keep the old json '
      'results from last run. This can be useful if you '
      'want to compare performance differences in two or '
      'more different runs. Default is False(off).')

  return parser.parse_args(argv)


# Clear old log files in bench suite directory
def clear_logs():
  logging.info('Removing old logfiles...')
  for f in ['build_log', 'device_log', 'test_log']:
    logfile = os.path.join(config.bench_suite_dir, f)
    try:
      os.remove(logfile)
    except OSError:
      logging.info('No logfile %s need to be removed. Ignored.', f)
  logging.info('Old logfiles been removed.')


# Clear old json files in bench suite directory
def clear_results():
  logging.info('Clearing old json results...')
  for bench in config.bench_list:
    result = os.path.join(config.bench_suite_dir, bench + '.json')
    try:
      os.remove(result)
    except OSError:
      logging.info('no %s json file need to be removed. Ignored.', bench)
  logging.info('Old json results been removed.')


# Use subprocess.check_call to run other script, and put logs to files
def check_call_with_log(cmd, log_file):
  log_file = os.path.join(config.bench_suite_dir, log_file)
  with open(log_file, 'a') as logfile:
    log_header = 'Log for command: %s\n' % (cmd)
    logfile.write(log_header)
    try:
      subprocess.check_call(cmd, stdout=logfile)
    except subprocess.CalledProcessError:
      logging.error('Error running %s, please check %s for more info.', cmd,
                    log_file)
      raise
  logging.info('Logs for %s are written to %s.', cmd, log_file)


def set_device(serials, remote, frequency):
  setting_cmd = [
      os.path.join(
          os.path.join(config.android_home, config.autotest_dir),
          'site_utils/set_device.py')
  ]
  setting_cmd.append('-r=' + remote)
  setting_cmd.append('-q=' + str(frequency))

  # Deal with serials.
  # If there is no serails specified, try to run test on the only device.
  # If specified, split the serials into a list and run test on each device.
  if serials:
    for serial in serials.split(','):
      setting_cmd.append('-s=' + serial)
      check_call_with_log(setting_cmd, 'device_log')
      setting_cmd.pop()
  else:
    check_call_with_log(setting_cmd, 'device_log')

  logging.info('CPU mode and frequency set successfully!')


def log_ambiguous_args():
  logging.error('The count of arguments does not match!')
  raise ValueError('The count of arguments does not match.')


# Check if the count of building arguments are log_ambiguous or not.  The
# number of -c/-l, -f, and -os should be either all 0s or all the same.
def check_count(compiler, llvm_version, build_os, cflags, ldflags):
  # Count will be set to 0 if no compiler or llvm_version specified.
  # Otherwise, one of these two args length should be 0 and count will be
  # the other one.
  count = max(len(compiler), len(llvm_version))

  # Check if number of cflags is 0 or the same with before.
  if len(cflags) != 0:
    if count != 0 and len(cflags) != count:
      log_ambiguous_args()
    count = len(cflags)

  if len(ldflags) != 0:
    if count != 0 and len(ldflags) != count:
      log_ambiguous_args()
    count = len(ldflags)

  if len(build_os) != 0:
    if count != 0 and len(build_os) != count:
      log_ambiguous_args()
    count = len(build_os)

  # If no settings are passed, only run default once.
  return max(1, count)


# Build benchmark binary with toolchain settings
def build_bench(setting_no, bench, compiler, llvm_version, build_os, cflags,
                ldflags):
  # Build benchmark locally
  build_cmd = ['./build_bench.py', '-b=' + bench]
  if compiler:
    build_cmd.append('-c=' + compiler[setting_no])
  if llvm_version:
    build_cmd.append('-l=' + llvm_version[setting_no])
  if build_os:
    build_cmd.append('-o=' + build_os[setting_no])
  if cflags:
    build_cmd.append('-f=' + cflags[setting_no])
  if ldflags:
    build_cmd.append('--ldflags=' + ldflags[setting_no])

  logging.info('Building benchmark for toolchain setting No.%d...', setting_no)
  logging.info('Command: %s', build_cmd)

  try:
    subprocess.check_call(build_cmd)
  except:
    logging.error('Error while building benchmark!')
    raise


def run_and_collect_result(test_cmd, setting_no, i, bench, serial='default'):

  # Run autotest script for benchmark on DUT
  check_call_with_log(test_cmd, 'test_log')

  logging.info('Benchmark with setting No.%d, iter.%d finished testing on '
               'device %s.', setting_no, i, serial)

  # Rename results from the bench_result generated in autotest
  bench_result = os.path.join(config.bench_suite_dir, 'bench_result')
  if not os.path.exists(bench_result):
    logging.error('No result found at %s, '
                  'please check test_log for details.', bench_result)
    raise OSError('Result file %s not found.' % bench_result)

  new_bench_result = 'bench_result_%s_%s_%d_%d' % (bench, serial, setting_no, i)
  new_bench_result_path = os.path.join(config.bench_suite_dir, new_bench_result)
  try:
    os.rename(bench_result, new_bench_result_path)
  except OSError:
    logging.error('Error while renaming raw result %s to %s', bench_result,
                  new_bench_result_path)
    raise

  logging.info('Benchmark result saved at %s.', new_bench_result_path)


def test_bench(bench, setting_no, iterations, serials, remote, mode):
  logging.info('Start running benchmark on device...')

  # Run benchmark and tests on DUT
  for i in xrange(iterations):
    logging.info('Iteration No.%d:', i)
    test_cmd = [
        os.path.join(
            os.path.join(config.android_home, config.autotest_dir),
            'site_utils/test_bench.py')
    ]
    test_cmd.append('-b=' + bench)
    test_cmd.append('-r=' + remote)
    test_cmd.append('-m=' + mode)

    # Deal with serials.
    # If there is no serails specified, try to run test on the only device.
    # If specified, split the serials into a list and run test on each device.
    if serials:
      for serial in serials.split(','):
        test_cmd.append('-s=' + serial)

        run_and_collect_result(test_cmd, setting_no, i, bench, serial)
        test_cmd.pop()
    else:
      run_and_collect_result(test_cmd, setting_no, i, bench)


def gen_json(bench, setting_no, iterations, serials):
  bench_result = os.path.join(config.bench_suite_dir, 'bench_result')

  logging.info('Generating JSON file for Crosperf...')

  if not serials:
    serials = 'default'

  for serial in serials.split(','):

    # Platform will be used as device lunch combo instead
    #experiment = '_'.join([serial, str(setting_no)])
    experiment = config.product_combo

    # Input format: bench_result_{bench}_{serial}_{setting_no}_
    input_file = '_'.join([bench_result, bench, serial, str(setting_no), ''])
    gen_json_cmd = [
        './gen_json.py', '--input=' + input_file,
        '--output=%s.json' % os.path.join(config.bench_suite_dir, bench),
        '--bench=' + bench, '--platform=' + experiment,
        '--iterations=' + str(iterations)
    ]

    logging.info('Command: %s', gen_json_cmd)
    if subprocess.call(gen_json_cmd):
      logging.error('Error while generating JSON file, please check raw data'
                    'of the results at %s.', input_file)


def gen_crosperf(infile, outfile):
  # Set environment variable for crosperf
  os.environ['PYTHONPATH'] = os.path.dirname(config.toolchain_utils)

  logging.info('Generating Crosperf Report...')
  crosperf_cmd = [
      os.path.join(config.toolchain_utils, 'generate_report.py'),
      '-i=' + infile, '-o=' + outfile, '-f'
  ]

  # Run crosperf generate_report.py
  logging.info('Command: %s', crosperf_cmd)
  subprocess.call(crosperf_cmd)

  logging.info('Report generated successfully!')
  logging.info('Report Location: ' + outfile + '.html at bench'
               'suite directory.')


def main(argv):
  # Set environment variable for the local loacation of benchmark suite.
  # This is for collecting testing results to benchmark suite directory.
  os.environ['BENCH_SUITE_DIR'] = config.bench_suite_dir

  # Set Android type, used for the difference part between aosp and internal.
  os.environ['ANDROID_TYPE'] = config.android_type

  # Set ANDROID_HOME for both building and testing.
  os.environ['ANDROID_HOME'] = config.android_home

  # Set environment variable for architecture, this will be used in
  # autotest.
  os.environ['PRODUCT'] = config.product

  arguments = _parse_arguments(argv)

  bench_list = arguments.bench
  if not bench_list:
    bench_list = config.bench_list

  compiler = arguments.compiler_dir
  build_os = arguments.build_os
  llvm_version = arguments.llvm_prebuilts_version
  cflags = arguments.cflags
  ldflags = arguments.ldflags
  iterations = arguments.iterations
  serials = arguments.serials
  remote = arguments.remote
  frequency = arguments.frequency
  mode = arguments.mode
  keep = arguments.keep

  # Clear old logs every time before run script
  clear_logs()

  if keep == 'False':
    clear_results()

  # Set test mode and frequency of CPU on the DUT
  set_device(serials, remote, frequency)

  test = arguments.test
  # if test configuration file has been given, use the build settings
  # in the configuration file and run the test.
  if test:
    test_config = ConfigParser.ConfigParser(allow_no_value=True)
    if not test_config.read(test):
      logging.error('Error while reading from building '
                    'configuration file %s.', test)
      raise RuntimeError('Error while reading configuration file %s.' % test)

    for setting_no, section in enumerate(test_config.sections()):
      bench = test_config.get(section, 'bench')
      compiler = [test_config.get(section, 'compiler')]
      build_os = [test_config.get(section, 'build_os')]
      llvm_version = [test_config.get(section, 'llvm_version')]
      cflags = [test_config.get(section, 'cflags')]
      ldflags = [test_config.get(section, 'ldflags')]

      # Set iterations from test_config file, if not exist, use the one from
      # command line.
      it = test_config.get(section, 'iterations')
      if not it:
        it = iterations
      it = int(it)

      # Build benchmark for each single test configuration
      build_bench(0, bench, compiler, llvm_version, build_os, cflags, ldflags)

      test_bench(bench, setting_no, it, serials, remote, mode)

      gen_json(bench, setting_no, it, serials)

    for bench in config.bench_list:
      infile = os.path.join(config.bench_suite_dir, bench + '.json')
      if os.path.exists(infile):
        outfile = os.path.join(config.bench_suite_dir, bench + '_report')
        gen_crosperf(infile, outfile)

    # Stop script if there is only config file provided
    return 0

  # If no configuration file specified, continue running.
  # Check if the count of the setting arguments are log_ambiguous.
  setting_count = check_count(compiler, llvm_version, build_os, cflags, ldflags)

  for bench in bench_list:
    logging.info('Start building and running benchmark: [%s]', bench)
    # Run script for each toolchain settings
    for setting_no in xrange(setting_count):
      build_bench(setting_no, bench, compiler, llvm_version, build_os, cflags,
                  ldflags)

      # Run autotest script for benchmark test on device
      test_bench(bench, setting_no, iterations, serials, remote, mode)

      gen_json(bench, setting_no, iterations, serials)

    infile = os.path.join(config.bench_suite_dir, bench + '.json')
    outfile = os.path.join(config.bench_suite_dir, bench + '_report')
    gen_crosperf(infile, outfile)


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