# Copyright 2015 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.

"""Logic that drives runs of the benchmarking mojo app and parses its output."""

import os.path
import re

_BENCHMARK_APP = 'https://core.mojoapps.io/benchmark.mojo'

# Additional time in seconds allocated per shell run to accommodate start-up.
# The shell should terminate before hitting this time out, it is an error if it
# doesn't.
_EXTRA_TIMEOUT = 20

_MEASUREMENT_RESULT_FORMAT = r"""
^              # Beginning of the line.
measurement:   # Hard-coded tag.
\s+(\S+)       # Match measurement spec.
\s+(\S+)       # Match measurement result.
$              # End of the line.
"""

_MEASUREMENT_REGEX = re.compile(_MEASUREMENT_RESULT_FORMAT, re.VERBOSE)


def _parse_measurement_results(output):
  """Parses the measurement results present in the benchmark output and returns
  the dictionary of correctly recognized and parsed results.
  """
  measurement_results = {}
  output_lines = [line.strip() for line in output.split('\n')]
  for line in output_lines:
    match = re.match(_MEASUREMENT_REGEX, line)
    if match:
      measurement_spec = match.group(1)
      measurement_result = match.group(2)
      try:
        measurement_results[measurement_spec] = float(measurement_result)
      except ValueError:
        pass
  return measurement_results


class Outcome(object):
  """Holds results of a benchmark run."""

  def __init__(self, succeeded, error_str, output):
    self.succeeded = succeeded
    self.error_str = error_str
    self.output = output
    # Maps measurement specs to measurement results given as floats. Only
    # measurements that succeeded (ie. we retrieved their results) are
    # represented.
    self.results = {}
    self.some_measurements_failed = False


def run(shell, shell_args, app, duration_seconds, measurements, verbose,
        android, output_file):
  """Runs the given benchmark by running `benchmark.mojo` in mojo shell with
  appropriate arguments and returns the produced output.

  Returns:
    An instance of Outcome holding the results of the run.
  """
  timeout = duration_seconds + _EXTRA_TIMEOUT
  benchmark_args = []
  benchmark_args.append('--app=' + app)
  benchmark_args.append('--duration=' + str(duration_seconds))

  device_output_file = None
  if output_file:
    if android:
      device_output_file = os.path.join(shell.get_tmp_dir_path(), output_file)
      benchmark_args.append('--trace-output=' + device_output_file)
    else:
      benchmark_args.append('--trace-output=' + output_file)

  for measurement in measurements:
    benchmark_args.append(measurement['spec'])

  shell_args = list(shell_args)
  shell_args.append(_BENCHMARK_APP)
  shell_args.append('--force-offline-by-default')
  shell_args.append('--args-for=%s %s' % (_BENCHMARK_APP,
                                          ' '.join(benchmark_args)))

  if verbose:
    print 'shell arguments: ' + str(shell_args)
  return_code, output, did_time_out = shell.run_and_get_output(
      shell_args, timeout=timeout)

  if did_time_out:
    return Outcome(False, 'timed out', output)
  if return_code:
    return Outcome(False, 'return code: ' + str(return_code), output)

  # Pull the trace file even if some measurements are missing, as it can be
  # useful in debugging.
  if device_output_file:
    shell.pull_file(device_output_file, output_file, remove_original=True)

  outcome = Outcome(True, None, output)
  parsed_results = _parse_measurement_results(output)
  for measurement in measurements:
    spec = measurement['spec']
    if spec in parsed_results:
      outcome.results[spec] = parsed_results[spec]
    else:
      outcome.some_measurements_failed = True
  return outcome
