From 4ec404dfc07d7fd61f752016a4b1eef0257d328c Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 22 Oct 2020 22:59:39 +0200 Subject: 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. --- lib/spack/spack/test/conftest.py | 12 +++- lib/spack/spack/test/data/config/config.yaml | 3 +- lib/spack/spack/test/modules/conftest.py | 84 ++-------------------------- lib/spack/spack/test/modules/tcl.py | 6 +- 4 files changed, 23 insertions(+), 82 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py index 152c2c846e..0a39d1c6c3 100644 --- a/lib/spack/spack/test/conftest.py +++ b/lib/spack/spack/test/conftest.py @@ -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') diff --git a/lib/spack/spack/test/data/config/config.yaml b/lib/spack/spack/test/data/config/config.yaml index efbe625151..4e036a3d66 100644 --- a/lib/spack/spack/test/data/config/config.yaml +++ b/lib/spack/spack/test/data/config/config.yaml @@ -14,4 +14,5 @@ config: checksum: true dirty: false module_roots: - tcl: $spack/share/spack/modules + tcl: {0} + lmod: {1} diff --git a/lib/spack/spack/test/modules/conftest.py b/lib/spack/spack/test/modules/conftest.py index 365a5a7092..4ab129a5dd 100644 --- a/lib/spack/spack/test/modules/conftest.py +++ b/lib/spack/spack/test/modules/conftest.py @@ -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 @@ import spack.util.path @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 modulefile_content(filename_dict, request): 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""" diff --git a/lib/spack/spack/test/modules/tcl.py b/lib/spack/spack/test/modules/tcl.py index ec0b47c484..ae7ef9e50e 100644 --- a/lib/spack/spack/test/modules/tcl.py +++ b/lib/spack/spack/test/modules/tcl.py @@ -133,8 +133,10 @@ class TestTcl(object): 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') -- cgit v1.2.3-60-g2f50