# 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.
"""Test API for enviroment."""

import re

from PB.recipe_modules.pigweed.environment import options as env_options
from recipe_engine import recipe_test_api


class EnvironmentTestApi(recipe_test_api.RecipeTestApi):
    """Test API for Enviroment."""

    def properties(
        self,
        *,
        name='environment_options',
        config_file='config_file.json',
        root_variable_name='FOO_ROOT',
        relative_pigweed_root='pigweed',
        skip_submodule_check=False,
        additional_variables=None,
    ):
        opts = env_options.Options()
        opts.config_file = config_file
        opts.root_variable_name = root_variable_name
        opts.relative_pigweed_root = relative_pigweed_root
        opts.skip_submodule_check = skip_submodule_check
        for key, value in (additional_variables or {}).items():
            opts.additional_variables[key] = str(value)

        return self.m.properties(**{name: opts})

    def override_clang(self, source, version):
        props = {
            '$fuchsia/build': {
                'clang_toolchain': {'source': source, 'version': version,},
            },
        }

        return self.m.properties(**props)
