# 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.
"""Tests for pw_cli.envparse."""

import math
import unittest

from pw_cli import envparse

# pylint: disable=no-member


class ErrorError(Exception):
    pass


def error(value: str):
    raise ErrorError('error!')


class TestEnvironmentParser(unittest.TestCase):
    """Tests for envparse.EnvironmentParser."""
    def setUp(self):
        self.raw_env = {
            'PATH': '/bin:/usr/bin:/usr/local/bin',
            'FOO': '2020',
            'ReVeRsE': 'pigweed',
        }

        self.parser = envparse.EnvironmentParser()
        self.parser.add_var('PATH')
        self.parser.add_var('FOO', type=int)
        self.parser.add_var('BAR', type=bool)
        self.parser.add_var('BAZ', type=float, default=math.pi)
        self.parser.add_var('ReVeRsE', type=lambda s: s[::-1])
        self.parser.add_var('INT', type=int)
        self.parser.add_var('ERROR', type=error)

    def test_string_value(self):
        env = self.parser.parse_env(env=self.raw_env)
        self.assertEqual(env.PATH, self.raw_env['PATH'])

    def test_int_value(self):
        env = self.parser.parse_env(env=self.raw_env)
        self.assertEqual(env.FOO, 2020)

    def test_custom_value(self):
        env = self.parser.parse_env(env=self.raw_env)
        self.assertEqual(env.ReVeRsE, 'deewgip')

    def test_empty_value(self):
        env = self.parser.parse_env(env=self.raw_env)
        self.assertEqual(env.BAR, None)

    def test_default_value(self):
        env = self.parser.parse_env(env=self.raw_env)
        self.assertEqual(env.BAZ, math.pi)

    def test_unknown_key(self):
        env = self.parser.parse_env(env=self.raw_env)
        with self.assertRaises(AttributeError):
            env.BBBBB  # pylint: disable=pointless-statement

    def test_bad_value(self):
        raw_env = {**self.raw_env, 'INT': 'not an int'}
        with self.assertRaises(envparse.EnvironmentValueError) as ctx:
            self.parser.parse_env(env=raw_env)

        self.assertEqual(ctx.exception.variable, 'INT')
        self.assertIsInstance(ctx.exception.__cause__, ValueError)

    def test_custom_exception(self):
        raw_env = {**self.raw_env, 'ERROR': 'error'}
        with self.assertRaises(envparse.EnvironmentValueError) as ctx:
            self.parser.parse_env(env=raw_env)

        self.assertEqual(ctx.exception.variable, 'ERROR')
        self.assertIsInstance(ctx.exception.__cause__, ErrorError)


class TestEnvironmentParserWithPrefix(unittest.TestCase):
    """Tests for envparse.EnvironmentParser using a prefix."""
    def setUp(self):
        self.raw_env = {
            'PW_FOO': '001',
            'PW_BAR': '010',
            'PW_BAZ': '100',
            'IGNORED': '011',
        }

    def test_parse_unrecognized_variable(self):
        parser = envparse.EnvironmentParser(prefix='PW_')
        parser.add_var('PW_FOO')
        parser.add_var('PW_BAR')

        with self.assertRaises(ValueError):
            parser.parse_env(env=self.raw_env)

    def test_parse_unrecognized_but_allowed_suffix(self):
        parser = envparse.EnvironmentParser(prefix='PW_')
        parser.add_allowed_suffix('_ALLOWED_SUFFIX')

        env = parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX': '001'})
        self.assertEqual(env.PW_FOO_ALLOWED_SUFFIX, '001')

    def test_parse_allowed_suffix_but_not_suffix(self):
        parser = envparse.EnvironmentParser(prefix='PW_')
        parser.add_allowed_suffix('_ALLOWED_SUFFIX')

        with self.assertRaises(ValueError):
            parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX_FOO': '001'})

    def test_parse_ignore_unrecognized(self):
        parser = envparse.EnvironmentParser(prefix='PW_',
                                            error_on_unrecognized=False)
        parser.add_var('PW_FOO')
        parser.add_var('PW_BAR')

        env = parser.parse_env(env=self.raw_env)
        self.assertEqual(env.PW_FOO, self.raw_env['PW_FOO'])
        self.assertEqual(env.PW_BAR, self.raw_env['PW_BAR'])

    def test_add_var_without_prefix(self):
        parser = envparse.EnvironmentParser(prefix='PW_')
        with self.assertRaises(ValueError):
            parser.add_var('FOO')


class TestStrictBool(unittest.TestCase):
    """Tests for envparse.strict_bool."""
    def setUp(self):
        self.good_bools = ['true', '1', 'TRUE', 'tRuE']
        self.bad_bools = [
            '', 'false', '0', 'foo', '2', '999', 'ok', 'yes', 'no'
        ]

    def test_good_bools(self):
        self.assertTrue(
            all(envparse.strict_bool(val) for val in self.good_bools))

    def test_bad_bools(self):
        self.assertFalse(
            any(envparse.strict_bool(val) for val in self.bad_bools))


if __name__ == '__main__':
    unittest.main()
