summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2022-11-11 21:32:40 +0100
committerGitHub <noreply@github.com>2022-11-11 21:32:40 +0100
commit022a2d2eafb04850b6a2b80b77642627e2878658 (patch)
tree61c899f6e54774c979b198355d3d770308d53879
parent5f8511311cb82e6debf1defc8f8a7b8d53279a33 (diff)
downloadspack-022a2d2eafb04850b6a2b80b77642627e2878658.tar.gz
spack-022a2d2eafb04850b6a2b80b77642627e2878658.tar.bz2
spack-022a2d2eafb04850b6a2b80b77642627e2878658.tar.xz
spack-022a2d2eafb04850b6a2b80b77642627e2878658.zip
Speed-up unit tests by caching default mock concretization (#33755)
-rw-r--r--lib/spack/spack/test/architecture.py39
-rw-r--r--lib/spack/spack/test/build_systems.py92
-rw-r--r--lib/spack/spack/test/ci.py33
-rw-r--r--lib/spack/spack/test/conftest.py24
-rw-r--r--lib/spack/spack/test/database.py20
-rw-r--r--lib/spack/spack/test/directory_layout.py11
-rw-r--r--lib/spack/spack/test/git_fetch.py47
-rw-r--r--lib/spack/spack/test/packaging.py18
-rw-r--r--lib/spack/spack/test/spec_semantics.py98
-rw-r--r--lib/spack/spack/test/url_fetch.py16
10 files changed, 218 insertions, 180 deletions
diff --git a/lib/spack/spack/test/architecture.py b/lib/spack/spack/test/architecture.py
index 92914be685..ef95e4b383 100644
--- a/lib/spack/spack/test/architecture.py
+++ b/lib/spack/spack/test/architecture.py
@@ -17,7 +17,7 @@ import spack.spec
import spack.target
-@pytest.fixture
+@pytest.fixture(scope="module")
def current_host_platform():
"""Return the platform of the current host as detected by the
'platform' stdlib package.
@@ -34,23 +34,23 @@ def current_host_platform():
# Valid keywords for os=xxx or target=xxx
-valid_keywords = ["fe", "be", "frontend", "backend"]
+VALID_KEYWORDS = ["fe", "be", "frontend", "backend"]
+TEST_PLATFORM = spack.platforms.Test()
-@pytest.fixture(
- params=([x for x in spack.platforms.Test().targets] + valid_keywords + ["default_target"])
-)
+
+@pytest.fixture(params=([str(x) for x in TEST_PLATFORM.targets] + VALID_KEYWORDS), scope="module")
def target_str(request):
"""All the possible strings that can be used for targets"""
- return str(request.param)
+ return request.param
@pytest.fixture(
- params=([x for x in spack.platforms.Test().operating_sys] + valid_keywords + ["default_os"])
+ params=([str(x) for x in TEST_PLATFORM.operating_sys] + VALID_KEYWORDS), scope="module"
)
def os_str(request):
"""All the possible strings that can be used for operating systems"""
- return str(request.param)
+ return request.param
def test_platform(current_host_platform):
@@ -64,16 +64,19 @@ def test_user_input_combination(config, target_str, os_str):
"""Test for all the valid user input combinations that both the target and
the operating system match.
"""
- platform = spack.platforms.Test()
- spec_str = "libelf"
- if os_str != "default_os":
- spec_str += " os={0}".format(os_str)
- if target_str != "default_target":
- spec_str += " target={0}".format(target_str)
- spec = spack.spec.Spec(spec_str).concretized()
-
- assert spec.architecture.os == str(platform.operating_system(os_str))
- assert spec.architecture.target == platform.target(target_str)
+ spec_str = "libelf os={} target={}".format(os_str, target_str)
+ spec = spack.spec.Spec(spec_str)
+ assert spec.architecture.os == str(TEST_PLATFORM.operating_system(os_str))
+ assert spec.architecture.target == TEST_PLATFORM.target(target_str)
+
+
+def test_default_os_and_target(config):
+ """Test that is we don't specify `os=` or `target=` we get the default values
+ after concretization.
+ """
+ spec = spack.spec.Spec("libelf").concretized()
+ assert spec.architecture.os == str(TEST_PLATFORM.operating_system("default_os"))
+ assert spec.architecture.target == TEST_PLATFORM.target("default_target")
def test_operating_system_conversion_to_dict():
diff --git a/lib/spack/spack/test/build_systems.py b/lib/spack/spack/test/build_systems.py
index 03a920a28e..5202a7f58d 100644
--- a/lib/spack/spack/test/build_systems.py
+++ b/lib/spack/spack/test/build_systems.py
@@ -27,9 +27,9 @@ pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="does not run on
@pytest.fixture()
-def concretize_and_setup():
+def concretize_and_setup(default_mock_concretization):
def _func(spec_str):
- s = Spec("mpich").concretized()
+ s = default_mock_concretization(spec_str)
setup_package(s.package, False)
return s
@@ -95,8 +95,8 @@ class TestTargets(object):
@pytest.mark.usefixtures("config", "mock_packages")
class TestAutotoolsPackage(object):
- def test_with_or_without(self):
- s = Spec("a").concretized()
+ def test_with_or_without(self, default_mock_concretization):
+ s = default_mock_concretization("a")
options = s.package.with_or_without("foo")
# Ensure that values that are not representing a feature
@@ -127,8 +127,8 @@ class TestAutotoolsPackage(object):
options = s.package.with_or_without("lorem-ipsum", variant="lorem_ipsum")
assert "--without-lorem-ipsum" in options
- def test_none_is_allowed(self):
- s = Spec("a foo=none").concretized()
+ def test_none_is_allowed(self, default_mock_concretization):
+ s = default_mock_concretization("a foo=none")
options = s.package.with_or_without("foo")
# Ensure that values that are not representing a feature
@@ -138,9 +138,11 @@ class TestAutotoolsPackage(object):
assert "--without-baz" in options
assert "--no-fee" in options
- def test_libtool_archive_files_are_deleted_by_default(self, mutable_database):
+ def test_libtool_archive_files_are_deleted_by_default(
+ self, default_mock_concretization, mutable_database
+ ):
# Install a package that creates a mock libtool archive
- s = Spec("libtool-deletion").concretized()
+ s = default_mock_concretization("libtool-deletion")
s.package.do_install(explicit=True)
# Assert the libtool archive is not there and we have
@@ -151,24 +153,25 @@ class TestAutotoolsPackage(object):
assert libtool_deletion_log
def test_libtool_archive_files_might_be_installed_on_demand(
- self, mutable_database, monkeypatch
+ self, mutable_database, monkeypatch, default_mock_concretization
):
# Install a package that creates a mock libtool archive,
# patch its package to preserve the installation
- s = Spec("libtool-deletion").concretized()
+ s = default_mock_concretization("libtool-deletion")
monkeypatch.setattr(type(s.package.builder), "install_libtool_archives", True)
s.package.do_install(explicit=True)
# Assert libtool archives are installed
assert os.path.exists(s.package.builder.libtool_archive_file)
- def test_autotools_gnuconfig_replacement(self, mutable_database):
+ def test_autotools_gnuconfig_replacement(self, default_mock_concretization, mutable_database):
"""
Tests whether only broken config.sub and config.guess are replaced with
files from working alternatives from the gnuconfig package.
"""
- s = Spec("autotools-config-replacement +patch_config_files +gnuconfig")
- s.concretize()
+ s = default_mock_concretization(
+ "autotools-config-replacement +patch_config_files +gnuconfig"
+ )
s.package.do_install()
with open(os.path.join(s.prefix.broken, "config.sub")) as f:
@@ -183,12 +186,15 @@ class TestAutotoolsPackage(object):
with open(os.path.join(s.prefix.working, "config.guess")) as f:
assert "gnuconfig version of config.guess" not in f.read()
- def test_autotools_gnuconfig_replacement_disabled(self, mutable_database):
+ def test_autotools_gnuconfig_replacement_disabled(
+ self, default_mock_concretization, mutable_database
+ ):
"""
Tests whether disabling patch_config_files
"""
- s = Spec("autotools-config-replacement ~patch_config_files +gnuconfig")
- s.concretize()
+ s = default_mock_concretization(
+ "autotools-config-replacement ~patch_config_files +gnuconfig"
+ )
s.package.do_install()
with open(os.path.join(s.prefix.broken, "config.sub")) as f:
@@ -252,29 +258,29 @@ spack:
@pytest.mark.usefixtures("config", "mock_packages")
class TestCMakePackage(object):
- def test_cmake_std_args(self):
+ def test_cmake_std_args(self, default_mock_concretization):
# Call the function on a CMakePackage instance
- s = Spec("cmake-client").concretized()
+ s = default_mock_concretization("cmake-client")
expected = spack.build_systems.cmake.CMakeBuilder.std_args(s.package)
assert s.package.builder.std_cmake_args == expected
# Call it on another kind of package
- s = Spec("mpich").concretized()
+ s = default_mock_concretization("mpich")
assert spack.build_systems.cmake.CMakeBuilder.std_args(s.package)
- def test_cmake_bad_generator(self, monkeypatch):
- s = Spec("cmake-client").concretized()
+ def test_cmake_bad_generator(self, monkeypatch, default_mock_concretization):
+ s = default_mock_concretization("cmake-client")
monkeypatch.setattr(type(s.package), "generator", "Yellow Sticky Notes", raising=False)
with pytest.raises(spack.package_base.InstallError):
s.package.builder.std_cmake_args
- def test_cmake_secondary_generator(config, mock_packages):
- s = Spec("cmake-client").concretized()
+ def test_cmake_secondary_generator(self, default_mock_concretization):
+ s = default_mock_concretization("cmake-client")
s.package.generator = "CodeBlocks - Unix Makefiles"
assert s.package.builder.std_cmake_args
- def test_define(self):
- s = Spec("cmake-client").concretized()
+ def test_define(self, default_mock_concretization):
+ s = default_mock_concretization("cmake-client")
define = s.package.define
for cls in (list, tuple):
@@ -324,8 +330,8 @@ class TestDownloadMixins(object):
),
],
)
- def test_attributes_defined(self, spec_str, expected_url):
- s = Spec(spec_str).concretized()
+ def test_attributes_defined(self, default_mock_concretization, spec_str, expected_url):
+ s = default_mock_concretization(spec_str)
assert s.package.urls[0] == expected_url
@pytest.mark.parametrize(
@@ -344,33 +350,33 @@ class TestDownloadMixins(object):
("mirror-xorg-broken", r"{0} must define a `xorg_mirror_path` attribute"),
],
)
- def test_attributes_missing(self, spec_str, error_fmt):
- s = Spec(spec_str).concretized()
+ def test_attributes_missing(self, default_mock_concretization, spec_str, error_fmt):
+ s = default_mock_concretization(spec_str)
error_msg = error_fmt.format(type(s.package).__name__)
with pytest.raises(AttributeError, match=error_msg):
s.package.urls
-def test_cmake_define_from_variant_conditional(config, mock_packages):
+def test_cmake_define_from_variant_conditional(default_mock_concretization):
"""Test that define_from_variant returns empty string when a condition on a variant
is not met. When this is the case, the variant is not set in the spec."""
- s = Spec("cmake-conditional-variants-test").concretized()
+ s = default_mock_concretization("cmake-conditional-variants-test")
assert "example" not in s.variants
assert s.package.define_from_variant("EXAMPLE", "example") == ""
-def test_autotools_args_from_conditional_variant(config, mock_packages):
+def test_autotools_args_from_conditional_variant(default_mock_concretization):
"""Test that _activate_or_not returns an empty string when a condition on a variant
is not met. When this is the case, the variant is not set in the spec."""
- s = Spec("autotools-conditional-variants-test").concretized()
+ s = default_mock_concretization("autotools-conditional-variants-test")
assert "example" not in s.variants
assert len(s.package.builder._activate_or_not("example", "enable", "disable")) == 0
-def test_autoreconf_search_path_args_multiple(config, mock_packages, tmpdir):
+def test_autoreconf_search_path_args_multiple(default_mock_concretization, tmpdir):
"""autoreconf should receive the right -I flags with search paths for m4 files
for build deps."""
- spec = Spec("dttop").concretized()
+ spec = default_mock_concretization("dttop")
aclocal_fst = str(tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal"))
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
@@ -384,11 +390,11 @@ def test_autoreconf_search_path_args_multiple(config, mock_packages, tmpdir):
]
-def test_autoreconf_search_path_args_skip_automake(config, mock_packages, tmpdir):
+def test_autoreconf_search_path_args_skip_automake(default_mock_concretization, tmpdir):
"""automake's aclocal dir should not be added as -I flag as it is a default
3rd party dir search path, and if it's a system version it usually includes
m4 files shadowing spack deps."""
- spec = Spec("dttop").concretized()
+ spec = default_mock_concretization("dttop")
tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal")
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
@@ -398,9 +404,9 @@ def test_autoreconf_search_path_args_skip_automake(config, mock_packages, tmpdir
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == ["-I", aclocal_snd]
-def test_autoreconf_search_path_args_external_order(config, mock_packages, tmpdir):
+def test_autoreconf_search_path_args_external_order(default_mock_concretization, tmpdir):
"""When a build dep is external, its -I flag should occur last"""
- spec = Spec("dttop").concretized()
+ spec = default_mock_concretization("dttop")
aclocal_fst = str(tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal"))
aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
@@ -414,18 +420,18 @@ def test_autoreconf_search_path_args_external_order(config, mock_packages, tmpdi
]
-def test_autoreconf_search_path_skip_nonexisting(config, mock_packages, tmpdir):
+def test_autoreconf_search_path_skip_nonexisting(default_mock_concretization, tmpdir):
"""Skip -I flags for non-existing directories"""
- spec = Spec("dttop").concretized()
+ spec = default_mock_concretization("dttop")
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.prefix = str(tmpdir.join("fst"))
build_dep_two.prefix = str(tmpdir.join("snd"))
assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == []
-def test_autoreconf_search_path_dont_repeat(config, mock_packages, tmpdir):
+def test_autoreconf_search_path_dont_repeat(default_mock_concretization, tmpdir):
"""Do not add the same -I flag twice to keep things readable for humans"""
- spec = Spec("dttop").concretized()
+ spec = default_mock_concretization("dttop")
aclocal = str(tmpdir.mkdir("prefix").mkdir("share").mkdir("aclocal"))
build_dep_one, build_dep_two = spec.dependencies(deptype="build")
build_dep_one.external_path = str(tmpdir.join("prefix"))
diff --git a/lib/spack/spack/test/ci.py b/lib/spack/spack/test/ci.py
index 2a4786d51b..a55f5841eb 100644
--- a/lib/spack/spack/test/ci.py
+++ b/lib/spack/spack/test/ci.py
@@ -18,7 +18,6 @@ import spack.config as cfg
import spack.environment as ev
import spack.error
import spack.paths as spack_paths
-import spack.spec as spec
import spack.util.gpg
import spack.util.spack_yaml as syaml
@@ -145,13 +144,12 @@ def test_download_and_extract_artifacts(tmpdir, monkeypatch, working_env):
ci.download_and_extract_artifacts(url, working_dir)
-def test_ci_copy_stage_logs_to_artifacts_fail(tmpdir, config, mock_packages, monkeypatch, capfd):
+def test_ci_copy_stage_logs_to_artifacts_fail(tmpdir, default_mock_concretization, capfd):
"""The copy will fail because the spec is not concrete so does not have
a package."""
log_dir = tmpdir.join("log_dir")
- s = spec.Spec("printing-package").concretized()
-
- ci.copy_stage_logs_to_artifacts(s, log_dir)
+ concrete_spec = default_mock_concretization("printing-package")
+ ci.copy_stage_logs_to_artifacts(concrete_spec, log_dir)
_, err = capfd.readouterr()
assert "Unable to copy files" in err
assert "No such file or directory" in err
@@ -456,17 +454,16 @@ def test_get_spec_filter_list(mutable_mock_env_path, config, mutable_mock_repo):
assert affected_pkg_names == expected_affected_pkg_names
-@pytest.mark.maybeslow
@pytest.mark.regression("29947")
-def test_affected_specs_on_first_concretization(mutable_mock_env_path, config):
+def test_affected_specs_on_first_concretization(mutable_mock_env_path, mock_packages, config):
e = ev.create("first_concretization")
- e.add("hdf5~mpi~szip")
- e.add("hdf5~mpi+szip")
+ e.add("mpileaks~shared")
+ e.add("mpileaks+shared")
e.concretize()
- affected_specs = spack.ci.get_spec_filter_list(e, ["zlib"])
- hdf5_specs = [s for s in affected_specs if s.name == "hdf5"]
- assert len(hdf5_specs) == 2
+ affected_specs = spack.ci.get_spec_filter_list(e, ["callpath"])
+ mpileaks_specs = [s for s in affected_specs if s.name == "mpileaks"]
+ assert len(mpileaks_specs) == 2, e.all_specs()
@pytest.mark.skipif(
@@ -515,14 +512,14 @@ def test_ci_create_buildcache(tmpdir, working_env, config, mock_packages, monkey
def test_ci_run_standalone_tests_missing_requirements(
- tmpdir, working_env, config, mock_packages, capfd
+ tmpdir, working_env, default_mock_concretization, capfd
):
"""This test case checks for failing prerequisite checks."""
ci.run_standalone_tests()
err = capfd.readouterr()[1]
assert "Job spec is required" in err
- args = {"job_spec": spec.Spec("printing-package").concretized()}
+ args = {"job_spec": default_mock_concretization("printing-package")}
ci.run_standalone_tests(**args)
err = capfd.readouterr()[1]
assert "Reproduction directory is required" in err
@@ -532,12 +529,12 @@ def test_ci_run_standalone_tests_missing_requirements(
sys.platform == "win32", reason="Reliance on bash script not supported on Windows"
)
def test_ci_run_standalone_tests_not_installed_junit(
- tmpdir, working_env, config, mock_packages, mock_test_stage, capfd
+ tmpdir, working_env, default_mock_concretization, mock_test_stage, capfd
):
log_file = tmpdir.join("junit.xml").strpath
args = {
"log_file": log_file,
- "job_spec": spec.Spec("printing-package").concretized(),
+ "job_spec": default_mock_concretization("printing-package"),
"repro_dir": tmpdir.join("repro_dir").strpath,
"fail_fast": True,
}
@@ -553,13 +550,13 @@ def test_ci_run_standalone_tests_not_installed_junit(
sys.platform == "win32", reason="Reliance on bash script not supported on Windows"
)
def test_ci_run_standalone_tests_not_installed_cdash(
- tmpdir, working_env, config, mock_packages, mock_test_stage, capfd
+ tmpdir, working_env, default_mock_concretization, mock_test_stage, capfd
):
"""Test run_standalone_tests with cdash and related options."""
log_file = tmpdir.join("junit.xml").strpath
args = {
"log_file": log_file,
- "job_spec": spec.Spec("printing-package").concretized(),
+ "job_spec": default_mock_concretization("printing-package"),
"repro_dir": tmpdir.join("repro_dir").strpath,
}
os.makedirs(args["repro_dir"])
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 6516c9c01f..c19c0c5528 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -1852,3 +1852,27 @@ def binary_with_rpaths(prefix_tmpdir):
return executable
return _factory
+
+
+@pytest.fixture(scope="session")
+def concretized_specs_cache():
+ """Cache for mock concrete specs"""
+ return {}
+
+
+@pytest.fixture
+def default_mock_concretization(config, mock_packages, concretized_specs_cache):
+ """Return the default mock concretization of a spec literal, obtained using the mock
+ repository and the mock configuration.
+
+ This fixture is unsafe to call in a test when either the default configuration or mock
+ repository are not used or have been modified.
+ """
+
+ def _func(spec_str, tests=False):
+ key = spec_str, tests
+ if key not in concretized_specs_cache:
+ concretized_specs_cache[key] = spack.spec.Spec(spec_str).concretized(tests=tests)
+ return concretized_specs_cache[key].copy()
+
+ return _func
diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py
index bd06e5eb2c..99e1b5c470 100644
--- a/lib/spack/spack/test/database.py
+++ b/lib/spack/spack/test/database.py
@@ -835,7 +835,7 @@ def test_clear_failure_keep(mutable_database, monkeypatch, capfd):
@pytest.mark.db
-def test_clear_failure_forced(mutable_database, monkeypatch, capfd):
+def test_clear_failure_forced(default_mock_concretization, mutable_database, monkeypatch, capfd):
"""Add test coverage for clear_failure operation when force."""
def _is(db, spec):
@@ -846,7 +846,7 @@ def test_clear_failure_forced(mutable_database, monkeypatch, capfd):
# Ensure raise OSError when try to remove the non-existent marking
monkeypatch.setattr(spack.database.Database, "prefix_failure_marked", _is)
- s = spack.spec.Spec("a").concretized()
+ s = default_mock_concretization("a")
spack.store.db.clear_failure(s, force=True)
out = capfd.readouterr()[1]
assert "Removing failure marking despite lock" in out
@@ -854,7 +854,7 @@ def test_clear_failure_forced(mutable_database, monkeypatch, capfd):
@pytest.mark.db
-def test_mark_failed(mutable_database, monkeypatch, tmpdir, capsys):
+def test_mark_failed(default_mock_concretization, mutable_database, monkeypatch, tmpdir, capsys):
"""Add coverage to mark_failed."""
def _raise_exc(lock):
@@ -864,7 +864,7 @@ def test_mark_failed(mutable_database, monkeypatch, tmpdir, capsys):
monkeypatch.setattr(lk.Lock, "acquire_write", _raise_exc)
with tmpdir.as_cwd():
- s = spack.spec.Spec("a").concretized()
+ s = default_mock_concretization("a")
spack.store.db.mark_failed(s)
out = str(capsys.readouterr()[1])
@@ -876,13 +876,13 @@ def test_mark_failed(mutable_database, monkeypatch, tmpdir, capsys):
@pytest.mark.db
-def test_prefix_failed(mutable_database, monkeypatch):
+def test_prefix_failed(default_mock_concretization, mutable_database, monkeypatch):
"""Add coverage to prefix_failed operation."""
def _is(db, spec):
return True
- s = spack.spec.Spec("a").concretized()
+ s = default_mock_concretization("a")
# Confirm the spec is not already marked as failed
assert not spack.store.db.prefix_failed(s)
@@ -900,13 +900,13 @@ def test_prefix_failed(mutable_database, monkeypatch):
assert spack.store.db.prefix_failed(s)
-def test_prefix_read_lock_error(mutable_database, monkeypatch):
+def test_prefix_read_lock_error(default_mock_concretization, mutable_database, monkeypatch):
"""Cover the prefix read lock exception."""
def _raise(db, spec):
raise lk.LockError("Mock lock error")
- s = spack.spec.Spec("a").concretized()
+ s = default_mock_concretization("a")
# Ensure subsequent lock operations fail
monkeypatch.setattr(lk.Lock, "acquire_read", _raise)
@@ -916,13 +916,13 @@ def test_prefix_read_lock_error(mutable_database, monkeypatch):
assert False
-def test_prefix_write_lock_error(mutable_database, monkeypatch):
+def test_prefix_write_lock_error(default_mock_concretization, mutable_database, monkeypatch):
"""Cover the prefix write lock exception."""
def _raise(db, spec):
raise lk.LockError("Mock lock error")
- s = spack.spec.Spec("a").concretized()
+ s = default_mock_concretization("a")
# Ensure subsequent lock operations fail
monkeypatch.setattr(lk.Lock, "acquire_write", _raise)
diff --git a/lib/spack/spack/test/directory_layout.py b/lib/spack/spack/test/directory_layout.py
index 32e0a340c6..86d160c5cc 100644
--- a/lib/spack/spack/test/directory_layout.py
+++ b/lib/spack/spack/test/directory_layout.py
@@ -24,11 +24,10 @@ from spack.util.path import path_to_os_path
max_packages = 10
-def test_yaml_directory_layout_parameters(tmpdir, config):
+def test_yaml_directory_layout_parameters(tmpdir, default_mock_concretization):
"""This tests the various parameters that can be used to configure
the install location"""
- spec = Spec("python")
- spec.concretize()
+ spec = default_mock_concretization("python")
# Ensure default layout matches expected spec format
layout_default = DirectoryLayout(str(tmpdir))
@@ -215,11 +214,9 @@ def test_find(temporary_store, config, mock_packages):
assert found_specs[name].eq_dag(spec)
-def test_yaml_directory_layout_build_path(tmpdir, config):
+def test_yaml_directory_layout_build_path(tmpdir, default_mock_concretization):
"""This tests build path method."""
- spec = Spec("python")
- spec.concretize()
-
+ spec = default_mock_concretization("python")
layout = DirectoryLayout(str(tmpdir))
rel_path = os.path.join(layout.metadata_dir, layout.packages_dir)
assert layout.build_packages_path(spec) == os.path.join(spec.prefix, rel_path)
diff --git a/lib/spack/spack/test/git_fetch.py b/lib/spack/spack/test/git_fetch.py
index 0f9f587421..678a30a4fd 100644
--- a/lib/spack/spack/test/git_fetch.py
+++ b/lib/spack/spack/test/git_fetch.py
@@ -83,7 +83,13 @@ def test_bad_git(tmpdir, mock_bad_git):
@pytest.mark.parametrize("type_of_test", ["default", "branch", "tag", "commit"])
@pytest.mark.parametrize("secure", [True, False])
def test_fetch(
- type_of_test, secure, mock_git_repository, config, mutable_mock_repo, git_version, monkeypatch
+ type_of_test,
+ secure,
+ mock_git_repository,
+ default_mock_concretization,
+ mutable_mock_repo,
+ git_version,
+ monkeypatch,
):
"""Tries to:
@@ -104,7 +110,7 @@ def test_fetch(
monkeypatch.delattr(pkg_class, "git")
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
monkeypatch.setitem(s.package.versions, ver("git"), t.args)
# Enter the stage directory and check some properties
@@ -136,7 +142,7 @@ def test_fetch(
@pytest.mark.disable_clean_stage_check
def test_fetch_pkg_attr_submodule_init(
- mock_git_repository, config, mutable_mock_repo, monkeypatch, mock_stage
+ mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch, mock_stage
):
"""In this case the version() args do not contain a 'git' URL, so
the fetcher must be assembled using the Package-level 'git' attribute.
@@ -151,7 +157,7 @@ def test_fetch_pkg_attr_submodule_init(
monkeypatch.setattr(pkg_class, "git", mock_git_repository.url)
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
monkeypatch.setitem(s.package.versions, ver("git"), t.args)
s.package.do_stage()
@@ -193,13 +199,15 @@ def test_adhoc_version_submodules(
@pytest.mark.parametrize("type_of_test", ["branch", "commit"])
-def test_debug_fetch(mock_packages, type_of_test, mock_git_repository, config, monkeypatch):
+def test_debug_fetch(
+ mock_packages, type_of_test, mock_git_repository, default_mock_concretization, monkeypatch
+):
"""Fetch the repo with debug enabled."""
# Retrieve the right test parameters
t = mock_git_repository.checks[type_of_test]
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
monkeypatch.setitem(s.package.versions, ver("git"), t.args)
# Fetch then ensure source path exists
@@ -231,7 +239,12 @@ def test_needs_stage():
@pytest.mark.parametrize("get_full_repo", [True, False])
def test_get_full_repo(
- get_full_repo, git_version, mock_git_repository, config, mutable_mock_repo, monkeypatch
+ get_full_repo,
+ git_version,
+ mock_git_repository,
+ default_mock_concretization,
+ mutable_mock_repo,
+ monkeypatch,
):
"""Ensure that we can clone a full repository."""
@@ -243,7 +256,7 @@ def test_get_full_repo(
t = mock_git_repository.checks[type_of_test]
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
args = copy.copy(t.args)
args["get_full_repo"] = get_full_repo
monkeypatch.setitem(s.package.versions, ver("git"), args)
@@ -273,7 +286,9 @@ def test_get_full_repo(
@pytest.mark.disable_clean_stage_check
@pytest.mark.parametrize("submodules", [True, False])
-def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo, monkeypatch):
+def test_gitsubmodule(
+ submodules, mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
+):
"""
Test GitFetchStrategy behavior with submodules. This package
has a `submodules` property which is always True: when a specific
@@ -286,7 +301,7 @@ def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo
t = mock_git_repository.checks[type_of_test]
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
args = copy.copy(t.args)
args["submodules"] = submodules
monkeypatch.setitem(s.package.versions, ver("git"), args)
@@ -304,7 +319,9 @@ def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo
@pytest.mark.disable_clean_stage_check
-def test_gitsubmodules_callable(mock_git_repository, config, mutable_mock_repo, monkeypatch):
+def test_gitsubmodules_callable(
+ mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
+):
"""
Test GitFetchStrategy behavior with submodules selected after concretization
"""
@@ -317,7 +334,7 @@ def test_gitsubmodules_callable(mock_git_repository, config, mutable_mock_repo,
t = mock_git_repository.checks[type_of_test]
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
args = copy.copy(t.args)
args["submodules"] = submodules_callback
monkeypatch.setitem(s.package.versions, ver("git"), args)
@@ -330,7 +347,9 @@ def test_gitsubmodules_callable(mock_git_repository, config, mutable_mock_repo,
@pytest.mark.disable_clean_stage_check
-def test_gitsubmodules_delete(mock_git_repository, config, mutable_mock_repo, monkeypatch):
+def test_gitsubmodules_delete(
+ mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
+):
"""
Test GitFetchStrategy behavior with submodules_delete
"""
@@ -338,7 +357,7 @@ def test_gitsubmodules_delete(mock_git_repository, config, mutable_mock_repo, mo
t = mock_git_repository.checks[type_of_test]
# Construct the package under test
- s = Spec("git-test").concretized()
+ s = default_mock_concretization("git-test")
args = copy.copy(t.args)
args["submodules"] = True
args["submodules_delete"] = ["third_party/submodule0", "third_party/submodule1"]
diff --git a/lib/spack/spack/test/packaging.py b/lib/spack/spack/test/packaging.py
index f0294f5a74..f889cd5384 100644
--- a/lib/spack/spack/test/packaging.py
+++ b/lib/spack/spack/test/packaging.py
@@ -570,7 +570,9 @@ def mock_download():
"manual,instr", [(False, False), (False, True), (True, False), (True, True)]
)
@pytest.mark.disable_clean_stage_check
-def test_manual_download(install_mockery, mock_download, monkeypatch, manual, instr):
+def test_manual_download(
+ install_mockery, mock_download, default_mock_concretization, monkeypatch, manual, instr
+):
"""
Ensure expected fetcher fail message based on manual download and instr.
"""
@@ -579,7 +581,7 @@ def test_manual_download(install_mockery, mock_download, monkeypatch, manual, in
def _instr(pkg):
return "Download instructions for {0}".format(pkg.spec.name)
- spec = Spec("a").concretized()
+ spec = default_mock_concretization("a")
pkg = spec.package
pkg.manual_download = manual
@@ -605,16 +607,20 @@ def fetching_not_allowed(monkeypatch):
monkeypatch.setattr(spack.package_base.PackageBase, "fetcher", fetcher)
-def test_fetch_without_code_is_noop(install_mockery, fetching_not_allowed):
+def test_fetch_without_code_is_noop(
+ default_mock_concretization, install_mockery, fetching_not_allowed
+):
"""do_fetch for packages without code should be a no-op"""
- pkg = Spec("a").concretized().package
+ pkg = default_mock_concretization("a").package
pkg.has_code = False
pkg.do_fetch()
-def test_fetch_external_package_is_noop(install_mockery, fetching_not_allowed):
+def test_fetch_external_package_is_noop(
+ default_mock_concretization, install_mockery, fetching_not_allowed
+):
"""do_fetch for packages without code should be a no-op"""
- spec = Spec("a").concretized()
+ spec = default_mock_concretization("a")
spec.external_path = "/some/where"
assert spec.external
spec.package.do_fetch()
diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py
index 04aa82797c..e2cbf706da 100644
--- a/lib/spack/spack/test/spec_semantics.py
+++ b/lib/spack/spack/test/spec_semantics.py
@@ -719,9 +719,8 @@ class TestSpecSematics(object):
with pytest.raises(ValueError):
Spec("libelf foo")
- def test_spec_formatting(self):
- spec = Spec("multivalue-variant cflags=-O2")
- spec.concretize()
+ def test_spec_formatting(self, default_mock_concretization):
+ spec = default_mock_concretization("multivalue-variant cflags=-O2")
# Since the default is the full spec see if the string rep of
# spec is the same as the output of spec.format()
@@ -797,9 +796,8 @@ class TestSpecSematics(object):
actual = spec.format(named_str)
assert expected == actual
- def test_spec_formatting_escapes(self):
- spec = Spec("multivalue-variant cflags=-O2")
- spec.concretize()
+ def test_spec_formatting_escapes(self, default_mock_concretization):
+ spec = default_mock_concretization("multivalue-variant cflags=-O2")
sigil_mismatches = [
"{@name}",
@@ -881,7 +879,7 @@ class TestSpecSematics(object):
# different orderings for repeated concretizations of the same
# spec and config
spec_str = "libelf %gcc@11.1.0 os=redhat6"
- for _ in range(25):
+ for _ in range(3):
s = Spec(spec_str).concretized()
assert all(
s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags")
@@ -954,13 +952,11 @@ class TestSpecSematics(object):
assert spec.target < "broadwell"
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice(self, transitive):
+ def test_splice(self, transitive, default_mock_concretization):
# Tests the new splice function in Spec using a somewhat simple case
# with a variant with a conditional dependency.
- spec = Spec("splice-t")
- dep = Spec("splice-h+foo")
- spec.concretize()
- dep.concretize()
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
# Sanity checking that these are not the same thing.
assert dep.dag_hash() != spec["splice-h"].dag_hash()
@@ -993,11 +989,9 @@ class TestSpecSematics(object):
assert out.spliced
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_with_cached_hashes(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-h+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_with_cached_hashes(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
# monkeypatch hashes so we can test that they are cached
spec._hash = "aaaaaa"
@@ -1014,9 +1008,9 @@ class TestSpecSematics(object):
assert out["splice-z"].dag_hash() == out_z_expected.dag_hash()
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_input_unchanged(self, transitive):
- spec = Spec("splice-t").concretized()
- dep = Spec("splice-h+foo").concretized()
+ def test_splice_input_unchanged(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
orig_spec_hash = spec.dag_hash()
orig_dep_hash = dep.dag_hash()
spec.splice(dep, transitive)
@@ -1026,16 +1020,13 @@ class TestSpecSematics(object):
assert dep.dag_hash() == orig_dep_hash
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_subsequent(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-h+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_subsequent(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
out = spec.splice(dep, transitive)
# Now we attempt a second splice.
- dep = Spec("splice-z+bar")
- dep.concretize()
+ dep = default_mock_concretization("splice-z+bar")
# Transitivity shouldn't matter since Splice Z has no dependencies.
out2 = out.splice(dep, transitive)
@@ -1046,11 +1037,9 @@ class TestSpecSematics(object):
assert out2.spliced
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_dict(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-h+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_dict(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
out = spec.splice(dep, transitive)
# Sanity check all hashes are unique...
@@ -1065,11 +1054,9 @@ class TestSpecSematics(object):
assert len(build_spec_nodes) == 1
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_dict_roundtrip(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-h+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_dict_roundtrip(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-h+foo")
out = spec.splice(dep, transitive)
# Sanity check all hashes are unique...
@@ -1132,21 +1119,17 @@ class TestSpecSematics(object):
assert s.satisfies("mpileaks ^zmpi ^fake", strict=True)
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_swap_names(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-a+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_swap_names(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-a+foo")
out = spec.splice(dep, transitive)
assert dep.name in out
assert transitive == ("+foo" in out["splice-z"])
@pytest.mark.parametrize("transitive", [True, False])
- def test_splice_swap_names_mismatch_virtuals(self, transitive):
- spec = Spec("splice-t")
- dep = Spec("splice-vh+foo")
- spec.concretize()
- dep.concretize()
+ def test_splice_swap_names_mismatch_virtuals(self, default_mock_concretization, transitive):
+ spec = default_mock_concretization("splice-t")
+ dep = default_mock_concretization("splice-vh+foo")
with pytest.raises(spack.spec.SpliceError, match="will not provide the same virtuals."):
spec.splice(dep, transitive)
@@ -1166,12 +1149,11 @@ class TestSpecSematics(object):
@pytest.mark.regression("3887")
-@pytest.mark.parametrize("spec_str", ["git", "hdf5", "py-flake8"])
-def test_is_extension_after_round_trip_to_dict(config, spec_str):
+@pytest.mark.parametrize("spec_str", ["py-extension2", "extension1", "perl-extension"])
+def test_is_extension_after_round_trip_to_dict(config, mock_packages, spec_str):
# x is constructed directly from string, y from a
# round-trip to dict representation
- x = Spec(spec_str)
- x.concretize()
+ x = Spec(spec_str).concretized()
y = Spec.from_dict(x.to_dict())
# Using 'y' since the round-trip make us lose build dependencies
@@ -1231,7 +1213,7 @@ def test_merge_anonymous_spec_with_named_spec(anonymous, named, expected):
assert s == Spec(expected)
-def test_spec_installed(install_mockery, database):
+def test_spec_installed(default_mock_concretization, database):
"""Test whether Spec.installed works."""
# a known installed spec should say that it's installed
specs = database.query()
@@ -1244,14 +1226,14 @@ def test_spec_installed(install_mockery, database):
assert not spec.installed
# 'a' is not in the mock DB and is not installed
- spec = Spec("a").concretized()
+ spec = default_mock_concretization("a")
assert not spec.installed
@pytest.mark.regression("30678")
-def test_call_dag_hash_on_old_dag_hash_spec(mock_packages, config):
+def test_call_dag_hash_on_old_dag_hash_spec(mock_packages, default_mock_concretization):
# create a concrete spec
- a = Spec("a").concretized()
+ a = default_mock_concretization("a")
dag_hashes = {spec.name: spec.dag_hash() for spec in a.traverse()}
# make it look like an old DAG hash spec with no package hash on the spec.
@@ -1298,9 +1280,9 @@ def test_unsupported_compiler():
Spec("gcc%fake-compiler").validate_or_raise()
-def test_package_hash_affects_dunder_and_dag_hash(mock_packages, config):
- a1 = Spec("a").concretized()
- a2 = Spec("a").concretized()
+def test_package_hash_affects_dunder_and_dag_hash(mock_packages, default_mock_concretization):
+ a1 = default_mock_concretization("a")
+ a2 = default_mock_concretization("a")
assert hash(a1) == hash(a2)
assert a1.dag_hash() == a2.dag_hash()
diff --git a/lib/spack/spack/test/url_fetch.py b/lib/spack/spack/test/url_fetch.py
index da13611585..024974c132 100644
--- a/lib/spack/spack/test/url_fetch.py
+++ b/lib/spack/spack/test/url_fetch.py
@@ -136,18 +136,22 @@ if sys.platform != "win32":
@pytest.mark.parametrize("secure", [True, False])
@pytest.mark.parametrize("_fetch_method", ["curl", "urllib"])
@pytest.mark.parametrize("mock_archive", files, indirect=True)
-def test_fetch(mock_archive, secure, _fetch_method, checksum_type, config, mutable_mock_repo):
+def test_fetch(
+ mock_archive,
+ secure,
+ _fetch_method,
+ checksum_type,
+ default_mock_concretization,
+ mutable_mock_repo,
+):
"""Fetch an archive and make sure we can checksum it."""
- mock_archive.url
- mock_archive.path
-
algo = crypto.hash_fun_for_algo(checksum_type)()
with open(mock_archive.archive_file, "rb") as f:
algo.update(f.read())
checksum = algo.hexdigest()
- # Get a spec and tweak the test package with new chcecksum params
- s = Spec("url-test").concretized()
+ # Get a spec and tweak the test package with new checksum params
+ s = default_mock_concretization("url-test")
s.package.url = mock_archive.url
s.package.versions[ver("test")] = {checksum_type: checksum, "url": s.package.url}