# Copyright 2021 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 pw_presubmit module."""

from __future__ import annotations

import collections
import datetime
from collections.abc import Iterator

from recipe_engine import recipe_api, recipe_test_api

from PB.recipe_modules.pigweed.gerrit_comment.options import CommentBehavior
from PB.recipe_modules.pigweed.pw_presubmit.tests.full import InputProperties

DEPS = [
    'pigweed/checkout',
    'pigweed/pw_presubmit',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/time',
]

INLINE_PROPERTIES_PROTO = """
import "recipe_modules/pigweed/checkout/options.proto";
import "recipe_modules/pigweed/pw_presubmit/options.proto";

message InputProperties {
  recipe_modules.pigweed.checkout.Options checkout_options = 1;

  recipe_modules.pigweed.pw_presubmit.Options pw_presubmit_options = 2;
}
"""

PROPERTIES = InputProperties

Environment = collections.namedtuple('Environment', 'override_gn_args')


def RunSteps(api: recipe_api.RecipeScriptApi, props: InputProperties):
    checkout = api.checkout.fake_context()

    with api.pw_presubmit(checkout, props.pw_presubmit_options) as presubmit:
        log_dir = api.path.start_dir / 'logs'

        for i, step in enumerate(presubmit.steps):
            # Need to take path with and without log_dir argument for coverage.
            kw = {}
            if i:
                kw['log_dir'] = log_dir / step.name

            if i:
                kw['env'] = Environment(dict(foo=1))
            else:
                kw['env'] = Environment(dict(foo='bar'))

            api.pw_presubmit.run(presubmit, step, **kw)

        # For coverage.
        _ = api.pw_presubmit.build_id(presubmit)


def GenTests(api) -> Iterator[recipe_test_api.TestData]:
    """Create tests."""

    def properties(*, checkout_options=None, **kwargs):
        props = InputProperties(
            pw_presubmit_options=api.pw_presubmit.options(**kwargs),
            checkout_options=checkout_options or api.checkout.git_options(),
        )
        return api.properties(props)

    yield api.test(
        'no-steps',
        properties(),
        api.checkout.ci_test_data(),
        status='FAILURE',
    )

    yield api.test(
        'bad-json-steps',
        properties(program=['program']),
        api.step_data(
            'get steps from programs.get steps',
            stdout=api.json.output(None),
        ),
        api.checkout.ci_test_data(),
    )

    yield api.test(
        'empty-program',
        properties(program=['empty']),
        api.step_data(
            'get steps from programs.get steps',
            stdout=api.json.output([]),
        ),
    )

    yield api.test(
        'substep',
        properties(step=['composite']),
        api.step_data(
            'get steps from programs.get steps',
            stdout=api.json.output(
                [
                    {
                        'name': 'composite',
                        'substeps': ['substep1', 'substep2', 'substep3'],
                    },
                ],
            ),
        ),
        api.step_data('composite.substep2', retcode=1),
        status='FAILURE',
    )

    yield api.test(
        'pigweed',
        properties(
            command_name='foo',
            program=['full'],
            only_on_changed_files=True,
            continue_after_build_error=True,
        ),
        api.checkout.ci_test_data(),
        api.step_data(
            'get build id',
            stdout=api.raw_io.output_text('0\n'),
        ),
    )

    yield api.test(
        'step',
        properties(
            step=['step1', 'step2'],
            use_time_for_rng_seed=True,
            override_gn_arg=('foo=1', 'bar=2'),
        ),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=120,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'long',
        properties(step=['step1', 'step2'], gcs_bucket='bucket'),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=3 * 60 * 60,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'medium',
        properties(step=['step1', 'step2']),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=30 * 60,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'comment-on-failure',
        properties(
            step=['step1', 'step2'],
            comment_behavior=CommentBehavior.COMMENT_ON_FAILURE,
        ),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=120,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'comment-always',
        properties(
            step=['step1', 'step2'],
            comment_behavior=CommentBehavior.COMMENT_ALWAYS,
        ),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=120,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'comment-always-no-cl',
        properties(
            step=['step1', 'step2'],
            comment_behavior=CommentBehavior.COMMENT_ALWAYS,
        ),
        api.checkout.ci_test_data(),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    yield api.test(
        'comment-always-disallowed-host',
        properties(
            step=['step1', 'step2'],
            comment_behavior=CommentBehavior.COMMENT_ALWAYS,
            comment_allowed_gerrit_hosts=['secret-host.googlesource.come'],
        ),
        api.checkout.try_test_data(
            start_time=datetime.datetime.utcfromtimestamp(1600000000),
            execution_timeout=120,
        ),
        api.time.seed(1600000000),
        api.time.step(20.0),
    )

    builder_manifest = (
        api.path.start_dir / 'checkout/p/step1/builder_manifest.json'
    )

    yield api.test(
        'cipd',
        properties(step=['step1']),
        api.checkout.ci_test_data(),
        api.path.files_exist(builder_manifest),
    )
