Add scratch module roots to test configuration (#19477)
fixes #19476 Module file content is written to file in a temporary location and read back to be analyzed by unit tests. The approach to patch "open" and write to a StringIO in memory has been abandoned, since over time other operations insisting on the filesystem have been added to the module file generator.
This commit is contained in:
parent
d6f19eeed2
commit
4ec404dfc0
@ -425,7 +425,17 @@ def configuration_dir(tmpdir_factory, linux_os):
|
||||
# Create temporary 'defaults', 'site' and 'user' folders
|
||||
tmpdir.ensure('user', dir=True)
|
||||
|
||||
# Slightly modify compilers.yaml to look like Linux
|
||||
# Slightly modify config.yaml and compilers.yaml
|
||||
config_yaml = test_config.join('config.yaml')
|
||||
modules_root = tmpdir_factory.mktemp('share')
|
||||
tcl_root = modules_root.ensure('modules', dir=True)
|
||||
lmod_root = modules_root.ensure('lmod', dir=True)
|
||||
content = ''.join(config_yaml.read()).format(
|
||||
str(tcl_root), str(lmod_root)
|
||||
)
|
||||
t = tmpdir.join('site', 'config.yaml')
|
||||
t.write(content)
|
||||
|
||||
compilers_yaml = test_config.join('compilers.yaml')
|
||||
content = ''.join(compilers_yaml.read()).format(linux_os)
|
||||
t = tmpdir.join('site', 'compilers.yaml')
|
||||
|
@ -14,4 +14,5 @@ config:
|
||||
checksum: true
|
||||
dirty: false
|
||||
module_roots:
|
||||
tcl: $spack/share/spack/modules
|
||||
tcl: {0}
|
||||
lmod: {1}
|
||||
|
@ -2,16 +2,9 @@
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os.path
|
||||
import collections
|
||||
import contextlib
|
||||
import inspect
|
||||
|
||||
import ruamel.yaml as yaml
|
||||
import pytest
|
||||
from six import StringIO
|
||||
|
||||
import spack.config
|
||||
import spack.paths
|
||||
import spack.spec
|
||||
import spack.modules.common
|
||||
@ -19,34 +12,7 @@
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def file_registry():
|
||||
"""Fake filesystem for modulefiles test"""
|
||||
return collections.defaultdict(StringIO)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def filename_dict(file_registry, monkeypatch):
|
||||
"""Returns a fake open that writes on a StringIO instance instead
|
||||
of disk.
|
||||
"""
|
||||
@contextlib.contextmanager
|
||||
def _mock(filename, mode):
|
||||
if not mode == 'w':
|
||||
raise RuntimeError('opening mode must be "w" [stringio_open]')
|
||||
|
||||
try:
|
||||
yield file_registry[filename]
|
||||
finally:
|
||||
handle = file_registry[filename]
|
||||
file_registry[filename] = handle.getvalue()
|
||||
handle.close()
|
||||
# Patch 'open' in the appropriate module
|
||||
monkeypatch.setattr(spack.modules.common, 'open', _mock, raising=False)
|
||||
return file_registry
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def modulefile_content(filename_dict, request):
|
||||
def modulefile_content(request):
|
||||
"""Returns a function that generates the content of a module file
|
||||
as a list of lines.
|
||||
"""
|
||||
@ -58,59 +24,21 @@ def _impl(spec_str):
|
||||
spec = spack.spec.Spec(spec_str)
|
||||
spec.concretize()
|
||||
generator = writer_cls(spec)
|
||||
generator.write()
|
||||
generator.write(overwrite=True)
|
||||
|
||||
# Get its filename
|
||||
filename = generator.layout.filename
|
||||
|
||||
# Retrieve the content
|
||||
content = filename_dict[filename].split('\n')
|
||||
with open(filename) as f:
|
||||
content = f.readlines()
|
||||
content = ''.join(content).split('\n')
|
||||
generator.remove()
|
||||
return content
|
||||
|
||||
return _impl
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def patch_configuration(monkeypatch, request):
|
||||
"""Reads a configuration file from the mock ones prepared for tests
|
||||
and monkeypatches the right classes to hook it in.
|
||||
"""
|
||||
# Class of the module file writer
|
||||
writer_cls = getattr(request.module, 'writer_cls')
|
||||
# Module where the module file writer is defined
|
||||
writer_mod = inspect.getmodule(writer_cls)
|
||||
# Key for specific settings relative to this module type
|
||||
writer_key = str(writer_mod.__name__).split('.')[-1]
|
||||
# Root folder for configuration
|
||||
root_for_conf = os.path.join(
|
||||
spack.paths.test_path, 'data', 'modules', writer_key
|
||||
)
|
||||
|
||||
def _impl(filename):
|
||||
|
||||
file = os.path.join(root_for_conf, filename + '.yaml')
|
||||
with open(file) as f:
|
||||
configuration = yaml.load(f)
|
||||
|
||||
monkeypatch.setattr(
|
||||
spack.modules.common,
|
||||
'configuration',
|
||||
configuration
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
writer_mod,
|
||||
'configuration',
|
||||
configuration[writer_key]
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
writer_mod,
|
||||
'configuration_registry',
|
||||
{}
|
||||
)
|
||||
return _impl
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def update_template_dirs(config, monkeypatch):
|
||||
"""Mocks the template directories for tests"""
|
||||
|
@ -133,8 +133,10 @@ def test_blacklist(self, modulefile_content, module_configuration):
|
||||
assert len([x for x in content if 'is-loaded' in x]) == 1
|
||||
assert len([x for x in content if 'module load ' in x]) == 1
|
||||
|
||||
# Returns a StringIO instead of a string as no module file was written
|
||||
with pytest.raises(AttributeError):
|
||||
# Catch "Exception" to avoid using FileNotFoundError on Python 3
|
||||
# and IOError on Python 2 or common bases like EnvironmentError
|
||||
# which are not officially documented
|
||||
with pytest.raises(Exception):
|
||||
modulefile_content('callpath arch=x86-linux')
|
||||
|
||||
content = modulefile_content('zmpi arch=x86-linux')
|
||||
|
Loading…
Reference in New Issue
Block a user