test/environment.py: ported to pytest, added a test on separators (#3375)

This commit is contained in:
Massimiliano Culpo 2017-03-07 16:03:12 +01:00 committed by Todd Gamblin
parent 3d9cd72e33
commit c6d9a45f18

View File

@ -22,182 +22,246 @@
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import unittest
import os
import pytest
from spack import spack_root
from llnl.util.filesystem import join_path
from spack.environment import EnvironmentModifications
from spack.environment import SetEnv, UnsetEnv
from spack.environment import RemovePath, PrependPath, AppendPath
from spack.environment import SetEnv, UnsetEnv
from spack.util.environment import filter_system_paths, filter_system_bin_paths
class EnvironmentTest(unittest.TestCase):
@pytest.fixture()
def prepare_environment_for_tests():
"""Sets a few dummy variables in the current environment, that will be
useful for the tests below.
"""
os.environ['UNSET_ME'] = 'foo'
os.environ['EMPTY_PATH_LIST'] = ''
os.environ['PATH_LIST'] = '/path/second:/path/third'
os.environ['REMOVE_PATH_LIST'] = '/a/b:/duplicate:/a/c:/remove/this:/a/d:/duplicate/:/f/g' # NOQA: ignore=E501
yield
for x in ('UNSET_ME', 'EMPTY_PATH_LIST', 'PATH_LIST', 'REMOVE_PATH_LIST'):
if x in os.environ:
del os.environ[x]
def setUp(self):
os.environ['UNSET_ME'] = 'foo'
os.environ['EMPTY_PATH_LIST'] = ''
os.environ['PATH_LIST'] = '/path/second:/path/third'
os.environ['REMOVE_PATH_LIST'] = \
'/a/b:/duplicate:/a/c:/remove/this:/a/d:/duplicate/:/f/g'
def tearDown(self):
pass
@pytest.fixture
def env(prepare_environment_for_tests):
"""Returns an empty EnvironmentModifications object."""
return EnvironmentModifications()
def test_set(self):
env = EnvironmentModifications()
env.set('A', 'dummy value')
env.set('B', 3)
env.apply_modifications()
self.assertEqual('dummy value', os.environ['A'])
self.assertEqual(str(3), os.environ['B'])
def test_unset(self):
env = EnvironmentModifications()
self.assertEqual('foo', os.environ['UNSET_ME'])
env.unset('UNSET_ME')
env.apply_modifications()
self.assertRaises(KeyError, os.environ.__getitem__, 'UNSET_ME')
@pytest.fixture
def miscellaneous_paths():
"""Returns a list of paths, including system ones."""
return [
'/usr/local/Cellar/gcc/5.3.0/lib',
'/usr/local/lib',
'/usr/local',
'/usr/local/include',
'/usr/local/lib64',
'/usr/local/opt/some-package/lib',
'/usr/opt/lib',
'/lib',
'/',
'/usr',
'/lib64',
'/include',
'/opt/some-package/include',
]
def test_filter_system_paths(self):
filtered = filter_system_paths([
'/usr/local/Cellar/gcc/5.3.0/lib',
'/usr/local/lib',
'/usr/local',
'/usr/local/include',
'/usr/local/lib64',
'/usr/local/opt/some-package/lib',
'/usr/opt/lib',
'/lib',
'/',
'/usr',
'/lib64',
'/include',
'/opt/some-package/include',
])
self.assertEqual(filtered,
['/usr/local/Cellar/gcc/5.3.0/lib',
'/usr/local/opt/some-package/lib',
'/usr/opt/lib',
'/opt/some-package/include'])
filtered = filter_system_bin_paths([
'/usr/local/Cellar/gcc/5.3.0/bin',
'/usr/local/bin',
'/usr/local/opt/some-package/bin',
'/usr/opt/bin',
'/bin',
'/opt/some-package/bin',
])
self.assertEqual(filtered,
['/usr/local/bin',
'/bin',
'/usr/local/Cellar/gcc/5.3.0/bin',
'/usr/local/opt/some-package/bin',
'/usr/opt/bin',
'/opt/some-package/bin'])
@pytest.fixture
def bin_paths():
"""Returns a list of bin paths, including system ones."""
return [
'/usr/local/Cellar/gcc/5.3.0/bin',
'/usr/local/bin',
'/usr/local/opt/some-package/bin',
'/usr/opt/bin',
'/bin',
'/opt/some-package/bin',
]
def test_set_path(self):
env = EnvironmentModifications()
env.set_path('A', ['foo', 'bar', 'baz'])
env.apply_modifications()
self.assertEqual('foo:bar:baz', os.environ['A'])
def test_path_manipulation(self):
env = EnvironmentModifications()
@pytest.fixture
def files_to_be_sourced():
"""Returns a list of files to be sourced"""
datadir = os.path.join(
spack_root, 'lib', 'spack', 'spack', 'test', 'data'
)
env.append_path('PATH_LIST', '/path/last')
env.prepend_path('PATH_LIST', '/path/first')
files = [
os.path.join(datadir, 'sourceme_first.sh'),
os.path.join(datadir, 'sourceme_second.sh'),
os.path.join(datadir, 'sourceme_parameters.sh intel64')
]
env.append_path('EMPTY_PATH_LIST', '/path/middle')
env.append_path('EMPTY_PATH_LIST', '/path/last')
env.prepend_path('EMPTY_PATH_LIST', '/path/first')
return files
env.append_path('NEWLY_CREATED_PATH_LIST', '/path/middle')
env.append_path('NEWLY_CREATED_PATH_LIST', '/path/last')
env.prepend_path('NEWLY_CREATED_PATH_LIST', '/path/first')
env.remove_path('REMOVE_PATH_LIST', '/remove/this')
env.remove_path('REMOVE_PATH_LIST', '/duplicate/')
def test_set(env):
"""Tests setting values in the environment."""
env.apply_modifications()
self.assertEqual(
'/path/first:/path/second:/path/third:/path/last',
os.environ['PATH_LIST']
)
self.assertEqual(
'/path/first:/path/middle:/path/last',
os.environ['EMPTY_PATH_LIST']
)
self.assertEqual(
'/path/first:/path/middle:/path/last',
os.environ['NEWLY_CREATED_PATH_LIST']
)
self.assertEqual('/a/b:/a/c:/a/d:/f/g', os.environ['REMOVE_PATH_LIST'])
# Here we are storing the commands to set a couple of variables
env.set('A', 'dummy value')
env.set('B', 3)
def test_extra_arguments(self):
env = EnvironmentModifications()
env.set('A', 'dummy value', who='Pkg1')
for x in env:
assert 'who' in x.args
env.apply_modifications()
self.assertEqual('dummy value', os.environ['A'])
# ...and then we are executing them
env.apply_modifications()
def test_extend(self):
env = EnvironmentModifications()
env.set('A', 'dummy value')
env.set('B', 3)
copy_construct = EnvironmentModifications(env)
self.assertEqual(len(copy_construct), 2)
for x, y in zip(env, copy_construct):
assert x is y
assert 'dummy value' == os.environ['A']
assert str(3) == os.environ['B']
def test_source_files(self):
datadir = join_path(spack_root, 'lib', 'spack',
'spack', 'test', 'data')
files = [
join_path(datadir, 'sourceme_first.sh'),
join_path(datadir, 'sourceme_second.sh'),
join_path(datadir, 'sourceme_parameters.sh intel64')
]
env = EnvironmentModifications.from_sourcing_files(*files)
modifications = env.group_by_name()
# This is sensitive to the user's environment; can include
# spurious entries for things like PS1
#
# TODO: figure out how to make a bit more robust.
self.assertTrue(len(modifications) >= 4)
def test_unset(env):
"""Tests unsetting values in the environment."""
# Set new variables
self.assertEqual(len(modifications['NEW_VAR']), 1)
self.assertTrue(isinstance(modifications['NEW_VAR'][0], SetEnv))
self.assertEqual(modifications['NEW_VAR'][0].value, 'new')
# Assert that the target variable is there and unset it
assert 'foo' == os.environ['UNSET_ME']
env.unset('UNSET_ME')
env.apply_modifications()
self.assertEqual(len(modifications['FOO']), 1)
self.assertTrue(isinstance(modifications['FOO'][0], SetEnv))
self.assertEqual(modifications['FOO'][0].value, 'intel64')
# Trying to retrieve is after deletion should cause a KeyError
with pytest.raises(KeyError):
os.environ['UNSET_ME']
# Unset variables
self.assertEqual(len(modifications['EMPTY_PATH_LIST']), 1)
self.assertTrue(isinstance(
modifications['EMPTY_PATH_LIST'][0], UnsetEnv))
# Modified variables
self.assertEqual(len(modifications['UNSET_ME']), 1)
self.assertTrue(isinstance(modifications['UNSET_ME'][0], SetEnv))
self.assertEqual(modifications['UNSET_ME'][0].value, 'overridden')
self.assertEqual(len(modifications['PATH_LIST']), 3)
self.assertTrue(
isinstance(modifications['PATH_LIST'][0], RemovePath)
)
self.assertEqual(modifications['PATH_LIST'][0].value, '/path/third')
self.assertTrue(
isinstance(modifications['PATH_LIST'][1], AppendPath)
)
self.assertEqual(modifications['PATH_LIST'][1].value, '/path/fourth')
self.assertTrue(
isinstance(modifications['PATH_LIST'][2], PrependPath)
)
self.assertEqual(modifications['PATH_LIST'][2].value, '/path/first')
def test_filter_system_paths(miscellaneous_paths):
"""Tests that the filtering of system paths works as expected."""
filtered = filter_system_paths(miscellaneous_paths)
expected = [
'/usr/local/Cellar/gcc/5.3.0/lib',
'/usr/local/opt/some-package/lib',
'/usr/opt/lib',
'/opt/some-package/include'
]
assert filtered == expected
def test_filter_system_bin_paths(bin_paths):
"""Tests that the filtering of system bin paths works as expected."""
filtered = filter_system_bin_paths(bin_paths)
expected = [
'/usr/local/bin',
'/bin',
'/usr/local/Cellar/gcc/5.3.0/bin',
'/usr/local/opt/some-package/bin',
'/usr/opt/bin',
'/opt/some-package/bin'
]
assert filtered == expected
def test_set_path(env):
"""Tests setting paths in an environment variable."""
# Check setting paths with the default separator
env.set_path('A', ['foo', 'bar', 'baz'])
env.apply_modifications()
assert 'foo:bar:baz' == os.environ['A']
env.set_path('B', ['foo', 'bar', 'baz'], separator=';')
env.apply_modifications()
assert 'foo;bar;baz' == os.environ['B']
def test_path_manipulation(env):
"""Tests manipulating list of paths in the environment."""
env.append_path('PATH_LIST', '/path/last')
env.prepend_path('PATH_LIST', '/path/first')
env.append_path('EMPTY_PATH_LIST', '/path/middle')
env.append_path('EMPTY_PATH_LIST', '/path/last')
env.prepend_path('EMPTY_PATH_LIST', '/path/first')
env.append_path('NEWLY_CREATED_PATH_LIST', '/path/middle')
env.append_path('NEWLY_CREATED_PATH_LIST', '/path/last')
env.prepend_path('NEWLY_CREATED_PATH_LIST', '/path/first')
env.remove_path('REMOVE_PATH_LIST', '/remove/this')
env.remove_path('REMOVE_PATH_LIST', '/duplicate/')
env.apply_modifications()
expected = '/path/first:/path/second:/path/third:/path/last'
assert os.environ['PATH_LIST'] == expected
expected = '/path/first:/path/middle:/path/last'
assert os.environ['EMPTY_PATH_LIST'] == expected
expected = '/path/first:/path/middle:/path/last'
assert os.environ['NEWLY_CREATED_PATH_LIST'] == expected
assert os.environ['REMOVE_PATH_LIST'] == '/a/b:/a/c:/a/d:/f/g'
def test_extra_arguments(env):
"""Tests that we can attach extra arguments to any command."""
env.set('A', 'dummy value', who='Pkg1')
for x in env:
assert 'who' in x.args
env.apply_modifications()
assert 'dummy value' == os.environ['A']
def test_extend(env):
"""Tests that we can construct a list of environment modifications
starting from another list.
"""
env.set('A', 'dummy value')
env.set('B', 3)
copy_construct = EnvironmentModifications(env)
assert len(copy_construct) == 2
for x, y in zip(env, copy_construct):
assert x is y
@pytest.mark.usefixtures('prepare_environment_for_tests')
def test_source_files(files_to_be_sourced):
"""Tests the construction of a list of environment modifications that are
the result of sourcing a file.
"""
env = EnvironmentModifications.from_sourcing_files(*files_to_be_sourced)
modifications = env.group_by_name()
# This is sensitive to the user's environment; can include
# spurious entries for things like PS1
#
# TODO: figure out how to make a bit more robust.
assert len(modifications) >= 4
# Set new variables
assert len(modifications['NEW_VAR']) == 1
assert isinstance(modifications['NEW_VAR'][0], SetEnv)
assert modifications['NEW_VAR'][0].value == 'new'
assert len(modifications['FOO']) == 1
assert isinstance(modifications['FOO'][0], SetEnv)
assert modifications['FOO'][0].value == 'intel64'
# Unset variables
assert len(modifications['EMPTY_PATH_LIST']) == 1
assert isinstance(modifications['EMPTY_PATH_LIST'][0], UnsetEnv)
# Modified variables
assert len(modifications['UNSET_ME']) == 1
assert isinstance(modifications['UNSET_ME'][0], SetEnv)
assert modifications['UNSET_ME'][0].value == 'overridden'
assert len(modifications['PATH_LIST']) == 3
assert isinstance(modifications['PATH_LIST'][0], RemovePath)
assert modifications['PATH_LIST'][0].value == '/path/third'
assert isinstance(modifications['PATH_LIST'][1], AppendPath)
assert modifications['PATH_LIST'][1].value == '/path/fourth'
assert isinstance(modifications['PATH_LIST'][2], PrependPath)
assert modifications['PATH_LIST'][2].value == '/path/first'