# 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 the cq_deps module."""

from typing import Generator

from recipe_engine import config, recipe_api, recipe_test_api

DEPS = [
    'pigweed/cq_deps',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = {
    'revision': recipe_api.Property(kind=str, default=None),
    'topic': recipe_api.Property(kind=str, default=None),
}


def RunSteps(api, revision, topic):
    result = api.cq_deps.resolve('pigweed', revision or 1, topic)

    with api.step.nest('final deps'):
        for dep in result.resolved:
            with api.step.nest(dep.name) as pres:
                pres.step_summary_text = dep.remote
                _ = dep.gerrit_url  # For coverage.

    if result.unresolved:
        with api.step.nest('errors'):
            for error in result.unresolved:
                with api.step.nest(error.name):
                    pass


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    yield (
        api.test('default')
        + api.properties(revision='b' * 40)
        + api.cq_deps.lookup_cl('b' * 40, 1)
        + api.cq_deps.details('pigweed:1')
    )

    yield (
        api.test('hash')
        + api.properties(revision='b' * 40)
        + api.cq_deps.lookup_cl('b' * 40, 1)
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1')
    )

    yield (
        api.test('cl-not-found')
        + api.properties(revision='b' * 40)
        + api.cq_deps.lookup_cl('b' * 40, found=False)
    )

    yield (
        api.test('no-patches-json', status='INFRA_FAILURE')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json_error('pigweed:1')
        + api.cq_deps.lacks_deps('pigweed:1')
    )

    yield (
        api.test('one')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.has_deps('pigweed:2')
        + api.cq_deps.lacks_deps('pigweed:1')
    )

    yield (
        api.test('two')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2', 'pigweed:3')
        + api.cq_deps.has_deps('pigweed:2', 'pigweed:3')
    )

    yield (
        api.test('no_space')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2', 'pigweed:3')
        + api.cq_deps.has_deps('pigweed:2', 'pigweed:3')
    )

    yield (
        api.test('loop_two')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.details('pigweed:2', patches_json=True)
        + api.cq_deps.patches_json('pigweed:2', 'pigweed:1')
        + api.cq_deps.has_deps('pigweed:2')
    )

    yield (
        api.test('loop_three')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.details('pigweed:2', patches_json=True)
        + api.cq_deps.details('pigweed:3', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.patches_json('pigweed:2', 'pigweed:3')
        + api.cq_deps.patches_json('pigweed:3', 'pigweed:1')
        + api.cq_deps.has_deps('pigweed:2', 'pigweed:3')
    )

    yield (
        api.test('abandoned')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.details(
            'pigweed:2', patches_json=True, status='ABANDONED'
        )
        + api.cq_deps.lacks_deps('pigweed:2')
    )

    yield (
        api.test('merged_skipped')
        + api.properties()
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.details('pigweed:2', status='MERGED')
        + api.cq_deps.lacks_deps('pigweed:2', 'pigweed:3')
    )

    yield (
        api.test('error')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.transient('pigweed:2')
        + api.cq_deps.transient('pigweed:2', n=2)
        + api.cq_deps.lacks_deps('forbidden:1')
    )

    yield (
        api.test('error_recovery')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'pigweed:2')
        + api.cq_deps.transient('pigweed:2')
        + api.cq_deps.details('pigweed:2', '', n=2)
        + api.cq_deps.has_deps('pigweed:2')
    )

    yield (
        api.test('forbidden')
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.patches_json('pigweed:1', 'forbidden:2')
        + api.cq_deps.forbidden('forbidden:2')
        + api.cq_deps.lacks_deps('forbidden:2')
    )

    yield (
        api.test('patches_json_disabled')
        + api.properties(**api.cq_deps.properties(patches_json_disabled=True))
        + api.cq_deps.details('pigweed:1', patches_json=True)
        + api.cq_deps.lacks_deps('pigweed:1', 'pigweed:2')
    )

    yield (
        api.test('topics')
        + api.properties(
            topic='topic',
            **api.cq_deps.properties(
                patches_json_disabled=True,
                topics_enabled=True,
            ),
        )
        + api.cq_deps.lacks_deps('pigweed:1')
        + api.cq_deps.has_deps('pigweed:2')
    )

    yield (
        api.test('topics-disabled')
        + api.properties(topic='topic')
        + api.cq_deps.lacks_deps('pigweed:1', 'pigweed:2')
    )
