# Copyright 2023 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Full test of build module."""

from recipe_engine import post_process

DEPS = [
    'pigweed/builder_status',
    'recipe_engine/buildbucket',
    'recipe_engine/step',
]


def RunSteps(api):
    builder = api.builder_status.retrieve(n=10)

    if api.builder_status.is_incomplete(builder):
        api.step('is incomplete', [])

    if api.builder_status.is_passing(builder):
        api.step('is passing', [])

    if api.builder_status.has_recently_passed(builder):
        api.step('has recently passed', [])


def GenTests(api):  # pylint: disable=invalid-name
    def assert_running():
        return api.post_process(post_process.MustRun, f'is incomplete')

    def assert_not_running():
        return api.post_process(post_process.DoesNotRun, f'is incomplete')

    def assert_passing():
        return api.post_process(post_process.MustRun, f'is passing')

    def assert_not_passing():
        return api.post_process(post_process.DoesNotRun, f'is passing')

    def assert_recently_passed():
        return api.post_process(post_process.MustRun, f'has recently passed')

    def assert_not_recently_passed():
        return api.post_process(post_process.DoesNotRun, f'has recently passed')

    def drop_expectations_must_be_last():
        # No need for expectation files, everything of note here is tested by
        # assertions. This must be the last thing added to the test.
        return api.post_process(post_process.DropExpectation)

    yield (
        api.test('none')
        + api.buildbucket.simulated_search_results([])
        + assert_not_running()
        + assert_not_passing()
        + assert_not_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_pass')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.passed()]
        )
        + assert_not_running()
        + assert_passing()
        + assert_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_scheduled_one_running_one_pass')
        + api.buildbucket.simulated_search_results(
            [
                api.builder_status.scheduled(),
                api.builder_status.running(),
                api.builder_status.passed(),
            ]
        )
        + assert_running()
        + assert_passing()
        + assert_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_fail')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.failure()]
        )
        + assert_not_running()
        + assert_not_passing()
        + assert_not_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_scheduled_one_running_one_fail')
        + api.buildbucket.simulated_search_results(
            [
                api.builder_status.scheduled(),
                api.builder_status.running(),
                api.builder_status.failure(),
            ]
        )
        + assert_running()
        + assert_not_passing()
        + assert_not_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_pass_one_fail')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.passed(), api.builder_status.failure()]
        )
        + assert_not_running()
        + assert_passing()
        + assert_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_fail_one_pass')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.failure(), api.builder_status.passed()]
        )
        + assert_not_running()
        + assert_not_passing()
        + assert_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('many_passes')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.passed()] * 10
        )
        + assert_not_running()
        + assert_passing()
        + assert_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('many_failures')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.failure()] * 10
        )
        + assert_not_running()
        + assert_not_passing()
        + assert_not_recently_passed()
        + drop_expectations_must_be_last()
    )

    yield (
        api.test('one_infra')
        + api.buildbucket.simulated_search_results(
            [api.builder_status.infra_failure()]
        )
        + assert_not_running()
        + assert_not_passing()
        + assert_not_recently_passed()
        + drop_expectations_must_be_last()
    )
