# Copyright 2014 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 collections
import contextlib
import copy
import itertools
import json
import re
import traceback

from recipe_engine.types import freeze
from recipe_engine import recipe_api

from . import bot_config_and_test_db as bdb_module
from . import builders as chromium_tests_builders
from . import generators
from . import steps


# Paths which affect recipe config and behavior in a way that survives
# deapplying user's patch.
RECIPE_CONFIG_PATHS = [
  'testing/buildbot/.*json$',
  'testing/buildbot/.*pyl$',
]

class ChromiumTestsApi(recipe_api.RecipeApi):
  def __init__(self, *args, **kwargs):
    super(ChromiumTestsApi, self).__init__(*args, **kwargs)
    self._builders = {}
    self.add_builders(chromium_tests_builders.BUILDERS)
    self._precommit_mode = False

  @property
  def builders(self):
    return self._builders

  @property
  def steps(self):
    """The steps module, which contains various Test python classes.

    Usage is generally discouraged.
    """
    return steps

  @property
  def _generators(self):
    """The generators module. Used in module unittests.

    Usually, you'll probably want all_generators, which is guaranteed to contain
    all the generators supported.
    """
    return generators

  @property
  def all_generators(self):
    return [
      generators.generate_isolated_script,
      generators.generate_cts_test,
      generators.generate_gtest,
      generators.generate_instrumentation_test,
      generators.generate_junit_test,
      generators.generate_script,
    ]

  @property
  def trybots(self):
    return self.test_api.trybots

  @property
  def swarming_extra_args(self):
    args = []
    if self.m.chromium.c.runtests.enable_lsan:
      args += ['--lsan=1']
    return args

  def log(self, message):
    presentation = self.m.step.active_result.presentation
    presentation.logs.setdefault('stdout', []).append(message)

  def add_builders(self, builders):
    """Adds builders to our builder map"""
    self._builders.update(builders)

  def create_bot_id(self, mastername, buildername, testername=None):
    bot_id = {
        'mastername': mastername,
        'buildername': buildername,
    }
    # TODO(crbug.com/884425): Figure out a better solution to mimic a tester.
    if testername and testername != buildername:
      bot_id['tester'] = testername
    return bot_id

  def create_bot_config_object(self, bot_ids, builders=None):
    try:
      return bdb_module.BotConfig(builders or self.builders, bot_ids)
    except Exception:
      if (self._test_data.enabled and
          not self._test_data.get('handle_bot_config_errors', True)):
        raise  # pragma: no cover
      self.m.python.failing_step(
          'Incorrect or missing bot configuration',
          [traceback.format_exc()],
          as_log='details')

  def create_bot_db_object(self):
    return bdb_module.BotConfigAndTestDB()

  def set_precommit_mode(self):
    """Configures this module to indicate that tests are running before
    the changes are committed. This must be called very early in the
    recipe, certainly before prepare_checkout, and the action can not
    be undone.
    """
    self._precommit_mode = True

  def is_precommit_mode(self):
    """Returns a Boolean indicating whether this module is running in
    precommit mode; i.e., whether tests are running before the changes
    are committed.
    """
    return self._precommit_mode

  def get_config_defaults(self):
    return {'CHECKOUT_PATH': self.m.path['checkout']}

  def _chromium_config(self, bot_config):
    chromium_config = self.m.chromium.make_config(
        bot_config.get('chromium_config'),
        **bot_config.get('chromium_config_kwargs', {}))

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

    return chromium_config

  def configure_build(self, bot_config, override_bot_type=None):
    # Get the buildspec version. It can be supplied as a build property or as
    # a recipe config value.
    buildspec_version = (self.m.properties.get('buildspec_version') or
                         bot_config.get('buildspec_version'))

    self.m.chromium.set_config(
        bot_config.get('chromium_config'),
        **bot_config.get('chromium_config_kwargs', {}))
    self.set_config(bot_config.get('chromium_tests_config', 'chromium'))

    self.m.gclient.set_config(
        bot_config.get('gclient_config'),
        BUILDSPEC_VERSION=buildspec_version,
        **bot_config.get('gclient_config_kwargs', {}))

    default_test_results_config = (
        'staging_server'
        if self.m.runtime.is_experimental
        else 'public_server')
    self.m.test_results.set_config(
        bot_config.get('test_results_config', default_test_results_config))

    if bot_config.get('android_config'):
      self.m.chromium_android.configure_from_properties(
          bot_config.get('android_config'),
          **bot_config.get('chromium_config_kwargs', {}))

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

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

    for c in bot_config.get('android_apply_config', []):
      self.m.chromium_android.apply_config(c)

    for c in bot_config.get('chromium_tests_apply_config', []):
      self.apply_config(c)

    bot_type = override_bot_type or bot_config.get('bot_type', 'builder_tester')

    if bot_config.get('set_component_rev'):
      # If this is a component build and the main revision is e.g. blink,
      # webrtc, or v8, the custom deps revision of this component must be
      # dynamically set to either:
      # (1) the revision of the builder if this is a tester,
      # (2) gitiles commit id from the waterfall, or
      # (3) 'HEAD' for forced builds with unspecified gitiles commit.
      component_rev = self.m.buildbucket.gitiles_commit.id or 'HEAD'

      if bot_type == 'tester':
        component_rev = self.m.properties.get(
            'parent_got_revision', component_rev)
      dep = bot_config.get('set_component_rev')
      self.m.gclient.c.revisions[dep['name']] = dep['rev_str'] % component_rev


  def set_up_swarming(self, bot_config):
    self.m.swarming.check_client_version()

    if bot_config.get('isolate_server'):
      self.m.isolate.isolate_server = bot_config.get('isolate_server')

    if bot_config.get('swarming_server'):
      self.m.swarming.swarming_server = bot_config.get('swarming_server')

    for key, value in bot_config.get('swarming_dimensions', {}).iteritems():
      self.m.swarming.set_default_dimension(key, value)

    if (bot_config.get('swarming_service_account') and
        not self.m.runtime.is_luci):
      self.m.swarming.service_account_json = (
          self.m.puppet_service_account.get_key_path(
              bot_config.get('swarming_service_account')))

    if (bot_config.get('isolate_service_account') and
        not self.m.runtime.is_luci):
      self.m.isolate.service_account_json = (
          self.m.puppet_service_account.get_key_path(
              bot_config.get('isolate_service_account')))

  def runhooks(self, update_step):
    if self.m.tryserver.is_tryserver:
      try:
        self.m.chromium.runhooks(name='runhooks (with patch)')
      except self.m.step.StepFailure:
        # As part of deapplying patch we call runhooks without the patch.
        self.deapply_patch(update_step)
        raise
    else:
      self.m.chromium.runhooks()

  # TODO(phajdan.jr): remove create_bot_db_from_master_dict. It adds another
  # entry point to _add_master_dict_and_test_spec which can really complicate
  # things.
  def create_bot_db_from_master_dict(self, mastername, master_dict):
    bot_db = self.create_bot_db_object()
    bot_db._add_master_dict_and_source_side_spec(mastername, master_dict, {})
    return bot_db

  def prepare_checkout(self, bot_config, **kwargs):
    update_step = self.m.chromium_checkout.ensure_checkout(bot_config, **kwargs)

    if (self.m.chromium.c.compile_py.compiler and
        'goma' in self.m.chromium.c.compile_py.compiler):
      self.m.chromium.ensure_goma(
          client_type=self.m.chromium.c.compile_py.goma_client_type)

    # Installs toolchains configured in the current bot, if any.
    self.m.chromium.ensure_toolchains()

    self.set_up_swarming(bot_config)
    self.runhooks(update_step)

    bot_db = bdb_module.BotConfigAndTestDB()
    bot_config.initialize_bot_db(self, bot_db, update_step)

    return update_step, bot_db

  def generate_tests_from_source_side_spec(self, source_side_spec, builder_dict,
      buildername, mastername, swarming_dimensions,
      scripts_compile_targets, bot_update_step):
    tests = builder_dict.get('tests', ())
    # TODO(phajdan.jr): Switch everything to scripts generators and simplify.
    for generator in self.all_generators:
      tests = (
          tuple(generator(
              self.m, self, mastername, buildername, source_side_spec,
              bot_update_step,
              swarming_dimensions=swarming_dimensions,
              scripts_compile_targets=scripts_compile_targets)) +
          tuple(tests))
    return tests

  # TODO(martiniss): Remove this
  def generate_tests_from_test_spec(self, *args): # pragma: no cover
    return self.generate_tests_from_source_side_spec(*args)

  def read_source_side_spec(self, source_side_spec_file):
    source_side_spec_path = self.c.source_side_spec_dir.join(
        source_side_spec_file)
    spec_result = self.m.json.read(
        'read test spec (%s)' % self.m.path.basename(source_side_spec_path),
        source_side_spec_path,
        step_test_data=lambda: self.m.json.test_api.output({}))
    spec_result.presentation.step_text = 'path: %s' % source_side_spec_path
    source_side_spec = spec_result.json.output

    return source_side_spec

  def create_test_runner(self, tests, suffix='', serialize_tests=False):
    """Creates a test runner to run a set of tests.

    Args
      api: API of the calling recipe.
      tests: List of step.Test objects to be run.
      suffix: Suffix to be passed when running the tests.
      serialize_tests: True if this bot should run all tests serially
        (specifically, tests run on Swarming). Used to reduce the load
        generated by waterfall bots.

    Returns:
      A function that can be passed to setup_chromium_tests or run directly.

    """

    def test_runner():
      if serialize_tests:
        tests_list = [[t] for t in tests]
      else:
        tests_list = [tests]

      failed_tests = []
      for tl in tests_list:
        failed_ts = self.m.test_utils.run_tests(self.m, tl, suffix)
        failed_tests.extend(failed_ts)

      self.m.swarming.report_stats()

      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))

    return test_runner

  def get_tests(self, bot_config, bot_db):
    """Returns a tuple: list of tests, and list of tests on the triggered
       testers."""

    assert isinstance(bot_db, bdb_module.BotConfigAndTestDB), \
        "bot_db argument %r was not a BotConfigAndTestDB" % (bot_db)

    return bot_config.get_tests(bot_db)

  def get_compile_targets(self, bot_config, bot_db, tests):
    assert isinstance(bot_db, bdb_module.BotConfigAndTestDB), \
        "bot_db argument %r was not a BotConfigAndTestDB" % (bot_db)

    compile_targets = bot_config.get_compile_targets(self, bot_db, tests)
    return sorted(set(compile_targets))

  def _get_android_version_details(self, bot_config, log_details=False):
    version = bot_config.get('android_version')
    if not version:
      return None, None

    version = self._convert_version(self.m.file.read_text(
        'get version',
        self.m.path['checkout'].join(version),
        test_data='MAJOR=51\nMINOR=0\nBUILD=2704\nPATCH=0\n'))
    android_version_name = '%(MAJOR)s.%(MINOR)s.%(BUILD)s.%(PATCH)s' % version
    # TODO: Consider CPU architecture
    android_version_code = '%d%03d' % (int(version['BUILD']),
                                       int(version['PATCH']))
    if log_details:
      self.log('version:%s' % version)
      self.log('android_version_name:%s' % android_version_name)
      self.log('android_version_code:%s' % android_version_code)
    return android_version_name, android_version_code

  def _use_goma(self, chromium_config=None):
    chromium_config = chromium_config or self.m.chromium.c
    return (chromium_config.compile_py.compiler and
            'goma' in chromium_config.compile_py.compiler)

  def compile_specific_targets(
      self, bot_config, update_step, bot_db,
      compile_targets, tests_including_triggered,
      mb_mastername=None, mb_buildername=None,
      mb_phase=None, mb_config_path=None,
      override_bot_type=None):
    """Runs compile and related steps for given builder.

    Allows finer-grained control about exact compile targets used.

    We don't use the given `mastername` and `buildername` to run MB, because
    they may be the values of the continuous builder the trybot may be
    configured to match; instead we need to use the actual mastername and
    buildername we're running on (Default to the "mastername" and
    "buildername" in the build properties -- self.m.properties, but could be
    overridden by `mb_mastername` and `mb_buildername`), because it may be
    configured with different MB settings.

    However, recipes used by Findit for culprit finding may still set
    (mb_mastername, mb_buildername) = (mastername, buildername) to exactly match
    a given continuous builder."""

    assert isinstance(bot_db, bdb_module.BotConfigAndTestDB), \
        "bot_db argument %r was not a BotConfigAndTestDB" % (bot_db)
    bot_type = override_bot_type or bot_config.get('bot_type', 'builder_tester')

    if self.m.chromium.c.TARGET_PLATFORM == 'android':
      self.m.chromium_android.clean_local_files()
      self.m.chromium_android.run_tree_truth()

    if bot_type in ['builder', 'builder_tester']:
      isolated_targets = [
          t.isolate_target
          for t in tests_including_triggered if t.uses_isolate
      ]

      if isolated_targets:
        self.m.isolate.clean_isolated_files(self.m.chromium.output_dir)

      name_suffix = ''
      if self.m.tryserver.is_tryserver:
        name_suffix=' (with patch)'

      try:
        android_version_name, android_version_code = (
            self._get_android_version_details(bot_config, log_details=True))

        self.run_mb_and_compile(compile_targets, isolated_targets,
                                name_suffix=name_suffix,
                                mb_mastername=mb_mastername,
                                mb_buildername=mb_buildername,
                                mb_phase=mb_phase,
                                mb_config_path=mb_config_path,
                                android_version_code=android_version_code,
                                android_version_name=android_version_name)
      except self.m.step.StepFailure:
        self.m.tryserver.set_compile_failure_tryjob_result()
        raise

      if isolated_targets:
        has_patch = self.m.tryserver.is_tryserver
        swarm_hashes_property_name = ''  # By default do not yield as property.
        if 'got_revision_cp' in update_step.presentation.properties:
          # Some recipes such as Findit's may build different revisions in the
          # same build. Hence including the commit position as part of the
          # property name.
          swarm_hashes_property_name = 'swarm_hashes_%s_%s_patch' % (
              update_step.presentation.properties['got_revision_cp'].replace(
                # At sign may clash with annotations format.
                '@', '(at)'), 'with' if has_patch else 'without')

        # 'compile' just prepares all information needed for the isolation,
        # and the isolation is a separate step.
        self.m.isolate.isolate_tests(
            self.m.chromium.output_dir,
            suffix=name_suffix,
            targets=list(set(isolated_targets)),
            verbose=True,
            swarm_hashes_property_name=swarm_hashes_property_name)

        if bot_config.get('perf_isolate_lookup'):
          self.m.perf_dashboard.upload_isolate(
              self.m.buildbucket.builder_name,
              self.m.perf_dashboard.get_change_info([{
                  'repository': 'chromium',
                  'git_hash':
                      update_step.presentation.properties['got_revision'],
              }]),
              self.m.isolate.isolate_server,
              self.m.isolate.isolated_tests)

  def package_build(self, mastername, buildername, update_step, bot_db):
    """Zip and upload the build to google storage.

    This is currently used for transfer between builder and tester,
    including bisect testers.

    Note that:
      - this will only upload when called from pure builders. On builder_testers
        and testers, this is a no-op.
      - this is a no-op for builders that upload to clusterfuzz; those are
        handled in archive_build.
      - this may upload twice on perf builders.
    """
    bot_config = bot_db.get_bot_config(mastername, buildername)

    bot_type = bot_config.get('bot_type')
    assert bot_type in ('builder', 'builder_tester'), (
        'Called package_build for %s:%s, which is a "%s". '
        'package_build only supports "builder" and "builder_tester". '
        'This is a bug in your recipe.' % (mastername, buildername, bot_type))

    if not bot_config.get('cf_archive_build'):
      master_config = bot_db.get_master_settings(mastername)
      build_revision = update_step.presentation.properties.get(
          'got_revision',
          update_step.presentation.properties.get('got_src_revision'))


      # For archiving 'chromium.perf', the builder also archives a version
      # without perf test files for manual bisect.
      # (https://bugs.chromium.org/p/chromium/issues/detail?id=604452)
      if (master_config.get('bisect_builders') and
          buildername in master_config.get('bisect_builders')):
        self.m.archive.zip_and_upload_build(
            'package build for bisect',
            self.m.chromium.c.build_config_fs,
            build_url=self._build_bisect_gs_archive_url(master_config),
            build_revision=build_revision,
            cros_board=self.m.chromium.c.TARGET_CROS_BOARD,
            update_properties=update_step.presentation.properties,
            exclude_perf_test_files=True,
            store_by_hash=False,
            platform=self.m.chromium.c.HOST_PLATFORM
        )

      return self.m.archive.zip_and_upload_build(
          'package build',
          self.m.chromium.c.build_config_fs,
          build_url=self._build_gs_archive_url(
              mastername, master_config, buildername),
          build_revision=build_revision,
          cros_board=self.m.chromium.c.TARGET_CROS_BOARD,
          # TODO(machenbach): Make asan a configuration switch.
          package_dsym_files=(
              self.m.chromium.c.runtests.enable_asan and
              self.m.chromium.c.HOST_PLATFORM == 'mac'),
      )


  def archive_build(self, mastername, buildername, update_step, bot_db):
    """Archive the build if the bot is configured to do so.

    See api.archive.clusterfuzz_archive and archive_build.py for more
    information.

    This is currently used to store builds long-term and to transfer them
    to clusterfuzz.
    """
    bot_config = bot_db.get_bot_config(mastername, buildername)

    if bot_config.get('archive_build') and not self.m.tryserver.is_tryserver:
      self.m.chromium.archive_build(
          'archive_build',
          bot_config['gs_bucket'],
          bot_config.get('gs_acl'),
          mode='dev',
          build_name=bot_config.get('gs_build_name'),
      )
    if bot_config.get('cf_archive_build') and not self.m.tryserver.is_tryserver:
       self.m.archive.clusterfuzz_archive(
         build_dir=self.m.chromium.c.build_dir.join(
         self.m.chromium.c.build_config_fs),
         update_properties=update_step.presentation.properties,
         gs_bucket=bot_config.get('cf_gs_bucket'),
         gs_acl=bot_config.get('cf_gs_acl'),
         archive_prefix=bot_config.get('cf_archive_name'),
         archive_subdir_suffix=bot_config.get('cf_archive_subdir_suffix', ''),
         revision_dir=bot_config.get('cf_revision_dir'),
       )

  def trigger_child_builds(self, mastername, buildername, update_step, bot_db,
                           additional_properties=None):
    additional_properties = additional_properties or {}

    # If you modify parameters or properties, make sure to modify it for both
    # legacy and LUCI cases below.
    if not self.m.runtime.is_luci:
      # Legacy buildbot-only triggering.
      # TODO(tandrii): get rid of legacy triggering.
      trigger_specs = []
      for _, loop_mastername, loop_buildername, _ in sorted(
          bot_db.bot_configs_matching_parent_buildername(
              mastername, buildername)):
        trigger_spec = {
            'builder_name': loop_buildername,
            'properties': {
                'parent_mastername': mastername,
            },
        }
        if mastername != loop_mastername:
          trigger_spec['bucket'] = 'master.' + loop_mastername
        for name, value in update_step.presentation.properties.iteritems():
          if name.startswith('got_'):
            trigger_spec['properties']['parent_' + name] = value
        trigger_spec['properties'].update(additional_properties)
        trigger_specs.append(trigger_spec)
      if trigger_specs:
        self.m.trigger(*trigger_specs)
      return

    # LUCI-Scheduler-based triggering (required on luci stack).
    properties = {
      'parent_mastername': mastername,
      'parent_buildername': buildername,
    }
    for name, value in update_step.presentation.properties.iteritems():
      if name.startswith('got_'):
        properties['parent_' + name] = value
    # Work around https://crbug.com/785462 in LUCI UI that ignores
    # buildset's revision and needs actual 'revision' property.
    if 'parent_got_revision' in properties:
      properties['revision'] = properties['parent_got_revision']

    properties.update(additional_properties)

    scheduler_jobs = collections.defaultdict(list)
    for luci_project, loop_mastername, loop_buildername, _ in sorted(
        bot_db.bot_configs_matching_parent_buildername(
            mastername, buildername)):
      # LUCI mode will emulate triggering of builds inside master.chromium*
      # masters which are all mapped into luci.chromium.ci bucket. The
      # triggering will go through LUCI Scheduler to ensure that outstanding
      # triggers get merged if triggered builder (aka loop_buildername) is too
      # slow. LUCI Scheduler `project` is chromium and `job` names are the same
      # as builder names. Config is located here:
      # https://chromium.googlesource.com/chromium/src/+/infra/config/luci-scheduler.cfg
      #
      # Schematically:
      #   <this build> --triggers--> LUCI Scheduler --triggers--> Buildbucket.
      scheduler_jobs[luci_project].append(loop_buildername)

    if scheduler_jobs:
      self.m.scheduler.emit_triggers(
          ((self.m.scheduler.BuildbucketTrigger(properties=properties),
            project, jobs)
           for project, jobs in scheduler_jobs.iteritems()),
          step_name='trigger')

  def run_mb_and_compile(self, compile_targets, isolated_targets, name_suffix,
                         mb_mastername=None, mb_buildername=None, mb_phase=None,
                         mb_config_path=None, android_version_code=None,
                         android_version_name=None):
    use_goma_module=False
    if self.m.chromium.c.project_generator.tool == 'mb':
      mb_mastername = mb_mastername or self.m.properties['mastername']
      mb_buildername = mb_buildername or self.m.buildbucket.builder_name
      use_goma = self._use_goma()
      self.m.chromium.mb_gen(mb_mastername, mb_buildername,
                             phase=mb_phase,
                             mb_config_path=mb_config_path,
                             use_goma=use_goma,
                             isolated_targets=isolated_targets,
                             name='generate_build_files%s' % name_suffix,
                             android_version_code=android_version_code,
                             android_version_name=android_version_name)
      if use_goma:
        use_goma_module = True

    self.m.chromium.compile(compile_targets, name='compile%s' % name_suffix,
                            use_goma_module=use_goma_module)

  def download_and_unzip_build(self, mastername, buildername, update_step,
                               bot_db, build_archive_url=None,
                               build_revision=None, override_bot_type=None,
                               read_gn_args=True):
    assert isinstance(bot_db, bdb_module.BotConfigAndTestDB), \
        "bot_db argument %r was not a BotConfigAndTestDB" % (bot_db)
    # We only want to do this for tester bots (i.e. those which do not compile
    # locally).
    bot_type = override_bot_type or bot_db.get_bot_config(
        mastername, buildername).get('bot_type')
    if bot_type != 'tester':  # pragma: no cover
      return

    # Protect against hard to debug mismatches between directory names
    # used to run tests from and extract build to. We've had several cases
    # where a stale build directory was used on a tester, and the extracted
    # build was not used at all, leading to confusion why source code changes
    # are not taking effect.
    #
    # The best way to ensure the old build directory is not used is to
    # remove it.
    self.m.file.rmtree(
      'build directory',
      self.m.chromium.c.build_dir.join(self.m.chromium.c.build_config_fs))

    legacy_build_url = None
    build_revision = (
        build_revision
        or self.m.properties.get('parent_got_revision')
        or update_step.presentation.properties.get('got_revision')
        or update_step.presentation.properties.get('got_src_revision'))
    build_archive_url = build_archive_url or self.m.properties.get(
        'parent_build_archive_url')
    if not build_archive_url:
      master_config = bot_db.get_master_settings(mastername)
      legacy_build_url = self._make_legacy_build_url(master_config, mastername)

    self.m.archive.download_and_unzip_build(
      step_name='extract build',
      target=self.m.chromium.c.build_config_fs,
      build_url=legacy_build_url,
      build_revision=build_revision,
      build_archive_url=build_archive_url)

    if read_gn_args:
      self.m.gn.get_args(
          self.m.chromium.c.build_dir.join(self.m.chromium.c.build_config_fs))

  def _make_legacy_build_url(self, master_config, mastername):
    # The master where the build was zipped and uploaded from.
    source_master = self.m.properties.get('parent_mastername')
    if not source_master:
      source_master = self.m.properties['mastername']
    return self.m.archive.legacy_download_url(
               master_config.get('build_gs_bucket'),
               extra_url_components=(
                   None if mastername.startswith('chromium.perf')
                   else source_master))

  @contextlib.contextmanager
  def wrap_chromium_tests(self, bot_config, tests=None):
    with self.m.context(
        cwd=self.m.chromium_checkout.working_dir or self.m.path['start_dir'],
        env=self.m.chromium.get_env()):
      bot_type = bot_config.get('bot_type', 'builder_tester')

      if bot_type in ('tester', 'builder_tester'):
        isolated_targets = [
            t.isolate_target
            for t in tests if t.uses_isolate]
        if isolated_targets:
          self.m.isolate.find_isolated_tests(self.m.chromium.output_dir)

      if bot_type == 'tester':
        if (self.m.chromium.c.TARGET_PLATFORM == 'android' and
            bot_config.get('root_devices')):
          self.m.adb.root_devices()

      # Some recipes use this wrapper to setup devices and have their own way
      # to run tests. If platform is Android and tests is None, run device
      # steps.
      require_device_steps = (tests is None or
                              any([t.uses_local_devices for t in tests]))

      if (self.m.chromium.c.TARGET_PLATFORM == 'android' and
          require_device_steps):
        #TODO(prasadv): Remove this hack and implement specific functions
        # at the point of call.
        perf_setup = bot_config.matches_any_bot_id(lambda bot_id:
            bot_id.mastername.startswith('chromium.perf') or
            bot_id.mastername.startswith('tryserver.chromium.perf'))
        self.m.chromium_android.common_tests_setup_steps(perf_setup=perf_setup)

      for test in (tests or []):
        for set_up_step in (test.set_up or []):
          self.m.python(
              set_up_step['name'],
              set_up_step['script'],
              args=set_up_step['args'])
      try:
        yield
      finally:
        if self.m.clang_coverage.using_coverage:
          self.m.clang_coverage.process_coverage_data(tests)
        for test in (tests or []):
          for tear_down_step in (test.tear_down or []):
            self.m.python(
                tear_down_step['name'],
                tear_down_step['script'],
                args=tear_down_step['args'])

        if self.m.platform.is_win:
          self.m.chromium.process_dumps()

        checkout_dir = None
        if self.m.chromium_checkout.working_dir:
          checkout_dir = self.m.chromium_checkout.working_dir.join('src')
        if self.m.chromium.c.TARGET_PLATFORM == 'android':
          if require_device_steps:
            self.m.chromium_android.common_tests_final_steps(
                logcat_gs_bucket='chromium-android',
                checkout_dir=checkout_dir)
          else:
            self.m.chromium_android.test_report()

  def deapply_patch(self, bot_update_step):
    assert self.m.tryserver.is_tryserver

    if self.m.platform.is_win:
      self.m.chromium.taskkill()

    with self.m.context(cwd=self.m.chromium_checkout.working_dir):
      self.m.bot_update.deapply_patch(bot_update_step)

    with self.m.context(cwd=self.m.path['checkout']):
      self.m.chromium.runhooks(name='runhooks (without patch)')


  def _build_and_isolate_failing_tests(self, failing_tests, bot_update_step,
                                       suffix):
    """Builds and isolates test suites in |failing_tests|.

    Args:
      failing_tests: An iterable of test_suites that need to be rebuilt.
      bot_update_step: Contains information about the current checkout. Used to
                       set swarming properties.
      suffix: Should be either 'without patch' or 'retry with patch'. Used to
              annotate steps and swarming properties.
    """
    compile_targets = list(itertools.chain(
        *[t.compile_targets(self.m) for t in failing_tests]))
    if compile_targets:
      # Remove duplicate targets.
      compile_targets = sorted(set(compile_targets))
      failing_swarming_tests = [
          t.isolate_target
          for t in failing_tests if t.uses_isolate]
      if failing_swarming_tests:
        self.m.isolate.clean_isolated_files(self.m.chromium.output_dir)
      self.run_mb_and_compile(compile_targets, failing_swarming_tests,
                              ' (%s)' % suffix)
      if failing_swarming_tests:
        swarm_hashes_property_name = 'swarm_hashes'
        if 'got_revision_cp' in bot_update_step.presentation.properties:
          revision_cp = (bot_update_step.
              presentation.properties['got_revision_cp'].replace('@', '(at)'))
          swarm_hashes_property_name = 'swarm_hashes_%s_%s' % (
              revision_cp, suffix.replace(' ', '_'))
        self.m.isolate.isolate_tests(
            self.m.chromium.output_dir,
            suffix=' (%s)' % suffix,
            swarm_hashes_property_name=swarm_hashes_property_name,
            verbose=True)


  def _deapply_patch_build_isolate(self, failing_tests, bot_update_step):
    """Deapplies patch. Then builds and isolates failing test suites.

    This method requires that the following steps have occurred:
      * Patch applied
      * Test suites built + isolated
      * Test suites have been run. Some have failures.

    Args:
      failing_tests: An iterable of Test objects. Each represents a failing test
                     suite. The list of exact test failures are stored on the
                     Test object itself.
      bot_update_step: Properties from the update_step when the patch was
                       applied. Used to update presentation properties of the
                       isolate step.
    """
    # The implementation of bot_update.deapply_patch is stateful. It will
    # deapply the patch, but keep the same ToT revision from the initial patch
    # application. bot_update.deapply_patch will update DEPS, since it's
    # possible that the patch was a DEPS change.
    self.deapply_patch(bot_update_step)
    self._build_and_isolate_failing_tests(failing_tests, bot_update_step,
                                          'without patch')


  def _reapply_patch(self, bot_config):
    """Rolls checkout. Reapplies patch.

    Args:
      bot_config: Contains checkout configuration.

    Returns: An update_step that contains information about the checkout
             revision.
    """
    assert self.m.tryserver.is_tryserver

    # First, we must roll checkout and reapply the patch. The chromium_checkout
    # recipe_module is stateful and uses revisions pinned by the dictionary
    # gclient.c.revisions. We clear all pinned revisions.
    self.m.gclient.c.revisions.clear()

    update_step = self.m.chromium_checkout.ensure_checkout(bot_config)

    with self.m.context(cwd=self.m.path['checkout']):
      self.m.chromium.runhooks(name='runhooks (retry with patch)')

    return update_step

  def _reapply_patch_build_isolate(self, failing_tests, bot_config):
    """Rolls checkout. Reapplies patch. Builds and isolates failing test suites.

    Args:
      failing_tests: An iterable of Test objects. Each represents a failing test
                     suite. The list of exact test failures are stored on the
                     Test object itself.
      bot_config: Contains checkout configuration.
    """
    update_step = self._reapply_patch(bot_config)
    self._build_and_isolate_failing_tests(failing_tests, update_step,
                                          'retry with patch')


  def _should_retry_with_patch_deapplied(self, affected_files):
    """Whether to retry failing test suites with patch deapplied.

    Returns: Boolean
    """
    # We skip the deapply_patch step if there are modifications that affect the
    # recipe itself, since that would potentially invalidate the previous test
    # results.
    exclusion_regexs = [re.compile(path) for path in RECIPE_CONFIG_PATHS]
    for f in affected_files:
      for regex in exclusion_regexs:
        if regex.match(f):
          return False

    return True

  def _run_tests_on_tryserver(self, bot_config, tests, bot_update_step,
                              affected_files):
    """Runs tests with retries.

    This function runs tests with the CL patched in. On failure, this will
    deapply the patch, rebuild/isolate binaries, and run the failing tests.
    """
    with self.wrap_chromium_tests(bot_config, tests):
      # Run the test. The isolates have already been created.
      failing_tests = self.m.test_utils.run_tests_with_patch(self.m, tests)

      # If there are no failures or if the config says that we only care about
      # the results with patch, we are done.
      if not failing_tests or self.c.only_with_patch:
        return

      # If there are failures but we shouldn't deapply the patch, then skip the
      # 'deapply patch' step.
      should_deapply_patch = (
          self._should_retry_with_patch_deapplied(affected_files))
      test_suites_to_retry_with_patch = []

      # If there are tests that failed, for which we are skipping both
      # 'without patch' and 'retry with patch', then the failures are fatal.
      if not should_deapply_patch:
        for t in failing_tests:
          if not t.should_retry_with_patch:
            self.m.test_utils.summarize_failing_test_with_no_retries(self.m, t)

      if should_deapply_patch:
        deferred_retry_results = []
        # Deapply the patch. Then rerun failing tests.
        self._deapply_patch_build_isolate(failing_tests, bot_update_step)
        self.m.test_utils.run_tests(self.m, failing_tests, 'without patch')

        # Summarize results.
        with self.m.step.defer_results():
          for t in failing_tests:
            # If we are not planning to run 'retry with patch', then failures
            # are fatal.
            failure_is_fatal = not t.should_retry_with_patch
            deferred_result = (self.m.test_utils.
              summarize_test_with_patch_deapplied(
                  self.m, t, failure_is_fatal=failure_is_fatal))

            if t.should_retry_with_patch:
              deferred_retry_results.append((deferred_result, t))

        # Looks for test suites that have to be retried.
        for deferred_result, test in deferred_retry_results:
          if not deferred_result.get_result():
            test_suites_to_retry_with_patch.append(test)
      else:
        test_suites_to_retry_with_patch = failing_tests

      # Early exit if all test_suites are passing.
      if not test_suites_to_retry_with_patch:
        return

      # Reapply the patch. Then rerun failing tests.
      self._reapply_patch_build_isolate(test_suites_to_retry_with_patch,
                                        bot_config)
      self.m.test_utils.run_tests(self.m, test_suites_to_retry_with_patch,
                                  'retry with patch')
      with self.m.step.defer_results():
        for t in test_suites_to_retry_with_patch:
          self.m.test_utils.summarize_test_with_patch_reapplied(self.m, t)

  def _build_bisect_gs_archive_url(self, master_config):
    return self.m.archive.legacy_upload_url(
        master_config.get('bisect_build_gs_bucket'),
        extra_url_components=master_config.get('bisect_build_gs_extra'))

  def _build_gs_archive_url(self, mastername, master_config, buildername):
    """Returns the archive URL to pass to self.m.archive.zip_and_upload_build.

    Most builders on most masters use a standard format for the build archive
    URL, but some builders on some masters may specify custom places to upload
    builds to. These special cases include:
      'chromium.perf' or 'chromium.perf.fyi':
        Exclude the name of the master from the url.
      'tryserver.chromium.perf', or
          linux_full_bisect_builder on 'tryserver.chromium.linux':
        Return None so that the archive url specified in factory_properties
        (as set on the master's configuration) is used instead.
    """
    if mastername.startswith('chromium.perf'):
      return self.m.archive.legacy_upload_url(
          master_config.get('build_gs_bucket'),
          extra_url_components=None)
    elif (mastername == 'tryserver.chromium.perf' or
          (mastername == 'tryserver.chromium.linux' and
           buildername == 'linux_full_bisect_builder')):
      return None
    else:
      return self.m.archive.legacy_upload_url(
          master_config.get('build_gs_bucket'),
          extra_url_components=self.m.properties['mastername'])

  def get_common_args_for_scripts(self, bot_config=None):
    args = []

    args.extend(['--build-config-fs', self.m.chromium.c.build_config_fs])

    paths = {
      'checkout': self.m.path['checkout'],
      'runit.py': self.package_repo_resource('scripts', 'tools', 'runit.py'),
      'runtest.py': self.package_repo_resource(
          'scripts', 'slave', 'runtest.py'),
    }
    args.extend(['--paths', self.m.json.input(paths)])

    properties = {}
    # TODO(phajdan.jr): Remove buildnumber when no longer used.

    if not bot_config:
      mastername = self.m.properties.get('mastername')
      buildername = self.m.buildbucket.builder_name
      master_dict = self.builders.get(mastername, {})
      bot_config = master_dict.get('builders', {}).get(buildername, {})

    properties['buildername'] = self.m.buildbucket.builder_name
    properties['buildnumber'] = self.m.buildbucket.build.number
    for name in ('bot_id', 'mastername'):
      properties[name] = self.m.properties[name]
    properties['slavename'] = properties['bot_id']

    properties['target_platform'] = self.m.chromium.c.TARGET_PLATFORM

    args.extend(['--properties', self.m.json.input(properties)])

    return args

  def get_compile_targets_for_scripts(self, bot_config=None):
    """This gets the combined compile_targets information from the
    //testing/scripts/get_compile_targets.py script.

    This script returns the compile targets for all of the 'script tests' in
    chromium (including ones that we don't plan to run on this configuration,
    see TODO). The information is returned in the following format:

    {
      "some_script_name.py": ["list", "of", "compile", "targets"],
    }

    Where "some_script_name.py" corresponds to
    "//testing/scripts/some_script_name.py".

    Returns:
      The compile target data in the form described above.

    TODO:
      * Only gather targets for the scripts that we might concievably run.
    """
    result = self.m.python(
        name='get compile targets for scripts',
        script=self.m.path['checkout'].join(
            'testing', 'scripts', 'get_compile_targets.py'),
        args=[
            '--output', self.m.json.output(),
            '--',
        ] + self.get_common_args_for_scripts(bot_config),
        step_test_data=lambda: self.m.json.test_api.output({}))
    return result.json.output

  def main_waterfall_steps(self, mb_config_path=None, builders=None):
    mastername = self.m.properties.get('mastername')
    buildername = self.m.buildbucket.builder_name
    bot_config = self.create_bot_config_object(
        [self.create_bot_id(mastername, buildername)], builders=builders)

    self._report_builders(bot_config)

    self.configure_build(bot_config)
    update_step, bot_db = self.prepare_checkout(bot_config)

    bot_type = bot_config.get('bot_type')
    if bot_type == 'tester':
      # Lookup GN args for the associated builder
      parent_mastername = bot_config.get('parent_mastername', mastername)
      parent_buildername = bot_config.get('parent_buildername')
      parent_bot_config = self.create_bot_config_object(
          [self.create_bot_id(parent_mastername, parent_buildername)],
          builders=builders)
      parent_chromium_config = self._chromium_config(parent_bot_config)
      android_version_name, android_version_code = (
          self._get_android_version_details(parent_bot_config))
      self.m.chromium.mb_lookup(parent_mastername, parent_buildername,
                                mb_config_path=mb_config_path,
                                chromium_config=parent_chromium_config,
                                use_goma=self._use_goma(parent_chromium_config),
                                android_version_name=android_version_name,
                                android_version_code=android_version_code,
                                name='lookup builder GN args')

    test_config = bot_config.get_tests(bot_db)
    if bot_type == 'tester':
      non_isolated_tests = [
          t for t in test_config.tests_on(mastername, buildername)
          if not t.uses_isolate]
      isolate_transfer = (
          # Some of the old buildbot trigger infrastructure may not be
          # able to handle the large number of hashes added to trigger
          # properties below (e.g. crbug.com/882889), so we restrict
          # isolate transfer to LUCI.
          self.m.runtime.is_luci and

          not bool(non_isolated_tests))
      package_transfer = not isolate_transfer

    else:
      isolate_transfer = (
          # Same as above.
          self.m.runtime.is_luci and

          any(t.uses_isolate
              for t in test_config.tests_triggered_by(mastername, buildername)))
      non_isolated_tests = [
          t for t in test_config.tests_triggered_by(mastername, buildername)
          if not t.uses_isolate]
      package_transfer = (
          # Always use package transfer on buildbot.
          not self.m.runtime.is_luci or

          bool(non_isolated_tests) or

          bot_config.get('enable_package_transfer'))

    if package_transfer:
      package_transfer_reasons = [
          'This builder is doing the full package transfer because:'
      ]
      if not self.m.runtime.is_luci:
        package_transfer_reasons.append(
            " - it's still running on buildbot :(")
      for t in non_isolated_tests:
        package_transfer_reasons.append(
            " - %s doesn't use isolate" % t.name)
      if bot_config.get('enable_package_transfer'):
        package_transfer_reasons.append(
            " - package transfer is explicitly enabled")

    compile_targets = self.get_compile_targets(
        bot_config, bot_db, test_config.all_tests())
    self.compile_specific_targets(
        bot_config, update_step, bot_db,
        compile_targets, test_config.all_tests(),
        mb_config_path=mb_config_path)

    additional_trigger_properties = {}
    if isolate_transfer:
      additional_trigger_properties['swarm_hashes'] = (
          self.m.isolate.isolated_tests)
    if package_transfer and bot_type in ('builder', 'builder_tester'):
      package_step = self.package_build(
          mastername, buildername, update_step, bot_db)
      package_step.presentation.logs['why is this running?'] = (
          package_transfer_reasons)

    self.trigger_child_builds(
        mastername, buildername, update_step, bot_db,
        additional_properties=additional_trigger_properties)
    self.archive_build(mastername, buildername, update_step, bot_db)

    if isolate_transfer and bot_type == 'tester':
      self.m.file.rmtree(
        'build directory',
        self.m.chromium.c.build_dir.join(self.m.chromium.c.build_config_fs))
    if package_transfer and bot_type == 'tester':
      # No need to read the GN args since we looked them up for testers already
      self.download_and_unzip_build(
          mastername, buildername, update_step, bot_db, read_gn_args=False)
      self.m.python.succeeding_step(
          'explain extract build',
          package_transfer_reasons,
          as_log='why is this running?')

    tests = test_config.tests_on(mastername, buildername)
    if not tests:
      return

    self.m.chromium_swarming.configure_swarming(
        'chromium', precommit=False, mastername=mastername,
        default_priority=bot_config.get('swarming_default_priority'))
    test_runner = self.create_test_runner(
        tests, serialize_tests=bot_config.get('serialize_tests'))
    with self.wrap_chromium_tests(bot_config, tests):
      test_runner()

  def trybot_steps(self, builders=None, trybots=None):
    with self.m.tryserver.set_failure_hash():
      (bot_config_object, bot_update_step, affected_files, tests) = (
          self._trybot_steps_internal(builders=builders, trybots=trybots))

      self.m.python.succeeding_step('mark: before_tests', '')
      if tests:
        self._run_tests_on_tryserver(
            bot_config_object, tests, bot_update_step, affected_files)
        self.m.swarming.report_stats()

  def _trybot_steps_internal(self, builders=None, trybots=None):
    """Initial configuration for all trybots.

    The main purpose of this method is to determine which tests need to be run.

    Args:
      builders: An optional mapping from <mastername, buildername> to
                build/test settings. For an example of defaults for chromium,
                see scripts/slave/recipe_modules/chromium_tests/chromium.py
      trybots: An optional mapping from <mastername, buildername> of the trybot
               to configurations of the mirrored CI bot. Defaults are in
               ChromiumTestsApi.

    Returns: [a 6-tuple of the following]
      bot_config_object: Configuration for the tests to be run.
      bot_update_step: Holds state on build properties. Used to pass state
                       between methods.
      affected_files: A list of paths affected by the CL.
      tests: A list of Test objects [see chromium_tests/steps.py]. Stateful
             objects that can run tests [possibly remotely via swarming] and
             parse the results. Running tests multiple times is not idempotent
             -- the results of previous runs affect future runs.
    """
    # Most trybots mirror a CI bot. They run the same suite of tests with the
    # same configuration.
    # This logic takes the <mastername, buildername> of the triggering trybot,
    # and looks up the configuration of the mirrored bot. For example,
    # <tryserver.chromium.mac, mac_chromium_dbg_ng> will return:
    # {
    #   'bot_ids': {
    #                'mastername': 'chromium.mac',
    #                'buildername': 'Mac Builder (dbg)',
    #                'tester': 'Mac10.13 Tests (dbg)',
    #              },
    #   'analyze_mode': None
    # }
    # See ChromiumTestsApi for more details.
    mastername = self.m.properties.get('mastername')
    buildername = self.m.buildbucket.builder_name
    trybot_config = (trybots or self.trybots).get(mastername, {}).get(
        'builders', {}).get(buildername)

    # Some trybots do not mirror a CI bot. In this case, return a configuration
    # that uses the same <mastername, buildername> of the triggering trybot.
    if not trybot_config:
      trybot_config = {
        'bot_ids': [self.create_bot_id(mastername, buildername)],
      }

    # bot_config_object contains build/test settings for the mirrored
    # <mastername, buildername>.
    bot_config_object = self.create_bot_config_object(
        trybot_config['bot_ids'], builders=builders)

    self._report_builders(bot_config_object)
    self.set_precommit_mode()

    # Applies build/test configurations from bot_config_object.
    self.configure_build(bot_config_object, override_bot_type='builder_tester')

    self.m.chromium_swarming.configure_swarming(
      'chromium', precommit=True)

    self.m.chromium.apply_config('trybot_flavor')

    # This rolls chromium checkout, applies the patch, runs gclient sync to
    # update all DEPS.
    bot_update_step, bot_db = self.prepare_checkout(bot_config_object)

    # Determine the tests that would be run if this were a CI tester.
    # Tests are instances of class(Test) from chromium_tests/steps.py. These
    # objects know how to dispatch isolate tasks, parse results, and keep
    # state on the results of previous test runs.
    test_config = self.get_tests(bot_config_object, bot_db)
    tests = test_config.tests_in_scope()
    tests_including_triggered = test_config.all_tests()

    affected_files = self.m.chromium_checkout.get_files_affected_by_patch()

    if self.m.clang_coverage.using_coverage:
      self.m.clang_coverage.instrument(affected_files)

    if self.m.tryserver.is_tryserver:
      self.m.tryserver.set_subproject_tag('chromium')

    # Determine the compile targets for the tests that would be run.
    compile_targets = self.get_compile_targets(
        bot_config_object,
        bot_db,
        test_config.all_tests())
    test_targets = sorted(set(
        self._all_compile_targets(test_config.all_tests())))

    # Use analyze to determine the compile targets that are affected by the CL.
    # Use this to prune the relevant compile targets and test targets.
    if self.m.tryserver.is_tryserver:
      additional_compile_targets = sorted(
          set(compile_targets) - set(test_targets))
      analyze_names = ['chromium'] + list(
          trybot_config.get('analyze_names', []))
      mb_config_path = (
          self.m.chromium.c.project_generator.config_path
          or self.m.path['checkout'].join('tools', 'mb', 'mb_config.pyl'))
      test_targets, compile_targets = self.m.filter.analyze(
          affected_files, test_targets, additional_compile_targets,
          'trybot_analyze_config.json',
          mb_mastername=mastername,
          mb_buildername=buildername,
          mb_config_path=mb_config_path,
          additional_names=analyze_names)

    # If this is a compile-only trybot, then clear our all tests. This cannot be
    # done sooner because we still want to determine the minimal set of binaries
    # that need to be compiled, which requires knowing the set of tests that
    # would be run.
    if trybot_config.get('analyze_mode') == 'compile':
      tests = []
      tests_including_triggered = []

    # Compiles and isolates test suites.
    if compile_targets:
      tests = self._tests_in_compile_targets(test_targets, tests)
      tests_including_triggered = self._tests_in_compile_targets(
          test_targets, tests_including_triggered)

      compile_targets = sorted(set(compile_targets))
      self.compile_specific_targets(
          bot_config_object,
          bot_update_step,
          bot_db,
          compile_targets,
          tests_including_triggered,
          override_bot_type='builder_tester')
    else:
      # Even though the patch doesn't require a compile on this platform,
      # we'd still like to run tests not depending on
      # compiled targets (that's obviously not covered by the
      # 'analyze' step) if any source files change.
      if any(self._is_source_file(f) for f in affected_files):
        tests = [t for t in tests if not t.compile_targets(self.m)]
      else:
        tests = []

    return (bot_config_object, bot_update_step, affected_files, tests)

  def _report_builders(self, bot_config):
    """Reports the builders being executed by the bot."""
    def present_bot(bot_id):
      if bot_id.tester:
        return ('running tester %r on master %r against builder %r on master %r'
                % (bot_id.tester, bot_id.tester_mastername,
                   bot_id.buildername, bot_id.mastername))
      bot_type = bot_config.get_bot_type(bot_id)
      if bot_type == 'builder_tester':
        bot_type = 'builder/tester'
      return ('running %s \'%s\' on master %r'
              % (bot_type, bot_id.buildername, bot_id.mastername))


    lines = [''] + [present_bot(b) for b in bot_config.bot_ids]
    result = self.m.python.succeeding_step(
        'report builders', '<br/>'.join(lines))

    def as_dict(bot_id):
      if bot_id.tester:
        return {
            'mastername': bot_id.mastername,
            'buildername': bot_id.buildername,
            'tester_buildername': bot_id.tester,
            'tester_mastername': bot_id.tester_mastername,
            'bot_type': 'tester',
        }
      bot_type = bot_config.get_bot_type(bot_id)
      if bot_type == 'builder_tester':
        bot_type = 'builder/tester'
      return {
          'mastername': bot_id.mastername,
          'buildername': bot_id.buildername,
          'bot_type': bot_type,
      }
    bots_json = [as_dict(b) for b in bot_config.bot_ids]
    result.presentation.logs['bots.json'] = self.m.json.dumps(
        bots_json, indent=2).split('/n')

  def _all_compile_targets(self, tests):
    """Returns the compile_targets for all the Tests in |tests|."""
    return sorted(set(x
                      for test in tests
                      for x in test.compile_targets(self.m)))

  def _is_source_file(self, filepath):
    """Returns true iff the file is a source file."""
    _, ext = self.m.path.splitext(filepath)
    return ext in ['.c', '.cc', '.cpp', '.h', '.java', '.mm']

  def _tests_in_compile_targets(self, compile_targets, tests):
    """Returns the tests in |tests| that have at least one of their compile
    targets in |compile_targets|."""
    result = []
    for test in tests:
      test_compile_targets = test.compile_targets(self.m)
      # Always return tests that don't require compile. Otherwise we'd never
      # run them.
      if ((set(compile_targets) & set(test_compile_targets)) or
          not test_compile_targets):
        result.append(test)
    return result

  def _convert_version(self, version):
    """ Convert the version string to a dict. """
    output = {}
    for line in version.splitlines():
      [k,v] = line.split('=', 1)
      output[k] = v
    return output
