test/environment.py: ported to pytest, added a test on separators (#3375)
This commit is contained in:
parent
3d9cd72e33
commit
c6d9a45f18
@ -22,182 +22,246 @@
|
|||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
import unittest
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
from spack import spack_root
|
from spack import spack_root
|
||||||
from llnl.util.filesystem import join_path
|
|
||||||
from spack.environment import EnvironmentModifications
|
from spack.environment import EnvironmentModifications
|
||||||
from spack.environment import SetEnv, UnsetEnv
|
|
||||||
from spack.environment import RemovePath, PrependPath, AppendPath
|
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
|
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):
|
@pytest.fixture
|
||||||
pass
|
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):
|
@pytest.fixture
|
||||||
env = EnvironmentModifications()
|
def miscellaneous_paths():
|
||||||
self.assertEqual('foo', os.environ['UNSET_ME'])
|
"""Returns a list of paths, including system ones."""
|
||||||
env.unset('UNSET_ME')
|
return [
|
||||||
env.apply_modifications()
|
'/usr/local/Cellar/gcc/5.3.0/lib',
|
||||||
self.assertRaises(KeyError, os.environ.__getitem__, 'UNSET_ME')
|
'/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([
|
@pytest.fixture
|
||||||
'/usr/local/Cellar/gcc/5.3.0/bin',
|
def bin_paths():
|
||||||
'/usr/local/bin',
|
"""Returns a list of bin paths, including system ones."""
|
||||||
'/usr/local/opt/some-package/bin',
|
return [
|
||||||
'/usr/opt/bin',
|
'/usr/local/Cellar/gcc/5.3.0/bin',
|
||||||
'/bin',
|
'/usr/local/bin',
|
||||||
'/opt/some-package/bin',
|
'/usr/local/opt/some-package/bin',
|
||||||
])
|
'/usr/opt/bin',
|
||||||
self.assertEqual(filtered,
|
'/bin',
|
||||||
['/usr/local/bin',
|
'/opt/some-package/bin',
|
||||||
'/bin',
|
]
|
||||||
'/usr/local/Cellar/gcc/5.3.0/bin',
|
|
||||||
'/usr/local/opt/some-package/bin',
|
|
||||||
'/usr/opt/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):
|
@pytest.fixture
|
||||||
env = EnvironmentModifications()
|
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')
|
files = [
|
||||||
env.prepend_path('PATH_LIST', '/path/first')
|
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')
|
return files
|
||||||
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')
|
def test_set(env):
|
||||||
env.remove_path('REMOVE_PATH_LIST', '/duplicate/')
|
"""Tests setting values in the environment."""
|
||||||
|
|
||||||
env.apply_modifications()
|
# Here we are storing the commands to set a couple of variables
|
||||||
self.assertEqual(
|
env.set('A', 'dummy value')
|
||||||
'/path/first:/path/second:/path/third:/path/last',
|
env.set('B', 3)
|
||||||
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'])
|
|
||||||
|
|
||||||
def test_extra_arguments(self):
|
# ...and then we are executing them
|
||||||
env = EnvironmentModifications()
|
env.apply_modifications()
|
||||||
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'])
|
|
||||||
|
|
||||||
def test_extend(self):
|
assert 'dummy value' == os.environ['A']
|
||||||
env = EnvironmentModifications()
|
assert str(3) == os.environ['B']
|
||||||
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
|
|
||||||
|
|
||||||
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
|
def test_unset(env):
|
||||||
# spurious entries for things like PS1
|
"""Tests unsetting values in the environment."""
|
||||||
#
|
|
||||||
# TODO: figure out how to make a bit more robust.
|
|
||||||
self.assertTrue(len(modifications) >= 4)
|
|
||||||
|
|
||||||
# Set new variables
|
# Assert that the target variable is there and unset it
|
||||||
self.assertEqual(len(modifications['NEW_VAR']), 1)
|
assert 'foo' == os.environ['UNSET_ME']
|
||||||
self.assertTrue(isinstance(modifications['NEW_VAR'][0], SetEnv))
|
env.unset('UNSET_ME')
|
||||||
self.assertEqual(modifications['NEW_VAR'][0].value, 'new')
|
env.apply_modifications()
|
||||||
|
|
||||||
self.assertEqual(len(modifications['FOO']), 1)
|
# Trying to retrieve is after deletion should cause a KeyError
|
||||||
self.assertTrue(isinstance(modifications['FOO'][0], SetEnv))
|
with pytest.raises(KeyError):
|
||||||
self.assertEqual(modifications['FOO'][0].value, 'intel64')
|
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)
|
def test_filter_system_paths(miscellaneous_paths):
|
||||||
self.assertTrue(
|
"""Tests that the filtering of system paths works as expected."""
|
||||||
isinstance(modifications['PATH_LIST'][0], RemovePath)
|
filtered = filter_system_paths(miscellaneous_paths)
|
||||||
)
|
expected = [
|
||||||
self.assertEqual(modifications['PATH_LIST'][0].value, '/path/third')
|
'/usr/local/Cellar/gcc/5.3.0/lib',
|
||||||
self.assertTrue(
|
'/usr/local/opt/some-package/lib',
|
||||||
isinstance(modifications['PATH_LIST'][1], AppendPath)
|
'/usr/opt/lib',
|
||||||
)
|
'/opt/some-package/include'
|
||||||
self.assertEqual(modifications['PATH_LIST'][1].value, '/path/fourth')
|
]
|
||||||
self.assertTrue(
|
assert filtered == expected
|
||||||
isinstance(modifications['PATH_LIST'][2], PrependPath)
|
|
||||||
)
|
|
||||||
self.assertEqual(modifications['PATH_LIST'][2].value, '/path/first')
|
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'
|
||||||
|
Loading…
Reference in New Issue
Block a user