# Copyright 2019 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 textwrap

from recipe_engine import post_process
from recipe_engine import recipe_api

DEPS = [
  'gclient',
  'presubmit',
  'recipe_engine/buildbucket',
  'recipe_engine/context',
  'recipe_engine/cq',
  'recipe_engine/json',
  'recipe_engine/path',
  'recipe_engine/properties',
  'recipe_engine/runtime',
]


def RunSteps(api):
  api.gclient.set_config('infra')
  with api.context(cwd=api.path['cache'].join('builder')):
    bot_update_step = api.presubmit.prepare()
    skip_owners = api.properties.get('skip_owners', False)
    return api.presubmit.execute(bot_update_step, skip_owners)


def GenTests(api):
  yield (
      api.test('success') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data(
          'presubmit',
          api.json.output({'errors': [], 'notifications': [], 'warnings': []}),
      ) +
      api.post_process(post_process.StatusSuccess) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('cq_dry_run') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.cq(dry_run=True) +
      api.post_process(post_process.StatusSuccess) +
      api.post_process(post_process.StepCommandContains, 'presubmit', ['--dry_run']) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('skip_owners') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.properties(skip_owners=True) +
      api.post_process(post_process.StatusSuccess) +
      api.post_process(
          post_process.StepCommandContains, 'presubmit', ['--skip_canned', 'CheckOwners']) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('timeout') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.presubmit(timeout_s=600) +
      api.step_data(
          'presubmit',
          api.json.output({'errors': [], 'notifications': [], 'warnings': []}),
          times_out_after=1200,
      ) +
      api.post_process(post_process.StatusFailure) +
      api.post_process(
          post_process.ResultReason,
         (u'#### There are 0 error(s), 0 warning(s), and 0 notifications(s).'
          ' Here are the errors:'
          '\n\nTimeout occurred during presubmit step.')) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('failure') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data('presubmit', api.json.output(
          {
            'errors': [
              {
                'message': 'Missing LGTM',
                'long_text': 'Here are some suggested OWNERS: fake@',
                'items': [],
                'fatal': True
              },
              {
                'message': 'Syntax error in fake.py',
                'long_text': 'Expected "," after item in list',
                'items': [],
                'fatal': True
              }
            ],
            'notifications': [
              {
                'message': 'If there is a bug associated please add it.',
                'long_text': '',
                'items': [],
                'fatal': False
              }
            ],
            'warnings': [
              {
                'message': 'Line 100 has more than 80 characters',
                'long_text': '',
                'items': [],
                'fatal': False
              }
            ]
          }, retcode=1)
      ) +
      api.post_process(post_process.StatusFailure) +
      api.post_process(post_process.ResultReason, textwrap.dedent(u'''
          #### There are 2 error(s), 1 warning(s), and 1 notifications(s). Here are the errors:

          **ERROR**
          ```
          Missing LGTM
          Here are some suggested OWNERS: fake@
          ```

          **ERROR**
          ```
          Syntax error in fake.py
          Expected "," after item in list
          ```

          #### To see notifications and warnings, look at the stdout of the presubmit step.
        ''').strip()
      ) +
      api.post_process(post_process.DropExpectation)
  )

  long_message = (u'Here are some suggested OWNERS:' +
    u'\nreallyLongFakeAccountNameEmail@chromium.org' * 10)
  yield (
      api.test('failure-long-message') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data('presubmit', api.json.output(
          {
            'errors': [
              {
                'message': 'Missing LGTM',
                'long_text': long_message,
                'items': [],
                'fatal': True
              }
            ],
            'notifications': [],
            'warnings': []
          }, retcode=1)
      ) +
      api.post_process(post_process.StatusFailure) +
      api.post_process(post_process.ResultReason, textwrap.dedent('''
          #### There are 1 error(s), 0 warning(s), and 0 notifications(s). Here are the errors:

          **ERROR**
          ```
          Missing LGTM
          Here are some suggested OWNERS:
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          reallyLongFakeAccountNameEmail@chromium.org
          ```

          **Error size > 450 chars, there are 2 more error(s) (15 total)**
          **The complete output can be found at the bottom of the presubmit stdout.**
        ''').strip()
      ) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('infra-failure') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data('presubmit', api.json.output(
          {
            'errors': [
              {
                'message': 'Infra Failure',
                'long_text': '',
                'items': [],
                'fatal': True
              }
            ],
            'notifications': [],
            'warnings': []
          }, retcode=2)
      ) +
      api.post_process(post_process.StatusException) +
      api.post_process(post_process.ResultReason, textwrap.dedent(u'''
        #### There are 1 error(s), 0 warning(s), and 0 notifications(s). Here are the errors:

        **ERROR**
        ```
        Infra Failure

        ```
        ''').strip()
      ) +
      api.post_process(post_process.DropExpectation)
  )

  bug_msg = (
    'Something unexpected occurred'
    ' while running presubmit checks.'
    ' Please [file a bug](https://bugs.chromium.org'
    '/p/chromium/issues/entry?components='
    'Infra%3EClient%3EChrome&status=Untriaged)'
  )
  yield (
      api.test('failure-no-json') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data('presubmit', api.json.output(None, retcode=1)) +
      api.post_process(post_process.StatusException) +
      api.post_process(post_process.ResultReason, bug_msg) +
      api.post_process(post_process.DropExpectation)
  )

  yield (
      api.test('infra-failure-no-json') +
      api.runtime(is_experimental=False, is_luci=True) +
      api.buildbucket.try_build(project='infra') +
      api.step_data('presubmit', api.json.output(None, retcode=2)) +
      api.post_process(post_process.StatusException) +
      api.post_process(post_process.ResultReason, bug_msg) +
      api.post_process(post_process.DropExpectation)
  )
