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

import argparse
import base64
import gzip
import io
import json
import logging
import os
import platform
import subprocess
import tempfile
import urllib
import urllib2


from core import path_util

from telemetry import benchmark
from telemetry import decorators
from telemetry.core import discover
from telemetry.util import command_line
from telemetry.util import matching


# Unsupported Perf bisect bots.
EXCLUDED_BOTS = {
    'win_xp_perf_bisect',  # Goma issues: crbug.com/330900
    'win_perf_bisect_builder',
    'win64_nv_tester',
    'winx64_bisect_builder',
    'linux_perf_bisect_builder',
    'mac_perf_bisect_builder',
    'android_perf_bisect_builder',
    'android_arm64_perf_bisect_builder',
    # Bisect FYI bots are not meant for testing actual perf regressions.
    # Hardware configuration on these bots is different from actual bisect bot
    # and these bots runs E2E integration tests for auto-bisect
    # using dummy benchmarks.
    'linux_fyi_perf_bisect',
    'mac_fyi_perf_bisect',
    'win_fyi_perf_bisect',
    'winx64_fyi_perf_bisect',
}

INCLUDE_BOTS = [
    'all',
    'all-win',
    'all-mac',
    'all-linux',
    'all-android'
]

# Default try bot to use incase builbot is unreachable.
DEFAULT_TRYBOTS = [
    'linux_perf_bisect',
    'mac_10_11_perf_bisect',
    'winx64_10_perf_bisect',
    'android_s5_perf_bisect',
]

CHROMIUM_SRC_PATH = path_util.GetChromiumSrcDir()
# Mapping of repo to its root path and git remote URL.
# Values for 'src' key in the map are related to path to the repo in the
# DEPS file, These values are to used create the DEPS patch along with patch
# that is being tried.
REPO_INFO_MAP = {
    'src': {
        'src': 'src',
        'url': 'https://chromium.googlesource.com/chromium/src.git',
    },
    'v8': {
        'src': 'src/v8',
        'url': 'https://chromium.googlesource.com/v8/v8.git',
    },
    'skia': {
        'src': 'src/third_party/skia',
        'url': 'https://chromium.googlesource.com/skia.git',
    },
    'angle': {
        'src': 'src/third_party/angle',
        'url': 'https://chromium.googlesource.com/angle/angle.git',
    },
    'catapult': {
        'src': 'src/third_party/catapult',
        'url': ('https://chromium.googlesource.com/external/github.com/'
                'catapult-project/catapult.git')
    }
}

_MILO_MASTER_ENDPOINT = ('https://luci-milo.appspot.com/prpc/milo.Buildbot/'
                        'GetCompressedMasterJSON')

_MILO_RESPONSE_PREFIX = ')]}\'\n'


assert not set(DEFAULT_TRYBOTS) & set(EXCLUDED_BOTS), (
    'A trybot cannot present in both Default as well as Excluded bots lists.')


class TrybotError(Exception):

  def __str__(self):
    return '(ERROR) Perf Try Job: %s' % self.args[0]


def _ProcessMiloData(data):
  if not data.startswith(_MILO_RESPONSE_PREFIX):
    return None
  data = data[len(_MILO_RESPONSE_PREFIX):]

  try:
    response_data = json.loads(data)
  except Exception:
    return None

  try:
    decoded_data = base64.b64decode(response_data.get('data'))
  except Exception:
    return None

  try:
    with io.BytesIO(decoded_data) as compressed_file:
      with gzip.GzipFile(fileobj=compressed_file) as decompressed_file:
        data_json = decompressed_file.read()
  except Exception:
    return None

  return json.loads(data_json)


def _GetTrybotList(builders):
  builders = ['%s' % bot.replace('_perf_bisect', '').replace('_', '-')
              for bot in builders]
  builders.extend(INCLUDE_BOTS)
  return sorted(builders)


def _GetBotPlatformFromTrybotName(trybot_name):
  os_names = ['linux', 'android', 'mac', 'win']
  try:
    return next(b for b in os_names if b in trybot_name)
  except StopIteration:
    raise TrybotError('Trybot "%s" unsupported for tryjobs.' % trybot_name)


def _GetBuilderNames(trybot_name, builders):
  """Return platform and its available bot name as dictionary."""
  os_names = ['linux', 'android', 'mac', 'win']
  if 'all' not in trybot_name:
    bot = ['%s_perf_bisect' % trybot_name.replace('-', '_')]
    bot_platform = _GetBotPlatformFromTrybotName(trybot_name)
    if 'x64' in trybot_name:
      bot_platform += '-x64'
    return {bot_platform: bot}

  platform_and_bots = {}
  for os_name in os_names:
    platform_and_bots[os_name] = [bot for bot in builders if os_name in bot]

  # Special case for Windows x64, consider it as separate platform
  # config config should contain target_arch=x64 and --browser=release_x64.
  win_x64_bots = [
      win_bot for win_bot in platform_and_bots['win']
      if 'x64' in win_bot]
  # Separate out non x64 bits win bots
  platform_and_bots['win'] = list(
      set(platform_and_bots['win']) - set(win_x64_bots))
  platform_and_bots['win-x64'] = win_x64_bots

  if 'all-win' in trybot_name:
    return {'win': platform_and_bots['win'],
            'win-x64': platform_and_bots['win-x64']}
  if 'all-mac' in trybot_name:
    return {'mac': platform_and_bots['mac']}
  if 'all-android' in trybot_name:
    return {'android': platform_and_bots['android']}
  if 'all-linux' in trybot_name:
    return {'linux': platform_and_bots['linux']}

  return platform_and_bots


_GIT_CMD = 'git'


if platform.system() == 'Windows':
  # On windows, the git command is installed as 'git.bat'
  _GIT_CMD = 'git.bat'


def RunGit(cmd, msg_on_error='', ignore_return_code=False):
  """Runs the git command with the given arguments.

  Args:
    cmd: git command arguments.
    msg_on_error: Message to be displayed on git command error.
    ignore_return_code: Ignores the return code for git command.

  Returns:
    The output of the git command as string.

  Raises:
    TrybotError: This exception is raised when git command fails.
  """
  proc = subprocess.Popen(
      [_GIT_CMD] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  output, err = proc.communicate()
  returncode = proc.poll()
  if returncode:
    if ignore_return_code:
      return None
    raise TrybotError('%s. \n%s \n%s' % (msg_on_error, err, output))

  return output.strip()


class Trybot(command_line.ArgParseCommand):
  """Run telemetry perf benchmark on trybot."""

  usage = 'botname benchmark_name [<benchmark run options>]'
  _builders = None

  def __init__(self):
    self._builder_names = None

  @classmethod
  def _GetBuilderList(cls):
    if not cls._builders:
      try:
        headers = {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        }
        values = {'name': 'tryserver.chromium.perf'}
        data = urllib.urlencode(values)
        req = urllib2.Request(_MILO_MASTER_ENDPOINT, None, headers)
        f = urllib2.urlopen(req, json.dumps(values), timeout=10)
      # In case of any kind of exception, allow tryjobs to use default trybots.
      # Possible exception are ssl.SSLError, urllib2.URLError,
      # socket.timeout, socket.error.
      except Exception:  # pylint: disable=broad-except
        # Incase of any exception return default trybots.
        print ('WARNING: Unable to reach builbot to retrieve trybot '
               'information, tryjob will use default trybots.')
        cls._builders = DEFAULT_TRYBOTS
      else:
        data = _ProcessMiloData(f.read())
        builders = data.get('builders', {}).keys()
        # Exclude unsupported bots like win xp and some dummy bots.
        cls._builders = [bot for bot in builders if bot not in EXCLUDED_BOTS]

    return cls._builders

  def _InitializeBuilderNames(self, trybot):
    self._builder_names = _GetBuilderNames(trybot, self._GetBuilderList())

  @classmethod
  def CreateParser(cls):
    parser = argparse.ArgumentParser(
        ('Run telemetry benchmarks on trybot. You can add all the benchmark '
         'options available except the --browser option'),
        formatter_class=argparse.RawTextHelpFormatter)
    return parser

  @classmethod
  def ProcessCommandLineArgs(cls, parser, options, extra_args, environment):
    del environment  # unused
    for arg in extra_args:
      if arg == '--browser' or arg.startswith('--browser='):
        parser.error('--browser=... is not allowed when running trybot.')
    all_benchmarks = discover.DiscoverClasses(
        start_dir=path_util.GetPerfBenchmarksDir(),
        top_level_dir=path_util.GetPerfDir(),
        base_class=benchmark.Benchmark).values()
    all_benchmark_names = [b.Name() for b in all_benchmarks]
    all_benchmarks_by_names = {b.Name(): b for b in all_benchmarks}
    benchmark_class = all_benchmarks_by_names.get(options.benchmark_name, None)
    if not benchmark_class:
      possible_benchmark_names = matching.GetMostLikelyMatchedObject(
          all_benchmark_names, options.benchmark_name)
      parser.error(
          'No benchmark named "%s". Do you mean any of those benchmarks '
          'below?\n%s' % (
              options.benchmark_name, '\n'.join(possible_benchmark_names)))
    is_benchmark_disabled, reason = cls.IsBenchmarkDisabledOnTrybotPlatform(
        benchmark_class, options.trybot)
    also_run_disabled_option = '--also-run-disabled-tests'
    if is_benchmark_disabled and also_run_disabled_option not in extra_args:
      parser.error('%s To run the benchmark on trybot anyway, add '
                   '%s option.' % (reason, also_run_disabled_option))

  @classmethod
  def IsBenchmarkDisabledOnTrybotPlatform(cls, benchmark_class, trybot_name):
    """Return whether benchmark will be disabled on trybot platform.

    Note that we cannot tell with certainty whether the benchmark will be
    disabled on the trybot platform since the disable logic in ShouldDisable()
    can be very dynamic and can only be verified on the trybot server platform.

    We are biased on the side of enabling the benchmark, and attempt to
    early discover whether the benchmark will be disabled as our best.

    It should never be the case that the benchmark will be enabled on the test
    platform but this method returns True.

    Returns:
      A tuple (is_benchmark_disabled, reason) whereas |is_benchmark_disabled| is
      a boolean that tells whether we are sure that the benchmark will be
      disabled, and |reason| is a string that shows the reason why we think the
      benchmark is disabled for sure.
    """
    benchmark_name = benchmark_class.Name()
    benchmark_disabled_strings = decorators.GetDisabledAttributes(
        benchmark_class)
    if 'all' in benchmark_disabled_strings:
      return True, 'Benchmark %s is disabled on all platform.' % benchmark_name
    if trybot_name == 'all':
      return False, ''
    trybot_platform = _GetBotPlatformFromTrybotName(trybot_name)
    if trybot_platform in benchmark_disabled_strings:
      return True, (
          "Benchmark %s is disabled on %s, and trybot's platform is %s." %
          (benchmark_name, ', '.join(benchmark_disabled_strings),
           trybot_platform))
    benchmark_enabled_strings = decorators.GetEnabledAttributes(benchmark_class)
    if (benchmark_enabled_strings and
        trybot_platform not in benchmark_enabled_strings and
        'all' not in benchmark_enabled_strings):
      return True, (
          "Benchmark %s is only enabled on %s, and trybot's platform is %s." %
          (benchmark_name, ', '.join(benchmark_enabled_strings),
           trybot_platform))
    if benchmark_class.ShouldDisable != benchmark.Benchmark.ShouldDisable:
      logging.warning(
          'Benchmark %s has ShouldDisable() method defined. If your trybot run '
          'does not produce any results, it is possible that the benchmark '
          'is disabled on the target trybot platform.', benchmark_name)
    return False, ''

  @classmethod
  def AddCommandLineArgs(cls, parser, environment):
    del environment  # unused
    available_bots = _GetTrybotList(cls._GetBuilderList())
    parser.add_argument(
        'trybot', choices=available_bots,
        help=('specify which bots to run telemetry benchmarks on. '
              ' Allowed values are:\n' + '\n'.join(available_bots)),
        metavar='<trybot name>')
    parser.add_argument(
        'benchmark_name', type=str,
        help=('specify which benchmark to run. To see all available benchmarks,'
              ' run `run_benchmark list`'),
        metavar='<benchmark name>')
    parser.add_argument(
        '--repo_path', type=str, default=CHROMIUM_SRC_PATH,
        help=("""specify the repo path where the patch is created.'
This argument should only be used if the changes are made outside chromium repo.
E.g.,
1) Assume you are running run_benchmarks command from $HOME/cr/src/ direcory:'
  a) If your changes are in $HOME/cr/src/v8, then --repo_path=v8 or
     --repo-path=$HOME/cr/src/v8
  b) If your changes are in $HOME/cr/src/third_party/catapult, then
     --repo_path=third_party/catapult or
     --repo_path = $HOME/cr/src/third_party/catapult'
  c) If your changes are not relative to src/ e.g. you created changes in some
     other direcotry say $HOME/mydir/v8/v8/, then the
     --repo_path=$HOME/mydir/v8/v8
2) Assume you are running run_benchmarks command not relatvie to src i.e.,
   you are running from $HOME/mydir/ direcory:'
   a) If your changes are in $HOME/cr/src/v8, then --repo-path=$HOME/cr/src/v8
   b) If your changes are in $HOME/cr/src/third_party/catapult, then
      --repo_path=$HOME/cr/src/third_party/catapult'
  c) If your changes are in $HOME/mydir/v8/v8/, then the
     --repo_path=$HOME/mydir/v8/v8 or --repo_path=v8/v8"""),
        metavar='<repo path>')
    parser.add_argument(
        '--deps_revision', type=str, default=None,
        help=('specify DEPS revision to modify DEPS entry in Chromium to a '
              'certain pushed revision.\n'
              'This revision overrides value in DEPS on TOT Chromium for the '
              'repo specified in --repo_path.\nIt is applied for both with and '
              'wihout patch.'),
        metavar='<deps revision>')

  def Run(self, options, extra_args=None):
    """Sends a tryjob to a perf trybot.

    This creates a branch, telemetry-tryjob, switches to that branch, edits
    the bisect config, commits it, uploads the CL to rietveld, and runs a
    tryjob on the given bot.
    """
    if extra_args is None:
      extra_args = []
    self._InitializeBuilderNames(options.trybot)

    return self._AttemptTryjob(options, extra_args)

  def _GetPerfConfig(self, bot_platform, arguments):
    """Generates the perf config for try job.

    Args:
      bot_platform: Name of the platform to be generated.
      arguments: Command line arguments.

    Returns:
      A dictionary with perf config parameters.
    """
    # To make sure that we don't mutate the original args
    arguments = arguments[:]

    # Always set verbose logging for later debugging
    if '-v' not in arguments and '--verbose' not in arguments:
      arguments.append('--verbose')

    # Generate the command line for the perf trybots
    target_arch = 'ia32'
    if any(arg == '--chrome-root' or arg.startswith('--chrome-root=') for arg
           in arguments):
      raise ValueError(
          'Trybot does not suport --chrome-root option set directly '
          'through command line since it may contain references to your local '
          'directory')

    arguments.insert(0, 'src/tools/perf/run_benchmark')
    if bot_platform == 'android':
      arguments.insert(1, '--browser=android-chromium')
    elif any('x64' in bot for bot in self._builder_names[bot_platform]):
      arguments.insert(1, '--browser=release_x64')
      target_arch = 'x64'
    else:

      arguments.insert(1, '--browser=release')

    command = ' '.join(arguments)

    return {
        'command': command,
        'repeat_count': '1',
        'max_time_minutes': '120',
        'truncate_percent': '0',
        'target_arch': target_arch,
    }

  def _GetRepoAndBranchName(self, repo_path):
    """Gets the repository name and working branch name.

    Args:
      repo_path: Path to the repository.

    Returns:
      Repository name and branch name as tuple.

    Raises:
      TrybotError: This exception is raised for the following cases:
        1. Try job is for non-git repository or in invalid branch.
        2. Un-committed changes in the current branch.
        3. No local commits in the current branch.
    """
    # If command runs successfully, then the output will be repo root path.
    # and current branch name.
    output = RunGit(['rev-parse', '--abbrev-ref', '--show-toplevel', 'HEAD'],
                    ('%s is not a git repository, must be in a git repository '
                     'to send changes to trybots' % os.getcwd()))

    repo_info = output.split()
    # Assuming the base directory name is same as repo project name set in
    # codereviews.settings file.
    repo_name = os.path.basename(repo_info[0]).strip()
    branch_name = repo_info[1].strip()

    if branch_name == 'HEAD':
      raise TrybotError('Not on a valid branch, looks like branch '
                        'is dettached. [branch:%s]' % branch_name)

    # Check if the tree is dirty: make sure the index is up to date and then
    # run diff-index
    RunGit(['update-index', '--refresh', '-q'], ignore_return_code=True)
    output = RunGit(['diff-index', 'HEAD'])
    if output:
      raise TrybotError(
          'Cannot send a try job with a dirty tree.\nPlease commit locally and '
          'upload your changes to rietveld in %s repository.' % repo_path)

    return (repo_name, branch_name)

  def _GetBaseGitHashForRepo(self, branch_name, git_url):
    """Gets the base revision for the repo on which local changes are made.

    Finds the upstream of the current branch that it is set to and gets
    the HEAD revision from upstream. This also checks if the remote URL on
    the upstream is supported by Perf Try job.

    Args:
      branch_name: Current working branch name.
      git_url: Remote URL of the repo.

    Returns:
      Git hash of the HEAD revision from the upstream branch.

    Raises:
      TrybotError: This exception is raised when a GIT command fails or if the
      remote URL of the repo found is not supported.
    """
    # Check if there is any upstream branch associated with current working
    # branch, Once the upstream branch is found i.e., then validates the
    # remote URL and then returns the HEAD revision from the remote branch.
    while not self._IsRepoSupported(branch_name, git_url):
      branch_name = RunGit(
          ['rev-parse', '--abbrev-ref', '%s@{upstream}' % branch_name],
          'Failed to get upstream branch name.')

    return RunGit(
        ['rev-parse', '%s@{upstream}' % branch_name],
        'Failed to get base revision hash on upstream.')

  def _IsRepoSupported(self, current_branch, repo_git_url):
    cur_remote = RunGit(
        ['config', 'branch.%s.remote'% current_branch],
        'Failed to get branch.%s.remote from git config' % current_branch)
    cur_remote = cur_remote.strip()
    if cur_remote == '.':
      return False
    cur_remote_url = RunGit(
        ['config', 'remote.%s.url' % cur_remote],
        'Failed to get remote.%s.url from git config' % cur_remote)
    if cur_remote_url.lower() == repo_git_url:
      return True
    raise TrybotError('URL %s on remote %s is not recognized on branch.'% (
        cur_remote_url, cur_remote))

  def _GetChangeList(self):
    """Gets the codereview URL for the current changes."""
    temp_file = None
    json_output = None
    try:
      fd, temp_file = tempfile.mkstemp(suffix='.json', prefix='perf_try_cl')
      os.close(fd)
      RunGit(['cl', 'issue', '--json', temp_file],
              'Failed to run "git cl issue" command.')
      with open(temp_file, 'r') as f:
        json_output = json.load(f)
    finally:
      try:
        if temp_file:
          os.remove(temp_file)
      except OSError:
        pass

    # Make sure the local commits are uploaded to rietveld.
    if not json_output.get('issue'):
      raise TrybotError(
          'PLEASE NOTE: The workflow for Perf Try jobs is changed. '
          'In order to run the perf try job, you must first upload your '
          'changes to rietveld.')
    return json_output.get('issue_url')

  def _AttemptTryjob(self, options, extra_args):
    """Attempts to run a tryjob from a repo directory.

    Args:
      options: Command line arguments to run benchmark.
      extra_args: Extra arugments to run benchmark.

    Returns:
     If successful returns 0, otherwise 1.
    """
    original_workdir = os.getcwd()
    repo_path = os.path.abspath(options.repo_path)
    try:
      # Check the existence of repo path.
      if not os.path.exists(repo_path):
        raise TrybotError('Repository path "%s" does not exist, please check '
                          'the value of <repo_path> argument.' % repo_path)
      # Change to the repo directory.
      os.chdir(repo_path)
      repo_name, branch_name = self._GetRepoAndBranchName(repo_path)

      repo_info = REPO_INFO_MAP.get(repo_name, None)
      if not repo_info:
        raise TrybotError('Unsupported repository %s' % repo_name)

      deps_override = None
      if repo_name != 'src':
        if not options.deps_revision:
          options.deps_revision = self._GetBaseGitHashForRepo(
              branch_name, repo_info.get('url'))
        deps_override = {repo_info.get('src'): options.deps_revision}

      rietveld_url = self._GetChangeList()
      print ('\nRunning try job....\nview progress here %s.'
             '\n\tRepo Name: %s\n\tPath: %s\n\tBranch: %s' % (
                 rietveld_url, repo_name, repo_path, branch_name))

      for bot_platform in self._builder_names:
        if not self._builder_names[bot_platform]:
          logging.warning('No builder is found for %s', bot_platform)
          continue
        try:
          arguments = [options.benchmark_name] + extra_args
          self._RunTryJob(bot_platform, arguments, deps_override)
        # Even if git cl try throws TrybotError exception for any platform,
        # keep sending try jobs to other platforms.
        except TrybotError, err:
          print err
    except TrybotError, error:
      print error
      return 1
    finally:
      # Restore to original working directory.
      os.chdir(original_workdir)
    return 0

  def _RunTryJob(self, bot_platform, arguments, deps_override):
    """Executes perf try job with benchmark test properties.

    Args:
      bot_platform: Name of the platform to be generated.
      arguments: Command line arguments.
      deps_override: DEPS revision if needs to be overridden.

    Raises:
      TrybotError: When trybot fails to upload CL or run git try.
    """
    config = self._GetPerfConfig(bot_platform, arguments)

    # Generate git try command for available bots.
    git_try_command = ['cl', 'try', '-m', 'tryserver.chromium.perf']

     # Add Perf Test config to git try --properties arg.
    git_try_command.extend(['-p', 'perf_try_config=%s' % json.dumps(config)])

    error_msg_on_fail = 'Could not try CL for %s' % bot_platform
    # Add deps overrides to git try --properties arg.
    if deps_override:
      git_try_command.extend([
          '-p', 'deps_revision_overrides=%s' % json.dumps(deps_override)])
      error_msg_on_fail += ' with DEPS override (%s)' % deps_override
    for bot in self._builder_names[bot_platform]:
      git_try_command.extend(['-b', bot])

    RunGit(git_try_command, error_msg_on_fail)
    print 'Perf Try job sent to rietveld for %s platform.' % bot_platform
