# Copyright (c) 2020, the Dart project 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 recipe_engine.post_process import (
    DropExpectation,
    DoesNotRun,
    DoesNotRunRE,
    Filter,
    MustRun,
    StatusSuccess,
)

from recipe_engine.recipe_api import Property

DEPS = [
    'depot_tools/gitiles',
    'bisect_build',
    'recipe_engine/buildbucket',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = {
    'current_failure':
        Property(
            kind=str,
            help='Reason for current failure or "SUCCESS"',
            default='SUCCESS'),
    'is_experimental':
        Property(
            kind=bool,
            help='Controls whether the bisection build should be scheduled as'
            ' experimental',
            default=False),
}


def RunSteps(api, current_failure, is_experimental):
  api.bisect_build.schedule('https://dummy/repo/url', current_failure,
                            is_experimental)


def _test(api, name, failure=None, is_experimental=False, build_number=3):
  data = api.test(
      name,
      api.buildbucket.ci_build(
          builder='builder',
          build_number=build_number,
          git_repo='https://dart.googlesource.com/sdk',
          revision='f' * 8))
  if failure:
    data += api.properties(
        current_failure=failure, is_experimental=is_experimental)
  return data


# TODO(karlklose): remove is_experimental support once we know that we do not
# want to use it again.
def _sets_experimental_flag(check, step_odict, step):
  # Verify that the step contains the option for an experimental build
  input = str(step_odict[step].stdin)
  check('"experimental": "YES"' in input)


def GenTests(api):

  yield _test(api, 'basic')

  BUILDER = 'foo'
  GIT_HASH = '2d72510e447ab60a9728aeea2362d8be2cbd7789'

  STARTS_BISECTION = api.post_process(
      MustRun, 'schedule bisect (f4d35da881f8fd329a4d3e01dd78b66a502d5c49)')
  DOES_NOT_BISECT = api.post_process(DoesNotRunRE, r'schedule bisect.*')

  builds = [api.bisect_build.build(api, BUILDER, 2, GIT_HASH)]
  yield (_test(api, 'starts bisection', failure='failure') + api.step_data(
      'gitiles log: 2d72510e447ab60a9728aeea2362d8be2cbd7789..ffffffff',
      api.gitiles.make_log_test_data('master')) +
         api.bisect_build.fetch_previous_builds(api, builds) + STARTS_BISECTION)

  yield (_test(
      api,
      'start-experimental-bisection',
      failure='failure',
      is_experimental=True) + api.step_data(
          'gitiles log: 2d72510e447ab60a9728aeea2362d8be2cbd7789..ffffffff',
          api.gitiles.make_log_test_data('master')) +
         api.bisect_build.fetch_previous_builds(api, builds) + api.post_process(
             MustRun,
             'schedule bisect (f4d35da881f8fd329a4d3e01dd78b66a502d5c49)') +
         api.post_process(StatusSuccess) + api.post_process(
             _sets_experimental_flag,
             'schedule bisect (f4d35da881f8fd329a4d3e01dd78b66a502d5c49)'))

  builds = [api.bisect_build.build(api, BUILDER, 2, GIT_HASH, is_success=False)]
  yield (_test(
      api, 'do-not-start-bisect-if-previous-build-failed', failure='failure') +
         api.bisect_build.fetch_previous_builds(api, builds) + DOES_NOT_BISECT)

  builds = [
      api.bisect_build.build(api, BUILDER, 2, GIT_HASH, is_bisection=True),
      api.bisect_build.build(api, BUILDER, 1, GIT_HASH, is_bisection=True),
      api.bisect_build.build(api, BUILDER, 0, GIT_HASH, is_bisection=True),
  ]
  yield (_test(
      api,
      'do-not-start-bisect-if-all-previous-builds-are-non-regular',
      failure='failure') + api.bisect_build.fetch_previous_builds(api, builds) +
         DOES_NOT_BISECT)

  yield (_test(
      api, 'do-not-start-bisect-without-previous-build', failure='failure') +
         DOES_NOT_BISECT)

  yield api.test(
      'do-not-start-bisect-without-current-revision',
      api.buildbucket.ci_build(
          builder='builder',
          git_repo='https://dart.googlesource.com/sdk',
          revision=None), api.properties(current_failure='failure'),
      DOES_NOT_BISECT)

  yield (_test(api, 'continue-bisect-on-failure', failure='failure') +
         api.properties(
             bisect_newer=['a', 'b', 'c'],
             bisect_older=['c', 'd', 'e'],
             bisect_base_build=4711,
             bisect_reason='failure') +
         api.post_process(MustRun, 'schedule bisect (d)') +
         api.post_process(Filter('schedule bisect (d)')))

  yield (
      _test(api, 'continue-bisect-on-failure-experimental', failure='failure') +
      api.properties(
          bisect_newer=['a', 'b', 'c'],
          bisect_older=['c', 'd', 'e'],
          bisect_base_build=4711,
          bisect_reason='failure',
          is_experimental=True) +
      api.post_process(MustRun, 'schedule bisect (d)') +
      api.post_process(_sets_experimental_flag, 'schedule bisect (d)') +
      api.post_process(Filter('schedule bisect (d)')))

  yield (_test(api, 'continue-bisect-on-success') + api.properties(
      bisect_newer=['a', 'b', 'c'],
      bisect_older=['c', 'd', 'e'],
      bisect_base_build=4711,
      bisect_reason='failure') +
         api.post_process(MustRun, 'schedule bisect (b)') +
         api.post_process(DoesNotRun, 'schedule bisect (d)') +
         api.post_process(Filter().include_re(r'schedule bisect \(.*\)')))

  yield (_test(api, 'fan-out-on-distinct-failure',
               failure='different failure') + api.properties(
                   bisect_newer=['a', 'b', 'c'],
                   bisect_older=['c', 'd', 'e'],
                   bisect_base_build=4711,
                   bisect_reason='failure') +
         api.post_process(MustRun, 'schedule bisect (b)') +
         api.post_process(MustRun, 'schedule bisect (d)') +
         api.post_process(Filter().include_re(r'schedule bisect \(.*\)')))

  yield (_test(api, 'stop-bisect') + api.properties(
      bisect_newer=[],
      bisect_older=[],
      bisect_base_build=4711,
      bisect_reason='failure') + DOES_NOT_BISECT +
         api.post_process(DropExpectation))
