Testing: fix unintended interactions between tests, part 2 (#16429)

This fixes some errors with setting up test configuration. These
errors do not cause current Spack tests to fail but do create
red herring issues elsewhere (see #15666). Fixing these errors
leads to more errors in tests that depended on the original
misconfigured state, so those are also addressed here.

This is an update to #16003 which accounts for some unit tests with
conflicting config/mutable_config fixtures. These conflicts were
not exposed until the mutable_config fixture was fixed. Details are
included below. The change which builds on #16003 is prefixed with
"(new)".

* For tests that use the real Spack package repository, the config
  needs to avoid using MPI providers that are not intended to be
  installed by Spack. Without this, it is possible that Spack tests
  which concretize the MPI virtual will end up trying to use an
  implementation that it shouldn't (e.g. one that is always
  provided externally). See #15666 for an example.
* The mutable_config test fixture was not initializing the scope
  roots to the right directories (so the resulting config was empty).
* The current_host fixture in the concretize.py tests was using the
  config fixture rather than mutable_config, and was polluting the
  config cache for other tests.
* One test in concretize.py was clearing a nonexistent cache
  (PackagePrefs._packages_config_cache). This reference has been
  removed.
* The test 'test_preferred_compilers' was was depending on cross
  test config pollution to succeed. The initial spec before
  concretization has been updated to updated to be explicit about
  the desired result.
* (new) For tests that use install_mockery and mutable_config,
  replace install_mockery with a separate install_mockery_mutable_config
  fixture that is exactly the same as install_mockery but uses the
  mutable_config fixture to avoid conflicts.
This commit is contained in:
Peter Scheibel 2020-05-07 14:01:58 -07:00 committed by GitHub
parent d7bd070ae9
commit 1ed564a1e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 12 deletions

View file

@ -159,7 +159,19 @@ def compiler_list(args):
tty.msg("Available compilers") tty.msg("Available compilers")
index = index_by(spack.compilers.all_compilers(scope=args.scope), index = index_by(spack.compilers.all_compilers(scope=args.scope),
lambda c: (c.spec.name, c.operating_system, c.target)) lambda c: (c.spec.name, c.operating_system, c.target))
ordered_sections = sorted(index.items(), key=lambda item: item[0])
# For a container, take each element which does not evaluate to false and
# convert it to a string. For elements which evaluate to False (e.g. None)
# convert them to '' (in which case it still evaluates to False but is a
# string type). Tuples produced by this are guaranteed to be comparable in
# Python 3
convert_str = (
lambda tuple_container:
tuple(str(x) if x else '' for x in tuple_container))
index_str_keys = list(
(convert_str(x), y) for x, y in index.items())
ordered_sections = sorted(index_str_keys, key=lambda item: item[0])
for i, (key, compilers) in enumerate(ordered_sections): for i, (key, compilers) in enumerate(ordered_sections):
if i >= 1: if i >= 1:
print() print()

View file

@ -722,8 +722,8 @@ def test_cdash_auth_token(tmpdir, install_mockery, capfd):
def test_compiler_bootstrap( def test_compiler_bootstrap(
install_mockery, mock_packages, mock_fetch, mock_archive, install_mockery_mutable_config, mock_packages, mock_fetch,
mutable_config, monkeypatch): mock_archive, mutable_config, monkeypatch):
monkeypatch.setattr(spack.concretize.Concretizer, monkeypatch.setattr(spack.concretize.Concretizer,
'check_for_compiler_existence', False) 'check_for_compiler_existence', False)
spack.config.set('config:install_missing_compilers', True) spack.config.set('config:install_missing_compilers', True)
@ -735,8 +735,8 @@ def test_compiler_bootstrap(
@pytest.mark.regression('16221') @pytest.mark.regression('16221')
def test_compiler_bootstrap_already_installed( def test_compiler_bootstrap_already_installed(
install_mockery, mock_packages, mock_fetch, mock_archive, install_mockery_mutable_config, mock_packages, mock_fetch,
mutable_config, monkeypatch): mock_archive, mutable_config, monkeypatch):
monkeypatch.setattr(spack.concretize.Concretizer, monkeypatch.setattr(spack.concretize.Concretizer,
'check_for_compiler_existence', False) 'check_for_compiler_existence', False)
spack.config.set('config:install_missing_compilers', True) spack.config.set('config:install_missing_compilers', True)

View file

@ -12,7 +12,6 @@
from spack.concretize import find_spec, NoValidVersionError from spack.concretize import find_spec, NoValidVersionError
from spack.error import SpecError from spack.error import SpecError
from spack.package_prefs import PackagePrefs
from spack.spec import Spec, CompilerSpec, ConflictsInSpecError from spack.spec import Spec, CompilerSpec, ConflictsInSpecError
from spack.version import ver from spack.version import ver
from spack.util.mock_package import MockPackageMultiRepo from spack.util.mock_package import MockPackageMultiRepo
@ -103,8 +102,6 @@ def current_host(request, monkeypatch):
monkeypatch.setattr(spack.platforms.test.Test, 'default', cpu) monkeypatch.setattr(spack.platforms.test.Test, 'default', cpu)
yield target yield target
else: else:
# There's a cache that needs to be cleared for unit tests
PackagePrefs._packages_config_cache = None
with spack.config.override('packages:all', {'target': [cpu]}): with spack.config.override('packages:all', {'target': [cpu]}):
yield target yield target
@ -112,7 +109,10 @@ def current_host(request, monkeypatch):
spack.architecture.get_platform.cache.clear() spack.architecture.get_platform.cache.clear()
@pytest.mark.usefixtures('config', 'mock_packages') # This must use the mutable_config fixture because the test
# adjusting_default_target_based_on_compiler uses the current_host fixture,
# which changes the config.
@pytest.mark.usefixtures('mutable_config', 'mock_packages')
class TestConcretize(object): class TestConcretize(object):
def test_concretize(self, spec): def test_concretize(self, spec):
check_concretize(spec) check_concretize(spec)

View file

@ -100,7 +100,7 @@ def test_preferred_compilers(self):
# Try the last available compiler # Try the last available compiler
compiler = str(compiler_list[-1]) compiler = str(compiler_list[-1])
update_packages('mpileaks', 'compiler', [compiler]) update_packages('mpileaks', 'compiler', [compiler])
spec = concretize('mpileaks') spec = concretize('mpileaks os=redhat6 target=x86')
assert spec.compiler == spack.spec.CompilerSpec(compiler) assert spec.compiler == spack.spec.CompilerSpec(compiler)
def test_preferred_target(self, mutable_mock_repo): def test_preferred_target(self, mutable_mock_repo):

View file

@ -423,13 +423,13 @@ def config(mock_configuration):
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def mutable_config(tmpdir_factory, configuration_dir, monkeypatch): def mutable_config(tmpdir_factory, configuration_dir):
"""Like config, but tests can modify the configuration.""" """Like config, but tests can modify the configuration."""
mutable_dir = tmpdir_factory.mktemp('mutable_config').join('tmp') mutable_dir = tmpdir_factory.mktemp('mutable_config').join('tmp')
configuration_dir.copy(mutable_dir) configuration_dir.copy(mutable_dir)
cfg = spack.config.Configuration( cfg = spack.config.Configuration(
*[spack.config.ConfigScope(name, str(mutable_dir)) *[spack.config.ConfigScope(name, str(mutable_dir.join(name)))
for name in ['site', 'system', 'user']]) for name in ['site', 'system', 'user']])
with use_configuration(cfg): with use_configuration(cfg):
@ -602,6 +602,26 @@ def install_mockery(tmpdir, config, mock_packages, monkeypatch):
spack.store.store = real_store spack.store.store = real_store
@pytest.fixture(scope='function')
def install_mockery_mutable_config(
tmpdir, mutable_config, mock_packages, monkeypatch):
"""Hooks a fake install directory, DB, and stage directory into Spack.
This is specifically for tests which want to use 'install_mockery' but
also need to modify configuration (and hence would want to use
'mutable config'): 'install_mockery' does not support this.
"""
real_store = spack.store.store
spack.store.store = spack.store.Store(str(tmpdir.join('opt')))
# We use a fake package, so temporarily disable checksumming
with spack.config.override('config:checksum', False):
yield
tmpdir.join('opt').remove()
spack.store.store = real_store
@pytest.fixture() @pytest.fixture()
def mock_fetch(mock_archive): def mock_fetch(mock_archive):
"""Fake the URL for a package so it downloads from a file.""" """Fake the URL for a package so it downloads from a file."""

View file

@ -1,4 +1,7 @@
packages: packages:
all:
providers:
mpi: [openmpi, mpich]
externaltool: externaltool:
buildable: False buildable: False
paths: paths: