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

from google.protobuf import struct_pb2, json_format

from recipe_engine import recipe_api

from recipe_engine.post_process import (
    DoesNotRunRE,
    DropExpectation,
    MustRun,
    StatusException,
    StatusFailure,
    StatusSuccess,
)

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2

from PB.recipes.dart.dart.gclient import Gclient

PROPERTIES = Gclient

DEPS = [
    'bisect_build',
    'dart',
    'depot_tools/gitiles',
    'depot_tools/osx_sdk',
    'recipe_engine/buildbucket',
    'recipe_engine/context',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]


TEST_MATRIX = {
  "filesets": {
    "fileset1": "[]",
    "nameoffileset": "[]"
  },
  "global": {
    "chrome": "66.0.3359.139",
    "firefox": "60.0.1"
  },
  "builder_configurations": [
    {
      "builders": [
        "dart2js-win-debug-x64-firefox",
      ],
      "meta": {},
      "steps": [{
        "name": "Build",
        "script": "tools/build.py",
        "arguments": ["foo", "--bar"],
        "shards": 1
      }, {
        "name": "Test-step 1",
        "script": "tools/test.py",
        "arguments": ["foo", "--bar", "-e co19", "language_2"],
      }, {
        "name": "Test-step 2",
        "arguments": ["foo", "--bar", "-mdebug",
                      "-n${runtime}-foo-${mode}-${arch}-bar"],
      }]
    }
  ]
}


def _is_infra_failure(api, failure):
  return (isinstance(failure, api.step.InfraFailure) or
          api.dart.has_infra_failure(failure))


def _compute_failure_reason(api, failure):
  assert not failure or not _is_infra_failure(api, failure)
  return failure.reason if failure else api.bisect_build.REASON_SUCCESS


def _schedule_bisection(api, failure=None):
  if not api.bisect_build.is_enabled:
    # This builder is not configured to use bisection.
    return
  if _is_infra_failure(api, failure):
    # TODO(karlklose): fan out on infra failures during bisection and consider
    #                  starting a bisection for some kinds of infra failures.
    return
  elif api.bisect_build.is_bisecting() or failure:
    reason = _compute_failure_reason(api, failure)
    api.bisect_build.schedule("https://dart.googlesource.com/sdk", reason)


def RunSteps(api, properties):
  # Override analyzer cache location to make analyzer runs hermetic.
  env = {'ANALYZER_STATE_LOCATION_OVERRIDE':
      api.path['cleanup'].join('analysis-cache')}
  try:
    with api.osx_sdk('mac'), api.context(env=env):
      _run_steps_impl(api, properties)
  except api.step.StepFailure as failure:
    _schedule_bisection(api, failure)
    raise
  _schedule_bisection(api)


def _run_steps_impl(api, properties):
  clobber = api.properties.get('clobber', False)
  api.dart.checkout(
      clobber=clobber,
      custom_vars=json_format.MessageToDict(properties.custom_vars))
  api.dart.kill_tasks()

  try:
    api.dart.test(test_data=TEST_MATRIX)
  finally:
    api.dart.kill_tasks()


RESULT_DATA = (
    '{"name":"test_foo"'
    ',"configuration":"config_bar","suite":"suite_baz",'
    '"test_name":"Language/Classes/Abstract_Instance_Members/inherited_t01",'
    '"time_ms":451,"result":"CompileTimeError","expected":"CompileTimeError",'
    '"matches":true,"commit_time":1551185312,'
    '"commit_hash":"f0042a32250a8a6193e6d07e2b6508b13f43c864",'
    '"build_number":"2404","builder_name":"vm-kernel-linux-product-x64",'
    '"bot_name":"trusty-dart-68765ebb-us-central1-b-2ls0","flaky":false,'
    '"previous_flaky":false,"previous_result":"CompileTimeError",'
    '"previous_commit_hash":"f0042a32250a8a6193e6d07e2b6508b13f43c864",'
    '"previous_commit_time":1551185312,"previous_build_number":2403,'
    '"changed":false}\n')

TESTED_REVISION = '1a2b3c4d'


def GenTests(api):
  yield api.test(
      'builders/dart2js-win-debug-x64-firefox-try',
      api.buildbucket.try_build(
          builder='dart2js-win-debug-x64-firefox-try',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart'),
      api.properties(
          Gclient(
              custom_vars=json_format.ParseDict({
                  'download_firefox': True,
              }, struct_pb2.Struct()))),
      api.step_data('add fields to result records',
                    api.raw_io.output_text(RESULT_DATA)),
  )

  yield api.test(
      'successful-build-does-not-start-bisection',
      api.buildbucket.ci_build(
          builder='dart2js-win-debug-x64-firefox',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart',
          revision=TESTED_REVISION),
      api.properties(bisection_enabled=True),
      api.step_data('add fields to result records',
                    api.raw_io.output_text(RESULT_DATA)),
      api.post_process(DoesNotRunRE, 'schedule bisect (.*)'),
      api.post_process(StatusSuccess),
  )

  yield api.test(
      'infra-failure-does-not-start-bisection',
      api.buildbucket.ci_build(
          builder='dart2js-win-debug-x64-firefox',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart',
          revision=TESTED_REVISION),
      api.properties(bisection_enabled=True),
      api.step_data('add fields to result records',
                    api.raw_io.output_text(RESULT_DATA)),
      # Create an infra-failure in the test results step
      api.step_data('test results', retcode=2),
      api.post_process(DoesNotRunRE, 'schedule bisect (.*)'),
      api.post_process(StatusException),
  )

  yield api.test(
      'toplevel-infra-failure-does-not-start-bisection',
      api.buildbucket.ci_build(
          # Specifies a builder that is not in the test matrix:
          builder='undefined-builder-name',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart',
          revision=TESTED_REVISION),
      api.properties(bisection_enabled=True),
      api.post_process(DoesNotRunRE, 'schedule bisect (.*)'),
      api.post_process(StatusException),
  )

  yield api.test(
      'failing-test-step-starts-bisection',
      api.buildbucket.ci_build(
          builder='dart2js-win-debug-x64-firefox',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart',
          build_number=4711,
          revision=TESTED_REVISION),
      api.properties(bisection_enabled=True),
      api.step_data('add fields to result records',
                    api.raw_io.output_text(RESULT_DATA)),
      # Create a successful base build for the bisection
      # (see bisect_build/test_api.py)
      api.bisect_build.fetch_previous_builds(api, [
          api.bisect_build.build(api, 'foo', 4710,
                                 '2d72510e447ab60a9728aeea2362d8be2cbd7789')
      ]) +
      # Create a fake gitiles log for the bisection algorithm (see gitiles/test_api.py)
      api.step_data(
          'gitiles log: 2d72510e447ab60a9728aeea2362d8be2cbd7789..%s' %
          TESTED_REVISION, api.gitiles.make_log_test_data('master')),
      # Make test step fail by failing the 'test results' step
      api.step_data('test results', retcode=1),
      api.post_process(
          MustRun,
          'schedule bisect (f4d35da881f8fd329a4d3e01dd78b66a502d5c49)'),
      api.post_process(StatusFailure),
  )

  yield api.test(
      'different-failure-in-bisection-schedules-two-bisection-builds',
      api.buildbucket.ci_build(
          builder='dart2js-win-debug-x64-firefox',
          git_repo='https://dart.googlesource.com/sdk',
          project='dart',
          revision=TESTED_REVISION),
      api.properties(
          bisection_enabled=True,
          bisect_newer=['a', 'b', 'c'],
          bisect_older=['c', 'd', 'e'],
          bisect_base_build=4711,
          bisect_reason="Step('Build') (retcode: 1)",
      ),
      # Make build step fail by failing the 'test results' step
      api.step_data('test results', retcode=1),
      api.post_process(MustRun, 'schedule bisect (b)'),
      api.post_process(MustRun, 'schedule bisect (d)'),
      api.post_process(StatusFailure),
      api.post_process(DropExpectation),
  )
