# 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 __future__ import annotations

from collections.abc import Iterator

from recipe_engine import recipe_api, recipe_test_api

from PB.recipe_modules.pigweed.cq_deps.tests.full import InputProperties

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

INLINE_PROPERTIES_PROTO = """
message InputProperties {
  string revision = 1;
  string topic = 2;
}
"""

PROPERTIES = InputProperties


def RunSteps(api: recipe_api.RecipeScriptApi, props: InputProperties):
    result = api.cq_deps.resolve('pigweed', props.revision or 1, props.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) -> Iterator[recipe_test_api.TestData]:
    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',
        api.cq_deps.details('pigweed:1', patches_json=True),
        api.cq_deps.patches_json_error('pigweed:1'),
        api.cq_deps.lacks_deps('pigweed:1'),
        status='INFRA_FAILURE',
    )

    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'),
    )
