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

"""Presubmit script for changes affecting tools/perf/.

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
"""

import os


def _CommonChecks(input_api, output_api, block_on_failure=False):
  """Performs common checks, which includes running pylint.

    block_on_failure: For some failures, we would like to warn the
        user but still allow them to upload the change. However, we
        don't want them to commit code with those failures, so we
        need to block the change on commit.
  """
  results = []

  results.extend(_CheckExpectations(input_api, output_api))
  results.extend(_CheckJson(input_api, output_api))
  results.extend(
      _CheckPerfDataCurrentness(input_api, output_api, block_on_failure))
  results.extend(
      _CheckPerfJsonConfigs(input_api, output_api, block_on_failure))
  results.extend(_CheckWprShaFiles(input_api, output_api))
  results.extend(_CheckShardMaps(input_api, output_api, block_on_failure))
  results.extend(input_api.RunTests(input_api.canned_checks.GetPylint(
      input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api),
      pylintrc='pylintrc')))
  return results


def _GetPathsToPrepend(input_api):
  perf_dir = input_api.PresubmitLocalPath()
  chromium_src_dir = input_api.os_path.join(perf_dir, '..', '..')
  telemetry_dir = input_api.os_path.join(
      chromium_src_dir, 'third_party', 'catapult', 'telemetry')
  typ_dir = input_api.os_path.join(
       chromium_src_dir, 'third_party', 'catapult', 'third_party', 'typ')
  experimental_dir = input_api.os_path.join(
      chromium_src_dir, 'third_party', 'catapult', 'experimental')
  tracing_dir = input_api.os_path.join(
      chromium_src_dir, 'third_party', 'catapult', 'tracing')
  py_utils_dir = input_api.os_path.join(
      chromium_src_dir, 'third_party', 'catapult', 'common', 'py_utils')
  android_pylib_dir = input_api.os_path.join(
      chromium_src_dir, 'build', 'android')
  return [
      telemetry_dir,
      typ_dir,
      input_api.os_path.join(telemetry_dir, 'third_party', 'mock'),
      experimental_dir,
      tracing_dir,
      py_utils_dir,
      android_pylib_dir,
  ]


def _RunArgs(args, input_api):
  p = input_api.subprocess.Popen(args, stdout=input_api.subprocess.PIPE,
                                 stderr=input_api.subprocess.STDOUT)
  out, _ = p.communicate()
  return (out, p.returncode)


def _CheckExpectations(input_api, output_api):
  results = []
  perf_dir = input_api.PresubmitLocalPath()
  vpython = 'vpython.bat' if input_api.is_windows else 'vpython'
  out, return_code = _RunArgs([
      vpython,
      input_api.os_path.join(perf_dir, 'validate_story_expectation_data')],
      input_api)
  if return_code:
    results.append(output_api.PresubmitError(
        'Validating story expectation data failed.', long_text=out))
  return results


def _CheckPerfDataCurrentness(input_api, output_api, block_on_failure):
  results = []
  perf_dir = input_api.PresubmitLocalPath()
  vpython = 'vpython.bat' if input_api.is_windows else 'vpython'
  out, return_code = _RunArgs([
      vpython,
      input_api.os_path.join(perf_dir, 'generate_perf_data'),
      '--validate-only'], input_api)
  if return_code:
    if block_on_failure:
      results.append(output_api.PresubmitError(
          'Validating perf data currentness failed', long_text=out))
    else:
      results.append(output_api.PresubmitPromptWarning(
          'Validating perf data currentness failed', long_text=out))
  return results


def _CheckPerfJsonConfigs(input_api, output_api, block_on_failure):
  results = []
  perf_dir = input_api.PresubmitLocalPath()
  vpython = 'vpython.bat' if input_api.is_windows else 'vpython'
  out, return_code = _RunArgs([
      vpython,
      input_api.os_path.join(perf_dir, 'validate_perf_json_config')], input_api)
  if return_code:
    if block_on_failure:
      results.append(output_api.PresubmitError(
          'Validating perf data correctness failed', long_text=out))
    else:
      results.append(output_api.PresubmitPromptWarning(
          'Validating perf data correctness failed', long_text=out))
  return results


def _CheckWprShaFiles(input_api, output_api):
  """Check whether the wpr sha files have matching URLs."""
  perf_dir = input_api.PresubmitLocalPath()

  results = []
  wpr_archive_shas = []
  for affected_file in input_api.AffectedFiles(include_deletes=False):
    filename = affected_file.AbsoluteLocalPath()
    if not filename.endswith('.sha1'):
      continue
    wpr_archive_shas.append(filename)

  vpython = 'vpython.bat' if input_api.is_windows else 'vpython'
  out, return_code = _RunArgs([
      vpython,
      input_api.os_path.join(perf_dir, 'validate_wpr_archives')] +
      wpr_archive_shas,
      input_api)
  if return_code:
    results.append(output_api.PresubmitError(
        'Validating WPR archives failed:', long_text=out))
  return results


def _CheckShardMaps(input_api, output_api, block_on_failure):
  results = []
  perf_dir = input_api.PresubmitLocalPath()
  vpython = 'vpython.bat' if input_api.is_windows else 'vpython'
  out, return_code = _RunArgs([
      vpython,
      input_api.os_path.join(perf_dir, 'generate_perf_sharding'),
      'validate'], input_api)
  if return_code:
    if block_on_failure:
      results.append(output_api.PresubmitError(
          'Validating shard maps failed', long_text=out))
    else:
      results.append(output_api.PresubmitPromptWarning(
          'Validating shard maps failed', long_text=out))
  return results


def _CheckJson(input_api, output_api):
  """Checks whether JSON files in this change can be parsed."""
  for affected_file in input_api.AffectedFiles(include_deletes=False):
    filename = affected_file.AbsoluteLocalPath()
    if os.path.splitext(filename)[1] != '.json':
      continue
    try:
      input_api.json.load(open(filename))
    except ValueError:
      return [output_api.PresubmitError('Error parsing JSON in %s!' % filename)]
  return []


def CheckChangeOnUpload(input_api, output_api):
  report = []
  report.extend(_CommonChecks(input_api, output_api))
  return report


def CheckChangeOnCommit(input_api, output_api):
  report = []
  report.extend(_CommonChecks(input_api, output_api, block_on_failure=True))
  return report
