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

from __future__ import annotations

import dataclasses
from typing import Generator, Optional, TYPE_CHECKING

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

if TYPE_CHECKING:  # pragma: no cover
    from recipe_engine import config_types, recipe_test_api

DEPS = [
    'pigweed/environment',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
]

PROPERTIES = InputProperties


@dataclasses.dataclass
class _FakeCheckoutContext:
    root: config_types.Path
    changes_json: Optional[config_types.Path] = None


def RunSteps(api, props):  # pylint: disable=invalid-name
    # pylint: disable=missing-function-docstring

    # If the environment options are the default, pass in None instead. The
    # module will default-construct an identical proto. This is for coverage.
    env_opts = props.environment_options
    if env_opts == InputProperties().environment_options:
        env_opts = None

    env = api.environment.init(
        checkout=_FakeCheckoutContext(api.path.start_dir),
        use_constraint_file=False,
        options=env_opts,
    )

    # The next couple lines help cover all of api.py.
    try:
        # VIRTUAL_ENV is set in almost all cases, but not in the 'empty' test.
        _ = env.VIRTUAL_ENV
        _ = env.VARIABLE_NAME_UNLIKELY_TO_BE_USED_ELSEWHERE
    except AttributeError:
        pass

    with env():
        pass


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    yield api.test('no-props')

    yield (
        api.test('normal')
        + api.environment.properties(skip_submodule_check=True)
        + api.properties(**{'$recipe_engine/led': {'led_run_id': '123'}})
        + api.platform.name('mac')
    )

    yield (
        api.test('doctor-fail')
        + api.environment.properties(
            skip_submodule_check=True,
            additional_cipd_files=('override.json',),
        )
        + api.platform.name('linux')
        + api.step_data('environment.doctor', retcode=1)
    )

    yield (
        api.test('windows')
        + api.environment.properties(additional_variables=dict(ABC=123))
        + api.platform.name('win')
    )

    yield (
        api.test('override-cipd')
        + api.environment.properties(skip_submodule_check=True)
        + api.environment.override_clang(cipd_version='latest')
    )

    yield (
        api.test('override-cas')
        + api.environment.properties(skip_submodule_check=True)
        + api.environment.override_clang(cas_digest='123456')
    )

    yield api.test('empty')
