# 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 env_setup.environment.

This tests the error-checking, context manager, and written environment scripts
of the Environment class.

Tests that end in "_ctx" modify the environment and validate it in-process.

Tests that end in "_written" write the environment to a file intended to be
evaluated by the shell, then launches the shell and then saves the environment.
This environment is then validated in the test process.
"""

import logging
import os
import subprocess
import tempfile
import unittest

import six

from pw_env_setup import environment

# pylint: disable=super-with-arguments


class WrittenEnvFailure(Exception):
    pass


def _evaluate_env_in_shell(env):
    """Write env to a file then evaluate and save the resulting environment.

    Write env to a file, then launch a shell command that sources that file
    and dumps the environment to stdout. Parse that output into a dict and
    return it.

    Args:
      env(environment.Environment): environment to write out

    Returns dictionary of resulting environment.
    """

    # Write env sourcing script to file.
    with tempfile.NamedTemporaryFile(
            prefix='pw-test-written-env-',
            suffix='.bat' if os.name == 'nt' else '.sh',
            delete=False,
            mode='w+') as temp:
        env.write(temp)
        temp_name = temp.name

    # Evaluate env sourcing script and capture output of 'env'.
    if os.name == 'nt':
        # On Windows you just run batch files and they modify your
        # environment, no need to call 'source' or '.'.
        cmd = '{} && set'.format(temp_name)
    else:
        # Using '.' instead of 'source' because 'source' is not POSIX.
        cmd = '. {} && env'.format(temp_name)

    res = subprocess.run(cmd, capture_output=True, shell=True)
    if res.returncode:
        raise WrittenEnvFailure(res.stderr)

    # Parse environment from stdout of subprocess.
    env_ret = {}
    for line in res.stdout.splitlines():
        line = line.decode()

        # Some people inexplicably have newlines in some of their
        # environment variables. This module does not allow that so we can
        # ignore any such extra lines.
        if '=' not in line:
            continue

        var, value = line.split('=', 1)
        env_ret[var] = value

    return env_ret


# pylint: disable=too-many-public-methods
class EnvironmentTest(unittest.TestCase):
    """Tests for env_setup.environment."""
    def setUp(self):
        self.env = environment.Environment()

        # Name of a variable that is already set when the test starts.
        self.var_already_set = self.env.normalize_key('var_already_set')
        os.environ[self.var_already_set] = 'orig value'
        self.assertIn(self.var_already_set, os.environ)

        # Name of a variable that is not set when the test starts.
        self.var_not_set = self.env.normalize_key('var_not_set')
        if self.var_not_set in os.environ:
            del os.environ[self.var_not_set]
        self.assertNotIn(self.var_not_set, os.environ)

        self.orig_env = os.environ.copy()

    def tearDown(self):
        self.assertEqual(os.environ, self.orig_env)

    def test_set_notpresent_ctx(self):
        self.env.set(self.var_not_set, '1')
        with self.env(export=False) as env:
            self.assertIn(self.var_not_set, env)
            self.assertEqual(env[self.var_not_set], '1')

    def test_set_notpresent_written(self):
        self.env.set(self.var_not_set, '1')
        env = _evaluate_env_in_shell(self.env)
        self.assertIn(self.var_not_set, env)
        self.assertEqual(env[self.var_not_set], '1')

    def test_set_present_ctx(self):
        self.env.set(self.var_already_set, '1')
        with self.env(export=False) as env:
            self.assertIn(self.var_already_set, env)
            self.assertEqual(env[self.var_already_set], '1')

    def test_set_present_written(self):
        self.env.set(self.var_already_set, '1')
        env = _evaluate_env_in_shell(self.env)
        self.assertIn(self.var_already_set, env)
        self.assertEqual(env[self.var_already_set], '1')

    def test_clear_notpresent_ctx(self):
        self.env.clear(self.var_not_set)
        with self.env(export=False) as env:
            self.assertNotIn(self.var_not_set, env)

    def test_clear_notpresent_written(self):
        self.env.clear(self.var_not_set)
        env = _evaluate_env_in_shell(self.env)
        self.assertNotIn(self.var_not_set, env)

    def test_clear_present_ctx(self):
        self.env.clear(self.var_already_set)
        with self.env(export=False) as env:
            self.assertNotIn(self.var_already_set, env)

    def test_clear_present_written(self):
        self.env.clear(self.var_already_set)
        env = _evaluate_env_in_shell(self.env)
        self.assertNotIn(self.var_already_set, env)

    def test_value_replacement(self):
        self.env.set(self.var_not_set, '/foo/bar/baz')
        self.env.add_replacement('FOOBAR', '/foo/bar')
        buf = six.StringIO()
        self.env.write(buf)
        assert '/foo/bar' not in buf.getvalue()

    def test_variable_replacement(self):
        self.env.set('FOOBAR', '/foo/bar')
        self.env.set(self.var_not_set, '/foo/bar/baz')
        self.env.add_replacement('FOOBAR')
        buf = six.StringIO()
        self.env.write(buf)
        print(buf.getvalue())
        assert '/foo/bar/baz' not in buf.getvalue()

    def test_nonglobal(self):
        self.env.set(self.var_not_set, '1')
        with self.env(export=False) as env:
            self.assertIn(self.var_not_set, env)
            self.assertNotIn(self.var_not_set, os.environ)

    def test_global(self):
        self.env.set(self.var_not_set, '1')
        with self.env(export=True) as env:
            self.assertIn(self.var_not_set, env)
            self.assertIn(self.var_not_set, os.environ)

    def test_set_badnametype(self):
        with self.assertRaises(environment.BadNameType):
            self.env.set(123, '123')

    def test_set_badvaluetype(self):
        with self.assertRaises(environment.BadValueType):
            self.env.set('var', 123)

    def test_prepend_badnametype(self):
        with self.assertRaises(environment.BadNameType):
            self.env.prepend(123, '123')

    def test_prepend_badvaluetype(self):
        with self.assertRaises(environment.BadValueType):
            self.env.prepend('var', 123)

    def test_append_badnametype(self):
        with self.assertRaises(environment.BadNameType):
            self.env.append(123, '123')

    def test_append_badvaluetype(self):
        with self.assertRaises(environment.BadValueType):
            self.env.append('var', 123)

    def test_set_badname_empty(self):
        with self.assertRaises(environment.BadVariableName):
            self.env.set('', '123')

    def test_set_badname_digitstart(self):
        with self.assertRaises(environment.BadVariableName):
            self.env.set('123', '123')

    def test_set_badname_equals(self):
        with self.assertRaises(environment.BadVariableName):
            self.env.set('foo=bar', '123')

    def test_set_badname_period(self):
        with self.assertRaises(environment.BadVariableName):
            self.env.set('abc.def', '123')

    def test_set_badname_hyphen(self):
        with self.assertRaises(environment.BadVariableName):
            self.env.set('abc-def', '123')

    def test_set_empty_value(self):
        with self.assertRaises(environment.EmptyValue):
            self.env.set('var', '')

    def test_set_newline_in_value(self):
        with self.assertRaises(environment.NewlineInValue):
            self.env.set('var', '123\n456')

    def test_equal_sign_in_value(self):
        with self.assertRaises(environment.BadVariableValue):
            self.env.append(self.var_already_set, 'pa=th')


class _PrependAppendEnvironmentTest(unittest.TestCase):
    """Tests for env_setup.environment."""
    def __init__(self, *args, **kwargs):
        windows = kwargs.pop('windows', False)
        pathsep = kwargs.pop('pathsep', os.pathsep)
        allcaps = kwargs.pop('allcaps', False)
        super(_PrependAppendEnvironmentTest, self).__init__(*args, **kwargs)
        self.windows = windows
        self.pathsep = pathsep
        self.allcaps = allcaps

        # If we're testing Windows behavior and actually running on Windows,
        # actually launch a subprocess to evaluate the shell init script.
        # Likewise if we're testing POSIX behavior and actually on a POSIX
        # system. Tests can check self.run_shell_tests and exit without
        # doing anything.
        real_windows = (os.name == 'nt')
        self.run_shell_tests = (self.windows == real_windows)

    def setUp(self):
        self.env = environment.Environment(windows=self.windows,
                                           pathsep=self.pathsep,
                                           allcaps=self.allcaps)

        self.var_already_set = self.env.normalize_key('VAR_ALREADY_SET')
        os.environ[self.var_already_set] = self.pathsep.join(
            'one two three'.split())
        self.assertIn(self.var_already_set, os.environ)

        self.var_not_set = self.env.normalize_key('VAR_NOT_SET')
        if self.var_not_set in os.environ:
            del os.environ[self.var_not_set]
        self.assertNotIn(self.var_not_set, os.environ)

        self.orig_env = os.environ.copy()

    def split(self, val):
        return val.split(self.pathsep)

    def tearDown(self):
        self.assertEqual(os.environ, self.orig_env)


# TODO(mohrr) remove disable=useless-object-inheritance once in Python 3.
# pylint: disable=useless-object-inheritance
class _AppendPrependTestMixin(object):
    def test_prepend_present_ctx(self):
        orig = os.environ[self.var_already_set]
        self.env.prepend(self.var_already_set, 'path')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_already_set],
                             self.pathsep.join(('path', orig)))

    def test_prepend_present_written(self):
        if not self.run_shell_tests:
            return

        orig = os.environ[self.var_already_set]
        self.env.prepend(self.var_already_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_already_set],
                         self.pathsep.join(('path', orig)))

    def test_prepend_notpresent_ctx(self):
        self.env.prepend(self.var_not_set, 'path')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_not_set], 'path')

    def test_prepend_notpresent_written(self):
        if not self.run_shell_tests:
            return

        self.env.prepend(self.var_not_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_not_set], 'path')

    def test_append_present_ctx(self):
        orig = os.environ[self.var_already_set]
        self.env.append(self.var_already_set, 'path')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_already_set],
                             self.pathsep.join((orig, 'path')))

    def test_append_present_written(self):
        if not self.run_shell_tests:
            return

        orig = os.environ[self.var_already_set]
        self.env.append(self.var_already_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_already_set],
                         self.pathsep.join((orig, 'path')))

    def test_append_notpresent_ctx(self):
        self.env.append(self.var_not_set, 'path')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_not_set], 'path')

    def test_append_notpresent_written(self):
        if not self.run_shell_tests:
            return

        self.env.append(self.var_not_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_not_set], 'path')

    def test_remove_ctx(self):
        self.env.set(self.var_not_set,
                     self.pathsep.join(('path', 'one', 'path', 'two', 'path')))

        self.env.append(self.var_not_set, 'path')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_not_set],
                             self.pathsep.join(('one', 'two', 'path')))

    def test_remove_written(self):
        if not self.run_shell_tests:
            return

        if self.windows:  # TODO(pwbug/231) Re-enable for Windows.
            return

        self.env.set(self.var_not_set,
                     self.pathsep.join(('path', 'one', 'path', 'two', 'path')))

        self.env.append(self.var_not_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_not_set],
                         self.pathsep.join(('one', 'two', 'path')))

    def test_remove_ctx_space(self):
        self.env.set(self.var_not_set,
                     self.pathsep.join(('pa th', 'one', 'pa th', 'two')))

        self.env.append(self.var_not_set, 'pa th')
        with self.env(export=False) as env:
            self.assertEqual(env[self.var_not_set],
                             self.pathsep.join(('one', 'two', 'pa th')))

    def test_remove_written_space(self):
        if not self.run_shell_tests:
            return

        if self.windows:  # TODO(pwbug/231) Re-enable for Windows.
            return

        self.env.set(self.var_not_set,
                     self.pathsep.join(('pa th', 'one', 'pa th', 'two')))

        self.env.append(self.var_not_set, 'pa th')
        env = _evaluate_env_in_shell(self.env)
        self.assertEqual(env[self.var_not_set],
                         self.pathsep.join(('one', 'two', 'pa th')))

    def test_remove_ctx_empty(self):
        self.env.remove(self.var_not_set, 'path')
        with self.env(export=False) as env:
            self.assertNotIn(self.var_not_set, env)

    def test_remove_written_empty(self):
        if not self.run_shell_tests:
            return

        self.env.remove(self.var_not_set, 'path')
        env = _evaluate_env_in_shell(self.env)
        self.assertNotIn(self.var_not_set, env)


class WindowsEnvironmentTest(_PrependAppendEnvironmentTest,
                             _AppendPrependTestMixin):
    def __init__(self, *args, **kwargs):
        kwargs['pathsep'] = ';'
        kwargs['windows'] = True
        kwargs['allcaps'] = True
        super(WindowsEnvironmentTest, self).__init__(*args, **kwargs)


class PosixEnvironmentTest(_PrependAppendEnvironmentTest,
                           _AppendPrependTestMixin):
    def __init__(self, *args, **kwargs):
        kwargs['pathsep'] = ':'
        kwargs['windows'] = False
        kwargs['allcaps'] = False
        super(PosixEnvironmentTest, self).__init__(*args, **kwargs)
        self.real_windows = (os.name == 'nt')


class WindowsCaseInsensitiveTest(unittest.TestCase):
    def test_lower_handling(self):
        # This is only for testing case-handling on Windows. It doesn't make
        # sense to run it on other systems.
        if os.name != 'nt':
            return

        lower_var = 'lower_var'
        upper_var = lower_var.upper()

        if upper_var in os.environ:
            del os.environ[upper_var]

        self.assertNotIn(lower_var, os.environ)

        env = environment.Environment()
        env.append(lower_var, 'foo')
        env.append(upper_var, 'bar')
        with env(export=False) as env_:
            self.assertNotIn(lower_var, env_)
            self.assertIn(upper_var, env_)
            self.assertEqual(env_[upper_var], 'foo;bar')


if __name__ == '__main__':
    import sys
    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
    unittest.main()
