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 # 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'