# Copyright 2020 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 non-repo non-submodule functionality of checkout module."""

from typing import Generator

from PB.go.chromium.org.luci.scheduler.api.scheduler.v1 import (
    triggers as triggers_pb2,
)
from PB.recipe_modules.pigweed.checkout.tests.properties import InputProperties
from recipe_engine import recipe_test_api

DEPS = [
    'pigweed/checkout',
    'recipe_engine/json',
    'recipe_engine/properties',
    'recipe_engine/scheduler',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


def RunSteps(api, props):  # pylint: disable=invalid-name
    checkout = api.checkout(props.checkout_options)

    def steplog(name, value):  # pylint: disable=invalid-name
        with api.step.nest(name) as pres:
            pres.step_summary_text = repr(value)

    # These lines are needed for coverage.
    steplog('revision', checkout.revision())
    steplog('revision', checkout.revision())  # Intentional repeat (caching).
    steplog('gerrit_host', checkout.gerrit_host())
    steplog('gerrit_project', checkout.gerrit_project())
    steplog('submodules', checkout.submodules())
    steplog('applied_changes', checkout.applied_changes())


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    def properties(**kwargs):
        kwargs.setdefault('remote', api.checkout.pigweed_repo)
        kwargs.setdefault('branch', None)
        props = InputProperties(
            checkout_options=api.checkout.git_options(**kwargs)
        )
        return api.properties(props)

    yield api.test('ci') + properties() + api.checkout.ci_test_data()

    yield (
        api.test('trigger')
        + properties()
        + api.checkout.ci_test_data()
        + api.scheduler(
            triggers=[
                triggers_pb2.Trigger(
                    gitiles=triggers_pb2.GitilesTrigger(
                        repo='https://pigweed.googlesource.com/pigweed/pigweed',
                        revision='2d72510e447ab60a9728aeea2362d8be2cbd7789',
                        ref='refs/heads/overridden-by-trigger',
                    ),
                ),
            ],
        )
    )

    yield (
        api.test('try')
        + properties(root_subdirectory='foo')
        + api.checkout.try_test_data()
        + api.checkout.cl_branch_parents(num_parents=2)
    )

    yield api.test('other') + properties()

    yield (
        api.test('not_in_gerrit')
        + properties()
        + api.step_data(
            'checkout pigweed.change data.number',
            api.json.output({}),
        )
    )

    yield (
        api.test('fail-config', status='INFRA_FAILURE')
        + properties()
        + api.step_data('checkout pigweed.cache.git fetch', retcode=1)
    )
