# Copyright 2013 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 ast
import contextlib
import datetime
import difflib
import random
import re
import urllib

from builders import EmptyTestSpec, TestStepConfig, TestSpec
from recipe_engine.types import freeze
from recipe_engine import recipe_api
from . import bisection
from . import builders
from . import testing


CBE_URL = 'http://chrome-build-extract.appspot.com'
V8_URL = 'https://chromium.googlesource.com/v8/v8'

COMMIT_TEMPLATE = '%s/+/%%s' % V8_URL

# Regular expressions for v8 branch names.
RELEASE_BRANCH_RE = re.compile(r'^(?:refs/branch-heads/)?\d+\.\d+$')

# With more than 23 letters, labels are to big for buildbot's popup boxes.
MAX_LABEL_SIZE = 23

# Make sure that a step is not flooded with log lines.
MAX_FAILURE_LOGS = 10

# Factor by which the considered failure for bisection must be faster than the
# ongoing build's total.
BISECT_DURATION_FACTOR = 5

TEST_RUNNER_PARSER = argparse.ArgumentParser()
TEST_RUNNER_PARSER.add_argument('--extra-flags')

VERSION_LINE_RE = r'^#define %s\s+(\d*)$'
VERSION_LINE_REPLACEMENT = '#define %s %s'
V8_MAJOR = 'V8_MAJOR_VERSION'
V8_MINOR = 'V8_MINOR_VERSION'
V8_BUILD = 'V8_BUILD_NUMBER'
V8_PATCH = 'V8_PATCH_LEVEL'

LCOV_IMAGE = 'lcov:2018-01-18_17-03'


class V8Version(object):
  """A v8 version as used for tagging (with patch level), e.g. '3.4.5.1'."""

  def __init__(self, major, minor, build, patch):
    self.major = major
    self.minor = minor
    self.build = build
    self.patch = patch

  def __eq__(self, other):
    return (self.major == other.major and
            self.minor == other.minor and
            self.build == other.build and
            self.patch == other.patch)

  def __str__(self):
    patch_str = '.%s' % self.patch if self.patch and self.patch != '0' else ''
    return '%s.%s.%s%s' % (self.major, self.minor, self.build, patch_str)

  def with_incremented_patch(self):
    return V8Version(
        self.major, self.minor, self.build, str(int(self.patch) + 1))

  def update_version_file_blob(self, blob):
    """Takes a version file's text and returns it with this object's version.
    """
    def sub(label, value, text):
      return re.sub(
          VERSION_LINE_RE % label,
          VERSION_LINE_REPLACEMENT % (label, value),
          text,
          flags=re.M,
      )
    blob = sub(V8_MAJOR, self.major, blob)
    blob = sub(V8_MINOR, self.minor, blob)
    blob = sub(V8_BUILD, self.build, blob)
    return sub(V8_PATCH, self.patch, blob)


class V8Api(recipe_api.RecipeApi):
  BUILDERS = builders.BUILDERS
  FLATTENED_BUILDERS = builders.FLATTENED_BUILDERS
  VERSION_FILE = 'include/v8-version.h'
  EMPTY_TEST_SPEC = EmptyTestSpec
  TEST_SPEC = TestSpec

  def bot_config_by_buildername(self, builders=FLATTENED_BUILDERS):
    default = {}
    if not self.m.properties.get('parent_buildername'):
      # Builders and builder_testers both build and need the following set of
      # default chromium configs:
      default['chromium_apply_config'] = ['default_compiler', 'goma', 'mb']
    return builders.get(self.m.properties.get('buildername'), default)

  def update_bot_config(self, bot_config, build_config, enable_swarming,
                        target_arch, target_platform, triggers):
    """Update bot_config dict with src-side properties.

    Args:
      bot_config: The bot_config dict to update.
      build_config: Config value for BUILD_CONFIG in chromium recipe module.
      enable_swarming: Switch to enable/disable swarming.
      target_arch: Config value for TARGET_ARCH in chromium recipe module.
      target_platform: Config value for TARGET_PLATFORM in chromium recipe
          module.
      triggers: List of tester names to trigger on success.

    Returns:
      An updated copy of the bot_config dict.
    """
    # Make mutable copy.
    bot_config = dict(bot_config)
    bot_config['v8_config_kwargs'] = dict(
        bot_config.get('v8_config_kwargs', {}))
    # Update only specified properties.
    for k, v in (
        ('BUILD_CONFIG', build_config),
        ('TARGET_ARCH', target_arch),
        ('TARGET_PLATFORM', target_platform)):
      if v is not None:
        bot_config['v8_config_kwargs'][k] = v
    if enable_swarming is not None:
      bot_config['enable_swarming'] = enable_swarming
    # Make mutable copy.
    bot_config['triggers'] = list(bot_config.get('triggers', []))
    bot_config['triggers'].extend(triggers or [])
    # TODO(machenbach): Temporarily also dedupe, during migrating triggers src
    # side. Should be removed when everything has migrated.
    bot_config['triggers'] = sorted(list(set(bot_config['triggers'])))
    return bot_config

  def get_test_roots(self):
    """Returns the list of default and extensible test root directories.

    A test root is a directory with the following layout:
    <root>/infra/testing/config.pyl (optional)
    <root>/infra/testing/builders.pyl
    <root>/test/<test suites> (optional)

    By default, the V8 checkout is a test root, and all matching directories
    under v8/custom_deps.

    Returns: List of paths to test roots.
    """
    result = [self.m.path['checkout']]
    custom_deps_dir = self.m.path['checkout'].join('custom_deps')
    self.m.file.ensure_directory('ensure custom_deps dir', custom_deps_dir)
    for path in self.m.file.listdir('list test roots', custom_deps_dir):
      if self.m.path.exists(path.join('infra', 'testing', 'builders.pyl')):
        assert self.bot_type == 'builder_tester', (
            'Separate test checkouts are only supported on builder_testers. '
            'For separate builders and testers, the test configs need to be '
            'transferred as properties')
        result.append(path)
    return result

  def update_test_configs(self, test_configs):
    """Update test configs without mutating previous copy."""
    self.test_configs = dict(getattr(self, 'test_configs', {}))
    self.test_configs.update(test_configs)

  def load_static_test_configs(self):
    """Set predifined test configs from build repository."""
    self.update_test_configs(testing.TEST_CONFIGS)

  def load_dynamic_test_configs(self, root):
    """Add test configs from configured location.

    The test configs in <root>/infra/testing/config.pyl are expected to follow
    the same structure as the TEST_CONFIGS dict in testing.py.

    Args:
      test_checkout: Path to test root, can either be the V8 checkout or an
          additional test checkout.
    Returns: Test config dict.
    """
    test_config_path = root.join('infra', 'testing', 'config.pyl')

    # Fallback for branch builders.
    if not self.m.path.exists(test_config_path):
      return {}

    try:
      # Eval python literal file.
      test_configs = ast.literal_eval(self.m.file.read_text(
          'read test config (%s)' % self.m.path.basename(root),
          test_config_path,
          test_data='{}',
      ))
    except SyntaxError as e:  # pragma: no cover
      raise self.m.step.InfraFailure(
          'Failed to parse test config "%s": %s' % (test_config_path, e))

    for test_config in test_configs.itervalues():
      # This configures the test runner to set the test root to the
      # test_checkout location for all tests from this checkout.
      # TODO(machenbach): This is starting to get hacky. The test config
      # dicts should be refactored into classes similar to test specs. Maybe
      # the extra configurations from test configs could be added to test
      # specs.
      test_config['test_root'] = str(root.join('test'))

    return test_configs

  def apply_bot_config(self, bot_config):
    """Entry method for using the v8 api."""
    self.bot_config = bot_config

    kwargs = {}
    if self.m.properties.get('parent_build_config'):
      kwargs['BUILD_CONFIG'] = self.m.properties['parent_build_config']
    kwargs.update(self.bot_config.get('v8_config_kwargs', {}))

    self.set_config('v8', optional=True, **kwargs)
    self.m.chromium.set_config('v8', **kwargs)
    self.m.gclient.set_config('v8', **kwargs)

    if self.m.chromium.c.TARGET_PLATFORM in ['android', 'fuchsia']:
      self.m.gclient.apply_config(self.m.chromium.c.TARGET_PLATFORM)

    for c in self.bot_config.get('gclient_apply_config', []):
      self.m.gclient.apply_config(c)
    for c in self.bot_config.get('chromium_apply_config', []):
      self.m.chromium.apply_config(c)
    for c in self.bot_config.get('v8_apply_config', []):
      self.apply_config(c)

    # Infer gclient variable that instructs sysroot download.
    if (self.m.chromium.c.TARGET_PLATFORM != 'android' and
        self.m.chromium.c.TARGET_ARCH == 'arm'):
      # This grabs both sysroots to not be dependent on additional bitness
      # setting.
      self.m.gclient.c.target_cpu.add('arm')
      self.m.gclient.c.target_cpu.add('arm64')

    if self.bot_config.get('enable_swarming', True):
      self.m.gclient.c.got_revision_reverse_mapping[
          'got_swarming_client_revision'] = ('v8/tools/swarming_client')

    # FIXME(machenbach): Use a context object that stores the state for each
    # test process. Otherwise it's easy to introduce bugs with multiple test
    # processes and stale context data. E.g. during bisection these values
    # change for tests on rerun.

    # Default failure retry.
    self.rerun_failures_count = 2

    # If tests are run, this value will be set to their total duration.
    self.test_duration_sec = 0

    # Allow overriding the isolate hashes during bisection with the ones that
    # correspond to the build of a bisect step.
    self._isolated_tests_override = None

    # Cache to compute isolated targets only once.
    self._isolate_targets_cached = []

    # This is inferred from the run_mb step or from the parent bot. If mb is
    # run multiple times, it is overwritten. It contains gn arguments.
    self.build_environment = self.m.properties.get(
        'parent_build_environment', {})

  def set_gclient_custom_var(self, var_name):
    """Sets the gclient custom var `var_name` if given.

    This customizes gclient sync, based on conditions on the variable in the
    V8 DEPS file.
    """
    if var_name:
      self.m.gclient.c.solutions[0].custom_vars[var_name] = 'True'

  @property
  def isolated_tests(self):
    # During bisection, the isolated hashes will be updated with hashes that
    # correspond to the bisect step.
    # TODO(machenbach): Remove pragma as soon as rerun is implemented for
    # swarming.
    if self._isolated_tests_override is not None:  # pragma: no cover
      return self._isolated_tests_override
    return self.m.isolate.isolated_tests

  def testing_random_seed(self):
    """Return a random seed suitable for v8 testing.

    If there are isolate hashes, build a random seed based on the hashes.
    Otherwise use the system's PRNG. This uses a deterministic seed for
    recipe simulation.
    """
    r = random.Random()
    if self.isolated_tests:
      r.seed(tuple(self.isolated_tests))
    elif self._test_data.enabled:
      r.seed(12345)

    seed = 0
    while not seed:
      # Avoid 0 because v8 switches off usage of random seeds when
      # passing 0 and creates a new one.
      seed = r.randint(-2147483648, 2147483647)
    return seed

  def checkout(self, revision=None, **kwargs):
    # Set revision for bot_update.
    revision = revision or self.m.properties.get(
        'parent_got_revision', self.m.properties.get('revision', 'HEAD'))
    solution = self.m.gclient.c.solutions[0]
    branch = self.m.properties.get('branch', 'master')
    if RELEASE_BRANCH_RE.match(branch):
      if branch.startswith('refs/branch-heads/'):
        revision = '%s:%s' % (branch, revision)
      else:
        # TODO(sergiyb): Deprecate this after migrating branch builders to LUCI.
        revision = 'refs/branch-heads/%s:%s' % (branch, revision)
    solution.revision = revision

    self.checkout_root = self.m.path['builder_cache']
    if self.m.runtime.is_luci:
      self.checkout_root = self.m.path['builder_cache']
    else:
      # TODO(sergiyb): Deprecate this after migrating all builders to LUCI.
      safe_buildername = ''.join(
          c if c.isalnum() else '_' for c in self.m.properties['buildername'])
      self.checkout_root = self.m.path['builder_cache'].join(safe_buildername)

    self.m.file.ensure_directory(
        'ensure builder cache dir', self.checkout_root)
    with self.m.context(cwd=self.checkout_root):
      update_step = self.m.bot_update.ensure_checkout(**kwargs)

    assert update_step.json.output['did_run']

    # Bot_update maintains the properties independent of the UI
    # presentation.
    self.revision = self.m.bot_update.last_returned_properties['got_revision']

    # Note, a commit position might not be available on feature branches.
    self.revision_cp = (
        self.m.bot_update.last_returned_properties.get('got_revision_cp'))
    self.revision_number = None
    if self.revision_cp:
      self.revision_number = str(self.m.commit_position.parse_revision(
          self.revision_cp))

    return update_step

  def calculate_patch_base_gerrit(self):
    """Calculates the commit hash a gerrit patch was branched off."""
    commits, _ = self.m.gitiles.log(
        url=V8_URL,
        ref='master..%s' % self.m.properties['patch_ref'],
        limit=100,
        step_name='Get patches',
        step_test_data=lambda: self.test_api.example_patch_range(),
    )
    # There'll be at least one commit with the patch. Maybe more for dependent
    # CLs.
    assert len(commits) >= 1
    # We don't support merges.
    assert len(commits[-1]['parents']) == 1
    return commits[-1]['parents'][0]

  def set_up_swarming(self):
    if self.bot_config.get('enable_swarming', True):
      self.m.swarming.check_client_version()

    self.m.swarming.set_default_dimension('pool', 'Chrome')
    self.m.swarming.set_default_dimension('os', 'Ubuntu-14.04')
    # TODO(machenbach): Investigate if this is causing a priority inversion
    # with tasks not specifying cores=8. See http://crbug.com/735388
    # self.m.swarming.set_default_dimension('cores', '8')
    self.m.swarming.add_default_tag('project:v8')
    self.m.swarming.default_hard_timeout = 45 * 60

    self.m.swarming.default_idempotent = True

    if self.m.properties['mastername'] == 'tryserver.v8':
      self.m.swarming.add_default_tag('purpose:pre-commit')
      requester = self.m.properties.get('requester')
      if requester == 'commit-bot@chromium.org':
        self.m.swarming.default_priority = 30
        self.m.swarming.add_default_tag('purpose:CQ')
        blamelist = self.m.properties.get('blamelist')
        if len(blamelist) == 1:
          requester = blamelist[0]
      else:
        self.m.swarming.default_priority = 28
        self.m.swarming.add_default_tag('purpose:ManualTS')
      self.m.swarming.default_user = requester

      patch_project = self.m.properties.get('patch_project')
      if patch_project:
        self.m.swarming.add_default_tag('patch_project:%s' % patch_project)
    else:
      if self.m.properties['mastername'] in ['client.v8', 'client.v8.ports']:
        self.m.swarming.default_priority = 25
      else:
        # This should be lower than the CQ.
        self.m.swarming.default_priority = 35
      self.m.swarming.add_default_tag('purpose:post-commit')
      self.m.swarming.add_default_tag('purpose:CI')

    if self.m.runtime.is_experimental:
      # Use lower priority for tasks scheduled from experimental builds.
      self.m.swarming.default_priority = 60

  def runhooks(self, **kwargs):
    if (self.m.chromium.c.compile_py.compiler and
        self.m.chromium.c.compile_py.compiler.startswith('goma')):
      # Only ensure goma if we want to use it. Otherwise it might break bots
      # that don't support the goma executables.
      self.m.chromium.ensure_goma()
    env = {}
    self.m.chromium.runhooks(env=env, **kwargs)

  @property
  def bot_type(self):
    if self.bot_config.get('triggers') or self.bot_config.get('triggers_proxy'):
      return 'builder'
    if self.m.properties.get('parent_buildername'):
      return 'tester'
    return 'builder_tester'

  @property
  def builderset(self):
    """Returns a list of names of this builder and all its triggered testers."""
    return (
        [self.m.properties['buildername']] +
        list(self.bot_config.get('triggers', []))
    )

  @property
  def should_build(self):
    return self.bot_type in ['builder', 'builder_tester']

  @property
  def should_test(self):
    return self.bot_type in ['tester', 'builder_tester']

  @property
  def should_upload_build(self):
    return (self.bot_config.get('triggers_proxy') or
            self.bot_config.get('should_upload_build'))

  @property
  def should_download_build(self):
    return self.bot_type == 'tester' and not self.is_pure_swarming_tester

  @property
  def relative_path_to_d8(self):
    return self.m.path.join('out', self.m.chromium.c.build_config_fs, 'd8')

  def extra_tests_from_properties(self):
    """Returns runnable testing.BaseTest objects for each extra test specified
    by parent_test_spec property.
    """
    return [
      testing.create_test(test, self.m)
      for test in TestSpec.from_properties_dict(self.m.properties)
    ]

  def extra_tests_from_test_spec(self, test_spec):
    """Returns runnable testing.BaseTest objects for each extra test specified
    in the test spec of the current builder.
    """
    return [
      testing.create_test(test, self.m)
      for test in test_spec.get_tests(self.m.properties['buildername'])
    ]

  def dedupe_tests(self, high_prec_tests, low_prec_tests):
    """Dedupe tests with lower precedence."""
    high_prec_ids = set([test.id for test in high_prec_tests])
    return high_prec_tests + [
      test for test in low_prec_tests if test.id not in high_prec_ids]

  def read_test_spec(self, root):
    """Reads a test specification file under <root>/infra/testing/builders.pyl.

    Args:
      root: Path to checkout root with configurations.
    Returns: TestSpec object, filtered by interesting builders (current builder
        and all its triggered testers).
    """
    test_spec_file = root.join('infra', 'testing', 'builders.pyl')

    # Fallback for branch builders.
    if not self.m.path.exists(test_spec_file):
      return EmptyTestSpec

    try:
      # Eval python literal file.
      full_test_spec = ast.literal_eval(self.m.file.read_text(
          'read test spec (%s)' % self.m.path.basename(root),
          test_spec_file,
          test_data='{}',
      ))
    except SyntaxError as e:  # pragma: no cover
      raise self.m.step.InfraFailure(
          'Failed to parse test specification "%s": %s' % (test_spec_file, e))

    # Transform into object.
    test_spec = TestSpec.from_python_literal(full_test_spec, self.builderset)

    # Log test spec for debuggability.
    self.m.step.active_result.presentation.logs['test_spec'] = (
        test_spec.log_lines())

    return test_spec

  def isolate_targets_from_tests(self, tests):
    """Returns the isolated targets associated with a list of tests.

    Args:
      tests: A list of test names used as keys in the V8 API's test config.
    """
    if not self.bot_config.get('enable_swarming', True):
      return []
    targets = []
    for test in tests:
      config = self.test_configs.get(test) or {}

      # Tests either define an explicit isolate target or use the test
      # names for convenience.
      if config.get('isolated_target'):
        targets.append(config['isolated_target'])
      elif config.get('tests'):
        targets.extend(config['tests'])
    return targets

  @property
  def isolate_targets(self):
    """Returns the isolate targets statically known from builders.py."""
    if self._isolate_targets_cached:
      return self._isolate_targets_cached

    if self.bot_config.get('enable_swarming', True):
      # Find tests to isolate on builders.
      for buildername in self.builderset:
        bot_config = builders.FLATTENED_BUILDERS.get(buildername, {})
        self._isolate_targets_cached.extend(
            self.isolate_targets_from_tests(
                [test.name for test in bot_config.get('tests', [])]))

      # Add the performance-tests isolate everywhere, where the perf-bot proxy
      # is triggered.
      if self.bot_config.get('triggers_proxy', False):
        self._isolate_targets_cached.append('perf')

    self._isolate_targets_cached = sorted(list(set(
        self._isolate_targets_cached)))
    return self._isolate_targets_cached

  def isolate_tests(self, isolate_targets):
    """Upload isolated tests to isolate server.

    Args:
      isolate_targets: Targets to isolate.
    """
    if isolate_targets:
      self.m.isolate.isolate_tests(
          self.m.chromium.output_dir,
          targets=isolate_targets,
          verbose=True,
          swarm_hashes_property_name=None,
      )
      self.upload_isolated_json()

  def _update_build_environment(self, mb_output):
    """Sets the build_environment property based on gn arguments in mb output.
    """
    self.build_environment = {}
    # Check if the output looks like gn. Space-join all gn args, except
    # goma_dir.
    # TODO(machenbach): Instead of scanning the output, we could also read
    # the gn.args file that was written.
    match = re.search(r'Writing """\\?\s*(.*)""" to ', mb_output, re.S)
    if match:
      self.build_environment['gn_args'] = ' '.join(
        l for l in match.group(1).strip().splitlines()
        if not l.startswith('goma_dir'))

  def _upload_build_dependencies(self, deps):
    values = {
      'ext_h_avg_deps': deps['by_extension']['h']['avg_deps'],
      'ext_h_top100_avg_deps': deps['by_extension']['h']['top100_avg_deps'],
      'ext_h_top200_avg_deps': deps['by_extension']['h']['top200_avg_deps'],
      'ext_h_top500_avg_deps': deps['by_extension']['h']['top500_avg_deps'],
    }
    points = []
    root = '/'.join([
      'v8.infra.experimental' if self.m.runtime.is_experimental else 'v8.infra',
      'build_dependencies',
      '',
    ])
    for k, v in values.iteritems():
      p = self.m.perf_dashboard.get_skeleton_point(
          root + k, self.revision_number, str(v))
      p['units'] = 'count'
      p['supplemental_columns'] = {
        'a_default_rev': 'r_v8_git',
        'r_v8_git': self.revision,
      }
      points.append(p)
    if points:
      self.m.perf_dashboard.add_point(points)

  def _track_binary_size(self, path_pieces_list, category):
    """Track and upload binary size of configured binaries.

    Args:
      path_pieces_list: List of path pieces to be joined to the build output
          folder respectively. Each path should point to a binary to track.
      category: ChromePerf category for qualifying the graph names, e.g.
          linux32 or linux64.
    """
    files = [
      self.build_output_dir.join(*path_pieces)
      for path_pieces in path_pieces_list
    ]

    sizes = self.m.file.filesizes('Check binary size', files)

    point_defaults = {
      'units': 'bytes',
      'supplemental_columns': {
        'a_default_rev': 'r_v8_git',
        'r_v8_git': self.revision,
      },
    }

    if self.m.runtime.is_experimental:
      trace_prefix = ['v8.infra.experimental']
    else:
      trace_prefix = ['v8.infra']

    trace_prefix.append('binary_size')

    points = []
    for path_pieces, size in zip(path_pieces_list, sizes):
      p = self.m.perf_dashboard.get_skeleton_point(
          '/'.join(trace_prefix + [path_pieces[-1]]),
          self.revision_number,
          str(size),
          bot=category,
      )
      p.update(point_defaults)
      points.append(p)
    self.m.perf_dashboard.add_point(points)

  def compile(self, test_spec=EmptyTestSpec, **kwargs):
    """Compile all desired targets and isolate tests.

    Args:
      test_spec: Optional TestSpec object as returned by read_test_spec().
          Expected to contain only specifications for the current builder and
          all triggered builders. All corrensponding extra targets will also be
          isolated.
    """
    use_goma = (self.m.chromium.c.compile_py.compiler and
                'goma' in self.m.chromium.c.compile_py.compiler)

    # Calculate extra targets to isolate from V8-side test specification. The
    # test_spec contains extra TestStepConfig objects for the current builder
    # and all its triggered builders.
    extra_targets = self.isolate_targets_from_tests(
        test_spec.get_all_test_names())
    isolate_targets = sorted(list(set(self.isolate_targets + extra_targets)))

    if self.m.chromium.c.project_generator.tool == 'mb':
      def step_test_data():
        # Fake MB output with GN flags.
        return self.m.raw_io.test_api.stream_output(
            'Writing """\\\n'
            'goma_dir = "/b/build/slave/cache/goma_client"\n'
            'target_cpu = "x86"\n'
            'use_goma = true\n'
            '""" to /b/build/slave/linux-builder/build/v8/out/Release/args.gn\n'
            'moar text'
        )
      try:
        self.m.chromium.run_mb(
            self.m.properties['mastername'],
            self.m.properties['buildername'],
            use_goma=use_goma,
            mb_config_path=self.m.path['checkout'].join(
                'infra', 'mb', 'mb_config.pyl'),
            isolated_targets=isolate_targets,
            stdout=self.m.raw_io.output_text(),
            step_test_data=step_test_data,
        )
      finally:
        # Log captured output. We call log below 'captured_stdout' instead of
        # simply 'stdout' to differentiate it from the default 'stdout' log that
        # is added to all steps. The latter log will actually contain no real
        # output because it is captured by the raw_io module.
        self.m.step.active_result.presentation.logs['captured_stdout'] = (
          self.m.step.active_result.stdout.splitlines())

      # Update the build environment dictionary, which is printed to the
      # user on test failures for easier build reproduction.
      self._update_build_environment(self.m.step.active_result.stdout)

      # Create logs surfacing GN arguments. This information is critical to
      # developers for reproducing failures locally.
      if 'gn_args' in self.build_environment:
        self.m.step.active_result.presentation.logs['gn_args'] = (
            self.build_environment['gn_args'].splitlines())
    elif self.m.chromium.c.project_generator.tool == 'gn':
      self.m.chromium.run_gn(use_goma=use_goma)

    if use_goma:
      kwargs['use_goma_module'] = True
    self.m.chromium.compile(**kwargs)

    if self.bot_config.get('track_build_dependencies', False):
      deps = self.m.python(
          name='track build dependencies (fyi)',
          script=self.resource('build-dep-stats.py'),
          args=[
            '-C', self.build_output_dir,
            '-x', '/third_party/',
            '-o', self.m.json.output(),
          ],
          step_test_data=lambda: self.test_api.example_build_dependencies(),
          ok_ret='any',
      ).json.output
      if deps:
        self._upload_build_dependencies(deps)

    # Track binary size if specified.
    tracking_config = self.bot_config.get('binary_size_tracking', {})
    if tracking_config:
      self._track_binary_size(
        tracking_config['path_pieces_list'],
        tracking_config['category'],
      )

    self.isolate_tests(isolate_targets)

  def _get_default_archive(self):
    return 'gs://chromium-v8/%sarchives/%s/%s' % (
        'experimental/' if self.m.runtime.is_experimental else '',
        self.m.properties['mastername'],
        self.m.properties['buildername'],
    )

  def upload_build(self, name_suffix='', archive=None):
    self.m.archive.zip_and_upload_build(
          'package build' + name_suffix,
          self.m.chromium.c.build_config_fs,
          archive or self._get_default_archive(),
          src_dir=self.checkout_root.join('v8'))

  @property
  def isolated_archive_path(self):
    buildername = (self.m.properties.get('parent_buildername') or
                   self.m.properties['buildername'])
    return 'chromium-v8/%sisolated/%s/%s' % (
        'experimental/' if self.m.runtime.is_experimental else '',
        self.m.properties['mastername'],
        buildername,
    )

  def upload_isolated_json(self):
    self.m.gsutil.upload(
        self.m.json.input(self.m.isolate.isolated_tests),
        self.isolated_archive_path,
        '%s.json' % self.revision,
        args=['-a', 'public-read'],
    )

  def maybe_create_clusterfuzz_archive(self, update_step):
    if self.bot_config.get('cf_archive_build', False):
      kwargs = {}
      if self.bot_config.get('cf_archive_bitness'):
        kwargs['use_legacy'] = False
        kwargs['bitness'] = self.bot_config['cf_archive_bitness']
      self.m.archive.clusterfuzz_archive(
          revision_dir='v8',
          build_dir=self.build_output_dir,
          update_properties=update_step.presentation.properties,
          gs_bucket=self.bot_config.get('cf_gs_bucket'),
          gs_acl=self.bot_config.get('cf_gs_acl'),
          archive_prefix=self.bot_config.get('cf_archive_name'),
          **kwargs
      )

  def download_build(self, name_suffix='', archive=None):
    self.m.file.rmtree('build directory' + name_suffix, self.build_output_dir)
    self.m.archive.download_and_unzip_build(
          'extract build' + name_suffix,
          self.m.chromium.c.build_config_fs,
          archive or self.m.properties.get('archive'),
          src_dir=self.checkout_root.join('v8'))

  def download_isolated_json(self, revision):
    archive = 'gs://' + self.isolated_archive_path + '/%s.json' % revision
    self.m.gsutil.download_url(
        archive,
        self.m.json.output(),
        name='download isolated json',
        step_test_data=lambda: self.m.json.test_api.output(
            {'bot_default': '[dummy hash for bisection]'}),
    )
    step_result = self.m.step.active_result
    self._isolated_tests_override = step_result.json.output

  @property
  def build_output_dir(self):
    """Absolute path to the build product based on the 'checkout' path."""
    return self.m.chromium.c.build_dir.join(self.m.chromium.c.build_config_fs)

  @property
  def generate_gcov_coverage(self):
    return bool(self.bot_config.get('gcov_coverage_folder'))

  def init_gcov_coverage(self):
    """Delete all gcov counter files."""
    self.m.docker.login()
    self.m.docker.run(
        LCOV_IMAGE,
        'lcov zero counters',
        ['lcov', '--directory', self.build_output_dir, '--zerocounters'],
        dir_mapping=[(self.build_output_dir, self.build_output_dir)],
    )

  def upload_gcov_coverage_report(self):
    """Capture coverage data and upload a report."""
    coverage_dir = self.m.path.mkdtemp('gcov_coverage')
    report_dir = self.m.path.mkdtemp('gcov_coverage_html')
    output_file = self.m.path.join(coverage_dir, 'app.info')

    dir_mapping = [
        # We need to map entire checkout, since some of the files generated by
        # lcov inside the build output dir contain relative paths to files in
        # the checkout and without this map, genhtml step below will fail to
        # find them.
        (self.m.path['checkout'], self.m.path['checkout']),
        (coverage_dir, coverage_dir),
        (report_dir, report_dir),
    ]

    # Capture data from gcda and gcno files.
    self.m.docker.run(
        LCOV_IMAGE,
        'lcov capture',
        [
          'lcov',
          '--directory', self.build_output_dir,
          '--capture',
          '--output-file', output_file,
        ],
        dir_mapping,
    )

    # Remove unwanted data.
    self.m.docker.run(
        LCOV_IMAGE,
        'lcov remove',
        [
          'lcov',
          '--directory', self.build_output_dir,
          '--remove', output_file,
          'third_party/*',
          'testing/gtest/*',
          'testing/gmock/*',
          '/usr/include/*',
          '--output-file', output_file,
        ],
        dir_mapping,
    )

    # Generate html report into a temp folder.
    self.m.docker.run(
        LCOV_IMAGE,
        'genhtml',
        [
          'genhtml',
          '--output-directory', report_dir,
          output_file,
        ],
        dir_mapping,
    )

    # Upload report to google storage.
    dest = '%s/%s' % (self.bot_config['gcov_coverage_folder'], self.revision)
    if self.m.runtime.is_experimental:
      dest = 'experimental/%s' % dest
    result = self.m.gsutil(
        [
          '-m', 'cp', '-a', 'public-read', '-R', report_dir,
          'gs://chromium-v8/%s' % dest,
        ],
        'coverage report',
    )
    result.presentation.links['report'] = (
      'https://storage.googleapis.com/chromium-v8/%s/index.html' % dest)

  @property
  def generate_sanitizer_coverage(self):
    return bool(self.bot_config.get('sanitizer_coverage_folder'))

  def create_coverage_context(self):
    if self.generate_sanitizer_coverage:
      return testing.SanitizerCoverageContext(self.m)
    else:
      return testing.NULL_COVERAGE

  def create_test(self, test):
    """Wrapper that allows to shortcut common tests with their names.

    Returns: A runnable test instance.
    """
    return testing.create_test(test, self.m)

  def create_tests(self):
    return [self.create_test(t) for t in self.bot_config.get('tests', [])]

  @property
  def is_pure_swarming_tester(self):
    return (self.bot_type == 'tester' and
            self.bot_config.get('enable_swarming', True))

  def runtests(self, tests):
    if self.extra_flags:
      result = self.m.step('Customized run with extra flags', cmd=None)
      result.presentation.step_text += ' '.join(self.extra_flags)
      assert all(re.match(r'[\w\-]*', x) for x in self.extra_flags), (
          'no special characters allowed in extra flags')

    start_time_sec = self.m.time.time()
    test_results = testing.TestResults.empty()

    # Apply test filter.
    # TODO(machenbach): Track also the number of tests that ran and throw an
    # error if the overall number of tests from all steps was zero.
    tests = [t for t in tests if t.apply_filter()]

    swarming_tests = [t for t in tests if t.uses_swarming]
    non_swarming_tests = [t for t in tests if not t.uses_swarming]
    failed_tests = []

    # Creates a coverage context if coverage is tracked. Null object otherwise.
    coverage_context = self.create_coverage_context()

    # Make sure swarming triggers come first.
    # TODO(machenbach): Port this for rerun for bisection.
    for t in swarming_tests + non_swarming_tests:
      try:
        t.pre_run(coverage_context=coverage_context)
      except self.m.step.InfraFailure:  # pragma: no cover
        raise
      except self.m.step.StepFailure:  # pragma: no cover
        failed_tests.append(t)

    # Setup initial zero coverage after all swarming jobs are triggered.
    coverage_context.setup()

    # Make sure non-swarming tests are run before swarming results are
    # collected.
    for t in non_swarming_tests + swarming_tests:
      try:
        test_results += t.run(coverage_context=coverage_context)
      except self.m.step.InfraFailure:  # pragma: no cover
        raise
      except self.m.step.StepFailure:  # pragma: no cover
        failed_tests.append(t)

    # Upload accumulated coverage data.
    coverage_context.maybe_upload()

    if failed_tests:
      failed_tests_names = [t.name for t in failed_tests]
      raise self.m.step.StepFailure(
          '%d tests failed: %r' % (len(failed_tests), failed_tests_names))
    self.test_duration_sec = self.m.time.time() - start_time_sec
    return test_results

  def maybe_bisect(self, test_results):
    """Build-local bisection for one failure."""
    # Don't activate for branch or fyi bots.
    if self.m.properties['mastername'] not in ['client.v8', 'client.v8.ports']:
      return

    if self.bot_config.get('disable_auto_bisect'):  # pragma: no cover
      return

    # Only bisect over failures not flakes. Rerun only the fastest test.
    try:
      failure = min(test_results.failures, key=lambda r: r.duration)
    except ValueError:
      return

    # Only bisect if the fastest failure is significantly faster than the
    # ongoing build's total.
    duration_factor = self.m.properties.get(
        'bisect_duration_factor', BISECT_DURATION_FACTOR)
    if (failure.duration * duration_factor > self.test_duration_sec):
      step_result = self.m.step(
          'Bisection disabled - test too slow', cmd=None)
      return

    # Don't retry failures during bisection.
    self.rerun_failures_count = 0

    # Suppress using shards to be able to rerun single tests.
    self.c.testing.may_shard = False

    # Only rebuild the target of the test to retry.
    targets = [failure.failure_dict.get('target_name', 'All')]

    test = self.create_test(failure.test_step_config)
    def test_func(revision):
      return test.rerun(failure_dict=failure.failure_dict)

    def is_bad(revision):
      with self.m.step.nest('Bisect ' + revision[:8]):
        if not self.is_pure_swarming_tester:
          self.checkout(revision, update_presentation=False)
        if self.bot_type == 'builder_tester':
          self.runhooks()
          self.compile(targets=targets)
        elif self.bot_type == 'tester':
          if test.uses_swarming:
            self.download_isolated_json(revision)
          else:  # pragma: no cover
            raise self.m.step.InfraFailure('Swarming required for bisect.')
        else:  # pragma: no cover
          raise self.m.step.InfraFailure(
              'Bot type %s not supported.' % self.bot_type)
        result = test_func(revision)
        if result.infra_failures:  # pragma: no cover
          raise self.m.step.InfraFailure(
              'Cannot continue bisection due to infra failures.')
        return result.failures

    with self.m.step.nest('Bisect'):
      # Setup bisection range ("from" exclusive).
      latest_previous, bisect_range = self.get_change_range()
      if len(bisect_range) <= 1:
        self.m.step('disabled - less than two changes', cmd=None)
        return

      if self.bot_type == 'tester':
        # Filter the bisect range to the revisions for which isolate hashes or
        # archived builds are available, depending on whether swarming is used
        # or not.
        available_bisect_range = self.get_available_range(
            bisect_range, test.uses_swarming)
      else:
        available_bisect_range = bisect_range

    if is_bad(latest_previous):
      # If latest_previous is already "bad", the test failed before the current
      # build's change range, i.e. it is a recurring failure.
      # TODO: Try to be smarter here, fetch the build data from the previous
      # one or two builds and check if the failure happened in revision
      # latest_previous. Otherwise, the cost of calling is_bad is as much as
      # one bisect step.
      step_result = self.m.step(
          'Bisection disabled - recurring failure', cmd=None)
      step_result.presentation.status = self.m.step.WARNING
      return

    # Log available revisions to ease debugging.
    self.log_available_range(available_bisect_range)

    culprit = bisection.keyed_bisect(available_bisect_range, is_bad)
    culprit_range = self.calc_missing_values_in_sequence(
        bisect_range,
        available_bisect_range,
        culprit,
    )
    self.report_culprits(culprit_range)

  @staticmethod
  def format_duration(duration_in_seconds):
    duration = datetime.timedelta(seconds=duration_in_seconds)
    time = (datetime.datetime.min + duration).time()
    return time.strftime('%M:%S:') + '%03i' % int(time.microsecond / 1000)

  def _command_results_text(self, results, flaky):
    """Returns log lines for all results of a unique command."""
    assert results
    lines = []

    # Add common description for multiple runs.
    flaky_suffix = ' (flaky in a repeated run)' if flaky else ''
    lines.append('Test: %s%s' % (results[0]['name'], flaky_suffix))
    lines.append('Flags: %s' % ' '.join(results[0]['flags']))
    lines.append('Command: %s' % results[0]['command'])
    lines.append('Variant: %s' % results[0]['variant'])
    lines.append('')
    lines.append('Build environment:')
    build_environment = self.build_environment
    if build_environment is None:
      lines.append(
          'Not available. Please look up the builder\'s configuration.')
    else:
      for key in sorted(build_environment):
        lines.append(' %s: %s' % (key, build_environment[key]))
    lines.append('')

    # Add results for each run of a command.
    for result in sorted(results, key=lambda r: int(r['run'])):
      lines.append('Run #%d' % int(result['run']))
      lines.append('Exit code: %s' % result['exit_code'])
      lines.append('Result: %s' % result['result'])
      if result.get('expected'):
        lines.append('Expected outcomes: %s' % ", ".join(result['expected']))
      lines.append('Duration: %s' % V8Api.format_duration(result['duration']))
      lines.append('')
      if result['stdout']:
        lines.append('Stdout:')
        lines.extend(result['stdout'].splitlines())
        lines.append('')
      if result['stderr']:
        lines.append('Stderr:')
        lines.extend(result['stderr'].splitlines())
        lines.append('')
    return lines

  def _duration_results_text(self, test):
    return [
      'Test: %s' % test['name'],
      'Flags: %s' % ' '.join(test['flags']),
      'Command: %s' % test['command'],
      'Duration: %s' % V8Api.format_duration(test['duration']),
    ]

  def _update_durations(self, output, presentation):
    # Slowest tests duration summary.
    lines = []
    for test in output['slowest_tests']:
      suffix = ''
      if test.get('marked_slow') is False:
        suffix = ' *'
      lines.append(
          '%s %s%s' % (V8Api.format_duration(test['duration']),
                       test['name'], suffix))

    # Slowest tests duration details.
    lines.extend(['', 'Details:', ''])
    for test in output['slowest_tests']:
      lines.extend(self._duration_results_text(test))
    presentation.logs['durations'] = lines

  def _get_failure_logs(self, output, failure_factory):
    def all_same(items):
      return all(x == items[0] for x in items)

    if not output['results']:
      return {}, [], {}, []

    unique_results = {}
    for result in output['results']:
      # Use test base name as UI label (without suite and directory names).
      label = result['name'].split('/')[-1]
      # Truncate the label if it is still too long.
      if len(label) > MAX_LABEL_SIZE:
        label = label[:MAX_LABEL_SIZE - 2] + '..'
      # Group tests with the same label (usually the same test that ran under
      # different configurations).
      unique_results.setdefault(label, []).append(result)

    failure_log = {}
    flake_log = {}
    failures = []
    flakes = []
    for label in sorted(unique_results.keys()[:MAX_FAILURE_LOGS]):
      failure_lines = []
      flake_lines = []

      # Group results by command. The same command might have run multiple
      # times to detect flakes.
      results_per_command = {}
      for result in unique_results[label]:
        results_per_command.setdefault(result['command'], []).append(result)

      for command in results_per_command:
        # Determine flakiness. A test is flaky if not all results from a unique
        # command are the same (e.g. all 'FAIL').
        if all_same(map(lambda x: x['result'], results_per_command[command])):
          # This is a failure. Only add the data of the first run to the final
          # test results, as rerun data is not important for bisection.
          failure = results_per_command[command][0]
          failures.append(failure_factory(failure, failure['duration']))
          failure_lines += self._command_results_text(
              results_per_command[command], False)
        else:
          # This is a flake. Only add the data of the first run to the final
          # test results, as rerun data is not important for bisection.
          flake = results_per_command[command][0]
          flakes.append(failure_factory(flake, flake['duration']))
          flake_lines += self._command_results_text(
              results_per_command[command], True)

      if failure_lines:
        failure_log[label] = failure_lines
      if flake_lines:
        flake_log[label] = flake_lines

    return failure_log, failures, flake_log, flakes

  def _update_failure_presentation(self, log, failures, presentation):
    for label in sorted(log):
      presentation.logs[label] = log[label]

    if failures:
      # Number of failures.
      presentation.step_text += ('failures: %d<br/>' % len(failures))

  @property
  def extra_flags(self):
    extra_flags = self.m.properties.get('extra_flags', '')
    if isinstance(extra_flags, basestring):
      extra_flags = extra_flags.split()
    assert isinstance(extra_flags, list) or isinstance(extra_flags, tuple)
    return list(extra_flags)

  def _with_extra_flags(self, args):
    """Returns: the arguments with additional extra flags inserted.

    Extends a possibly existing extra flags option.
    """
    if not self.extra_flags:
      return args

    options, args = TEST_RUNNER_PARSER.parse_known_args(args)

    if options.extra_flags:
      new_flags = [options.extra_flags] + self.extra_flags
    else:
      new_flags = self.extra_flags

    args.extend(['--extra-flags', ' '.join(new_flags)])
    return args

  @property
  def test_filter(self):
    return [f for f in self.m.properties.get('testfilter', [])
            if f != 'defaulttests']

  def _applied_test_filter(self, test):
    """Returns: the list of test filters that match a test configuration."""
    # V8 test filters always include the full suite name, followed
    # by more specific paths and possibly ending with a glob, e.g.:
    # 'mjsunit/regression/prefix*'.
    return [f for f in self.test_filter
              for t in test.get('suite_mapping', test['tests'])
              if f.startswith(t)]

  def _setup_test_runner(self, test, applied_test_filter, test_step_config):
    env = {}
    full_args = [
      '--progress=verbose',
      '--mode', self.m.chromium.c.build_config_fs,
      '--outdir', self.m.path.split(self.m.chromium.c.build_dir)[-1],
      '--buildbot',
      '--timeout=200',
    ]

    # Add optional non-standard root directory for test suites.
    if test.get('test_root'):
      full_args += ['--test-root', test['test_root']]

    # On reruns, there's a fixed random seed set in the test configuration.
    if ('--random-seed' not in test.get('test_args', []) and
        test.get('use_random_seed', True)):
      full_args.append('--random-seed=%d' % self.testing_random_seed())

    # Either run tests as specified by the filter (trybots only) or as
    # specified by the test configuration.
    if applied_test_filter:
      full_args += applied_test_filter
    else:
      full_args += list(test.get('tests', []))

    # Add test-specific test arguments.
    full_args += test.get('test_args', [])

    # Add builder-specific test arguments.
    full_args += self.c.testing.test_args

    # Add builder-, test- and step-specific variants.
    full_args += testing.test_args_from_variants(
        self.bot_config.get('variants'),
        test.get('variants'),
        test_step_config.variants,
    )

    # Add step-specific test arguments.
    full_args += test_step_config.test_args

    full_args = self._with_extra_flags(full_args)

    full_args += [
      '--rerun-failures-count=%d' % self.rerun_failures_count,
    ]

    # TODO(machenbach): This is temporary code for rolling out the new test
    # runner. It should be removed after the roll-out. We skip the branches
    # waterfall, as it runs older versions of the V8 side.
    if self.m.properties['mastername'] != 'client.v8.branches':
      full_args += [
        '--mastername', self.m.properties['mastername'],
        '--buildername', self.m.properties['buildername'],
      ]

    return full_args, env

  @staticmethod
  def _copy_property(src, dest, key):
    if key in src:
      dest[key] = src[key]

  def maybe_trigger(self, test_spec=EmptyTestSpec, **additional_properties):
    triggers = self.bot_config.get('triggers', [])
    triggers_proxy = self.bot_config.get('triggers_proxy', False)
    triggered_build_ids = []
    if triggers or triggers_proxy:
      # Careful! Before adding new properties, note the following:
      # Triggered bots on CQ will either need new properties to be explicitly
      # whitelisted or their name should be prefixed with 'parent_'.
      properties = {
        'parent_got_revision': self.revision,
        'parent_buildername': self.m.properties['buildername'],
        'parent_build_config': self.m.chromium.c.BUILD_CONFIG,
      }
      if self.revision_cp:
        properties['parent_got_revision_cp'] = self.revision_cp
      if self.m.tryserver.is_tryserver:
        properties.update(
          category=self.m.properties.get('category', 'manual_ts'),
          reason=str(self.m.properties.get('reason', 'ManualTS')),
          # On tryservers, set revision to the same as on the current bot,
          # as CQ expects builders and testers to match the revision field.
          revision=str(self.m.properties.get('revision', 'HEAD')),
        )
        for p in ['issue', 'master', 'patch_gerrit_url', 'patch_git_url',
                  'patch_issue', 'patch_project', 'patch_ref',
                  'patch_repository_url', 'patch_set', 'patch_storage',
                  'patchset', 'requester', 'rietveld']:
          try:
            properties[p] = str(self.m.properties[p])
          except KeyError:
            pass
      else:
        # On non-tryservers, we can set the revision to whatever the
        # triggering builder checked out.
        properties['revision'] = self.revision

      if self.m.properties.get('testfilter'):
        properties.update(testfilter=list(self.m.properties['testfilter']))
      self._copy_property(self.m.properties, properties, 'extra_flags')

      # TODO(machenbach): Also set meaningful buildbucket tags of triggering
      # parent.

      # Pass build environment to testers if it doesn't exceed buildbot's
      # limits.
      # TODO(machenbach): Remove the check in the after-buildbot age.
      if len(self.m.json.dumps(self.build_environment)) < 1024:
        properties['parent_build_environment'] = self.build_environment

      swarm_hashes = self.m.isolate.isolated_tests
      if swarm_hashes:
        properties['swarm_hashes'] = swarm_hashes
      properties.update(**additional_properties)

      if self.m.tryserver.is_tryserver:
        if triggers:
          trigger_props = {}
          self._copy_property(self.m.properties, trigger_props, 'git_revision')
          self._copy_property(self.m.properties, trigger_props, 'revision')
          trigger_props.update(properties)
          try:
            bucket_name = self.m.buildbucket.properties['build']['bucket']
          except (TypeError, KeyError) as e:
            bucket_name = 'master.%s' % self.m.properties['mastername']
          # Generate a list of fake changes from the blamelist property to have
          # correct blamelist displayed on the child build. Unfortunately, this
          # only copies author names, but additional details about the list of
          # changes associated with the build are currently not accessible from
          # the recipe code.
          step_result = self.buildbucket_trigger(
              bucket_name, self.get_changes(),
              [{
                'builder_name': builder_name,
                'properties': dict(
                    trigger_props,
                    **test_spec.as_properties_dict(builder_name)
                ),
              } for builder_name in triggers],
              # Tryserver uses custom buildset that is set by the buildbucket
              # module itself.
              no_buildset=True,
          )
          triggered_build_ids.extend(
              build['build']['id'] for build in step_result.stdout['results'])
      else:
        ci_properties = dict(properties)
        if self.should_upload_build:
          ci_properties['archive'] = self._get_default_archive()
        if self.m.runtime.is_luci:
          self.m.scheduler.emit_triggers(
              [(
                self.m.scheduler.BuildbucketTrigger(
                  properties=dict(
                    ci_properties,
                    **test_spec.as_properties_dict(builder_name)
                  ),
                  tags={
                    'buildset': 'commit/gitiles/chromium.googlesource.com/v8/'
                                'v8/+/%s' % ci_properties['revision']
                  }
                ), 'v8', [builder_name],
              ) for builder_name in triggers],
              step_name='trigger'
          )
        else:
          self.m.trigger(*[{
            'builder_name': builder_name,
            # Attach additional builder-specific test-spec properties.
            'properties': dict(
                ci_properties,
                **test_spec.as_properties_dict(builder_name)
            ),
          } for builder_name in triggers])

      if triggers_proxy and not self.m.runtime.is_experimental:
        proxy_properties = {'archive': self._get_default_archive()}
        proxy_properties.update(properties)
        self.buildbucket_trigger(
            'master.internal.client.v8', self.get_changes(),
            [{
              'properties': proxy_properties,
              'builder_name': 'v8_trigger_proxy'
            }]
        )

    if triggered_build_ids:
      output_properties = self.m.step.active_result.presentation.properties
      output_properties['triggered_build_ids'] = triggered_build_ids

  def get_changes(self):
    # TODO(sergiyb): Remove this after migrating all builders to LUCI as
    # there the revision from the buildset will be used instead.
    blamelist = self.m.properties.get('blamelist', ['fake-author'])
    return [{'author': email} for email in blamelist]

  def buildbucket_trigger(self, bucket, changes, requests, step_name='trigger',
                          service_account='v8-bot', no_buildset=False):
    """Triggers builds via buildbucket.

    Args:
      bucket: Name of the bucket to add builds to.
      changes: List of changes to be associated with the scheduled build. Each
          entry is a dictionary like this: {'author': ..., 'revision': ...}. The
          revision is optional and will be extracted from build propeties if not
          provided. The author is an arbitrary string or an email address.
      requests: List of requests, where each request is a dictionary like this:
          {'builder_name': ..., 'properties': {'revision': ..., ...}}. Note that
          builder_name and revision are mandatory, whereas additional properties
          are optional.
      step_name: Name of the triggering step that appear on the build.
      service_account: Puppet service account to be used for authentication to
          buildbucket.
      no_buildset: Disable setting custom buildset. Useful when one needs to
          rely on the built-in buildset set by the buildbucket module, e.g. on
          tryserver.
    """
    # TODO(sergiyb): Remove this line after migrating all builders to swarming.
    # There an implicit task account (specified in the cr-buildbucket.cfg) will
    # be used instead.
    if not self.m.runtime.is_luci:
      self.m.buildbucket.use_service_account_key(
          self.m.puppet_service_account.get_key_path(service_account))

    step_result = self.m.buildbucket.put(
        [{
          'bucket': bucket,
          'tags': {} if no_buildset else {
            'buildset': 'commit/gitiles/chromium.googlesource.com/v8/v8/+/%s' %
               request['properties']['revision']
          },
          'parameters': {
            'builder_name': request['builder_name'],
            'properties': request['properties'],
            # This is required by Buildbot to correctly set 'revision' and
            # 'repository' properties, which are used by Milo and the recipe.
            # TODO(sergiyb): Remove this after migrating to LUCI/Swarming.
            'changes': [{
              'author': {'email': change['author']},
              'revision': change.get(
                'revision', request['properties']['revision']),
              'repo_url': 'https://chromium.googlesource.com/v8/v8'
            } for change in changes],
          },
        } for request in requests],
        name=step_name,
        step_test_data=lambda: (
          self.m.v8.test_api.buildbucket_test_data(len(requests))),
    )

    if 'error' in step_result.stdout:
      step_result.presentation.status = self.m.step.FAILURE

    return step_result

  def get_change_range(self):
    if self.m.properties.get('override_changes'):
      # This can be used for manual testing or on a staging builder that
      # simulates a change range.
      changes = self.m.properties['override_changes']
      step_result = self.m.step('Override changes', cmd=None)
      step_result.presentation.logs['changes'] = self.m.json.dumps(
        changes, indent=2).splitlines()
    else:
      # TODO(sergiyb): Migrate to using new Milo API that allows to specify
      # Buildbucket ID to retrieve build info. This will allow to deprecate
      # build numbers for builders using V8 recipe.
      url = '%s/p/%s/builders/%s/builds/%s?json=1' % (
          CBE_URL,
          self.m.properties['mastername'],
          urllib.quote(self.m.properties['buildername']),
          str(self.m.properties['buildnumber']),
      )
      change_json = self.m.url.get_json(
          url,
          step_name='Fetch changes',
          default_test_data=self.test_api.example_buildbot_changes(),
      ).output
      changes = change_json['sourceStamp']['changes']

    assert changes
    first_change = changes[0]['revision']
    last_change = changes[-1]['revision']

    # Commits is a list of gitiles commit dicts in reverse chronological order.
    commits, _ = self.m.gitiles.log(
        url=V8_URL,
        ref='%s~2..%s' % (first_change, last_change),
        limit=100,
        step_name='Get change range',
        step_test_data=lambda: self.test_api.example_bisection_range()
    )

    # We get minimum two commits when the first and last commit are equal (i.e.
    # there was only one commit C). Commits will contain the latest previous
    # commit and C.
    assert len(commits) > 1

    return (
        # Latest previous.
        commits[-1]['commit'],
        # List of commits oldest -> newest, without the latest previous.
        [commit['commit'] for commit in reversed(commits[:-1])],
    )

  def get_available_range(self, bisect_range, use_swarming=False):
    assert self.bot_type == 'tester'
    archive_url_pattern = 'gs://' + self.isolated_archive_path + '/%s.json'
    # TODO(machenbach): Maybe parallelize this in a wrapper script.
    args = ['ls']
    available_range = []
    # Check all builds except the last as we already know it is "bad".
    for r in bisect_range[:-1]:
      step_result = self.m.gsutil(
          args + [archive_url_pattern % r],
          name='check build %s' % r[:8],
          # Allow failures, as the tool will formally fail for any absent file.
          ok_ret='any',
          stdout=self.m.raw_io.output_text(),
          step_test_data=lambda: self.test_api.example_available_builds(r),
      )
      if r in step_result.stdout.strip():
        available_range.append(r)

    # Always keep the latest revision in the range. The latest build is
    # assumed to be "bad" and won't be tested again.
    available_range.append(bisect_range[-1])
    return available_range

  def calc_missing_values_in_sequence(
        self, sequence, subsequence, value):
    """Calculate a list of missing values from a subsequence.

    Args:
      sequence: The complete sequence including all values.
      subsequence: A subsequence from the sequence above.
      value: An element from subsequence.
    Returns: A subsequence from sequence [a..b], where b is the value and
             for all x in a..b-1 holds x not in subsequence. Also
             a-1 is either in subsequence or value was the first
             element in subsequence.
    """
    from_index = 0
    to_index = sequence.index(value) + 1
    index_on_subsequence = subsequence.index(value)
    if index_on_subsequence > 0:
      # Value is not the first element in subsequence.
      previous = subsequence[index_on_subsequence - 1]
      from_index = sequence.index(previous) + 1
    return sequence[from_index:to_index]

  def log_available_range(self, available_bisect_range):
    step_result = self.m.step('Available range', cmd=None)
    for revision in available_bisect_range:
      step_result.presentation.links[revision[:8]] = COMMIT_TEMPLATE % revision

  def report_culprits(self, culprit_range):
    assert culprit_range
    if len(culprit_range) > 1:
      text = 'Suspecting multiple commits'
    else:
      text = 'Suspecting %s' % culprit_range[0][:8]

    step_result = self.m.step(text, cmd=None)
    for culprit in culprit_range:
      step_result.presentation.links[culprit[:8]] = COMMIT_TEMPLATE % culprit

  def read_version_file(self, ref, step_name_desc):
    """Read and return the version-file content at a paricular ref."""
    with self.m.context(cwd=self.m.path['checkout']):
      return self.m.git(
          'show', '%s:%s' % (ref, self.VERSION_FILE),
          name='Check %s version file' % step_name_desc,
          stdout=self.m.raw_io.output_text(),
      ).stdout

  def read_version_from_ref(self, ref, step_name_desc):
    """Read and return the version at a paricular ref."""
    return V8Api.version_from_file(self.read_version_file(ref, step_name_desc))

  @staticmethod
  def version_from_file(blob):
    major = re.search(VERSION_LINE_RE % V8_MAJOR, blob, re.M).group(1)
    minor = re.search(VERSION_LINE_RE % V8_MINOR, blob, re.M).group(1)
    build = re.search(VERSION_LINE_RE % V8_BUILD, blob, re.M).group(1)
    patch = re.search(VERSION_LINE_RE % V8_PATCH, blob, re.M).group(1)
    return V8Version(major, minor, build, patch)
