unit-tests: fix most unit tests to account for the new model

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
Massimiliano Culpo 2024-11-11 13:17:18 +01:00
parent f79354c312
commit 28d42eed5e
No known key found for this signature in database
GPG Key ID: 3E52BB992233066C
47 changed files with 716 additions and 690 deletions

View File

@ -15,6 +15,7 @@
from llnl.util.lang import classproperty, memoized from llnl.util.lang import classproperty, memoized
import spack.compilers.libraries import spack.compilers.libraries
import spack.config
import spack.package_base import spack.package_base
import spack.paths import spack.paths
import spack.util.executable import spack.util.executable

View File

@ -21,7 +21,7 @@
from spack.error import SpackError from spack.error import SpackError
default_projections = { default_projections = {
"all": "{architecture}/{compiler.name}-{compiler.version}/{name}-{version}-{hash}" "all": "{architecture.platform}/{architecture.target}/{name}-{version}-{hash}"
} }

View File

@ -86,7 +86,6 @@
import spack import spack
import spack.compilers.flags import spack.compilers.flags
import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.hash_types as ht import spack.hash_types as ht

View File

@ -11,7 +11,7 @@
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
from spack.installer import PackageInstaller from spack.installer import PackageInstaller
from spack.solver.asp import SolverError from spack.solver.asp import SolverError, UnsatisfiableSpecError
from spack.spec import Spec from spack.spec import Spec
@ -65,7 +65,7 @@ def test_splice_installed_hash(install_specs, mutable_config):
mutable_config.set("packages", packages_config) mutable_config.set("packages", packages_config)
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0" goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0"
with pytest.raises(SolverError): with pytest.raises(UnsatisfiableSpecError):
spack.concretize.concretize_one(goal_spec) spack.concretize.concretize_one(goal_spec)
_enable_splicing() _enable_splicing()
concrete = spack.concretize.concretize_one(goal_spec) concrete = spack.concretize.concretize_one(goal_spec)
@ -87,7 +87,7 @@ def test_splice_build_splice_node(install_specs, mutable_config):
mutable_config.set("packages", _make_specs_non_buildable(["splice-t"])) mutable_config.set("packages", _make_specs_non_buildable(["splice-t"]))
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0+compat" goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0+compat"
with pytest.raises(SolverError): with pytest.raises(UnsatisfiableSpecError):
spack.concretize.concretize_one(goal_spec) spack.concretize.concretize_one(goal_spec)
_enable_splicing() _enable_splicing()
@ -113,7 +113,7 @@ def test_double_splice(install_specs, mutable_config):
mutable_config.set("packages", _make_specs_non_buildable(["splice-t", "splice-h", "splice-z"])) mutable_config.set("packages", _make_specs_non_buildable(["splice-t", "splice-h", "splice-z"]))
goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.2+compat" goal_spec = "splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.2+compat"
with pytest.raises(SolverError): with pytest.raises(UnsatisfiableSpecError):
spack.concretize.concretize_one(goal_spec) spack.concretize.concretize_one(goal_spec)
_enable_splicing() _enable_splicing()
@ -202,7 +202,7 @@ def test_manyvariant_matching_variant_splice(
original = install_specs(original_spec)[0] original = install_specs(original_spec)[0]
mutable_config.set("packages", {"depends-on-manyvariants": {"buildable": False}}) mutable_config.set("packages", {"depends-on-manyvariants": {"buildable": False}})
with pytest.raises(SolverError): with pytest.raises((UnsatisfiableSpecError, SolverError)):
spack.concretize.concretize_one(goal_spec) spack.concretize.concretize_one(goal_spec)
_enable_splicing() _enable_splicing()

View File

@ -150,10 +150,7 @@ def install_dir_non_default_layout(tmpdir):
"""Hooks a fake install directory with a non-default layout""" """Hooks a fake install directory with a non-default layout"""
opt_dir = tmpdir.join("opt") opt_dir = tmpdir.join("opt")
original_store, spack.store.STORE = spack.store.STORE, spack.store.Store( original_store, spack.store.STORE = spack.store.STORE, spack.store.Store(
str(opt_dir), str(opt_dir), projections={"all": "{name}-{version}-{hash:4}"}
projections={
"all": "{name}/{version}/{architecture}-{compiler.name}-{compiler.version}-{hash}"
},
) )
try: try:
yield spack.store yield spack.store
@ -389,7 +386,7 @@ def test_spec_needs_rebuild(monkeypatch, tmpdir):
s = spack.concretize.concretize_one("libdwarf") s = spack.concretize.concretize_one("libdwarf")
# Install a package # Install a package
install_cmd(s.name) install_cmd("--fake", s.name)
# Put installed package in the buildcache # Put installed package in the buildcache
buildcache_cmd("push", "-u", mirror_dir.strpath, s.name) buildcache_cmd("push", "-u", mirror_dir.strpath, s.name)
@ -418,7 +415,7 @@ def test_generate_index_missing(monkeypatch, tmpdir, mutable_config):
s = spack.concretize.concretize_one("libdwarf") s = spack.concretize.concretize_one("libdwarf")
# Install a package # Install a package
install_cmd("--no-cache", s.name) install_cmd("--fake", "--no-cache", s.name)
# Create a buildcache and update index # Create a buildcache and update index
buildcache_cmd("push", "-u", mirror_dir.strpath, s.name) buildcache_cmd("push", "-u", mirror_dir.strpath, s.name)
@ -542,11 +539,8 @@ def test_install_legacy_buildcache_layout(mutable_config, compiler_factory, inst
where the .spack file contained a repeated spec.json and another where the .spack file contained a repeated spec.json and another
compressed archive file containing the install tree. This test compressed archive file containing the install tree. This test
makes sure we can still read that layout.""" makes sure we can still read that layout."""
mutable_config.set(
"compilers", [compiler_factory(spec="gcc@4.5.0", operating_system="debian6")]
)
legacy_layout_dir = os.path.join(test_path, "data", "mirrors", "legacy_layout") legacy_layout_dir = os.path.join(test_path, "data", "mirrors", "legacy_layout")
mirror_url = "file://{0}".format(legacy_layout_dir) mirror_url = f"file://{legacy_layout_dir}"
filename = ( filename = (
"test-debian6-core2-gcc-4.5.0-archive-files-2.0-" "test-debian6-core2-gcc-4.5.0-archive-files-2.0-"
"l3vdiqvbobmspwyb4q2b62fz6nitd4hk.spec.json" "l3vdiqvbobmspwyb4q2b62fz6nitd4hk.spec.json"
@ -555,9 +549,7 @@ def test_install_legacy_buildcache_layout(mutable_config, compiler_factory, inst
mirror_cmd("add", "--scope", "site", "test-legacy-layout", mirror_url) mirror_cmd("add", "--scope", "site", "test-legacy-layout", mirror_url)
output = install_cmd("--no-check-signature", "--cache-only", "-f", spec_json_path, output=str) output = install_cmd("--no-check-signature", "--cache-only", "-f", spec_json_path, output=str)
mirror_cmd("rm", "--scope=site", "test-legacy-layout") mirror_cmd("rm", "--scope=site", "test-legacy-layout")
expect_line = ( expect_line = "Extracting archive-files-2.0-l3vdiqvbobmspwyb4q2b62fz6nitd4hk from binary cache"
"Extracting archive-files-2.0-" "l3vdiqvbobmspwyb4q2b62fz6nitd4hk from binary cache"
)
assert expect_line in output assert expect_line in output
@ -1131,10 +1123,11 @@ def test_get_valid_spec_file_no_json(tmp_path, filename):
bindist._get_valid_spec_file(str(tmp_path / filename), max_supported_layout=1) bindist._get_valid_spec_file(str(tmp_path / filename), max_supported_layout=1)
def test_download_tarball_with_unsupported_layout_fails(tmp_path, mutable_config, capsys): def test_download_tarball_with_unsupported_layout_fails(
tmp_path, mock_packages, mutable_config, capsys
):
layout_version = bindist.CURRENT_BUILD_CACHE_LAYOUT_VERSION + 1 layout_version = bindist.CURRENT_BUILD_CACHE_LAYOUT_VERSION + 1
spec = Spec("gmake@4.4.1%gcc@13.1.0 arch=linux-ubuntu23.04-zen2") spec = spack.concretize.concretize_one("pkg-c")
spec._mark_concrete()
spec_dict = spec.to_dict() spec_dict = spec.to_dict()
spec_dict["buildcache_layout_version"] = layout_version spec_dict["buildcache_layout_version"] = layout_version

View File

@ -13,6 +13,8 @@
import spack.store import spack.store
import spack.util.path import spack.util.path
from .conftest import _true
@pytest.fixture @pytest.fixture
def active_mock_environment(mutable_config, mutable_mock_env_path): def active_mock_environment(mutable_config, mutable_mock_env_path):
@ -93,12 +95,14 @@ def test_raising_exception_if_bootstrap_disabled(mutable_config):
spack.bootstrap.config.store_path() spack.bootstrap.config.store_path()
def test_raising_exception_module_importable(): def test_raising_exception_module_importable(config, monkeypatch):
monkeypatch.setattr(spack.bootstrap.core, "source_is_enabled", _true)
with pytest.raises(ImportError, match='cannot bootstrap the "asdf" Python module'): with pytest.raises(ImportError, match='cannot bootstrap the "asdf" Python module'):
spack.bootstrap.core.ensure_module_importable_or_raise("asdf") spack.bootstrap.core.ensure_module_importable_or_raise("asdf")
def test_raising_exception_executables_in_path(): def test_raising_exception_executables_in_path(config, monkeypatch):
monkeypatch.setattr(spack.bootstrap.core, "source_is_enabled", _true)
with pytest.raises(RuntimeError, match="cannot bootstrap any of the asdf, fdsa executables"): with pytest.raises(RuntimeError, match="cannot bootstrap any of the asdf, fdsa executables"):
spack.bootstrap.core.ensure_executables_in_path_or_raise(["asdf", "fdsa"], "python") spack.bootstrap.core.ensure_executables_in_path_or_raise(["asdf", "fdsa"], "python")
@ -218,12 +222,10 @@ def test_source_is_disabled(mutable_config):
# Get the configuration dictionary of the current bootstrapping source # Get the configuration dictionary of the current bootstrapping source
conf = next(iter(spack.bootstrap.core.bootstrapping_sources())) conf = next(iter(spack.bootstrap.core.bootstrapping_sources()))
# The source is not explicitly enabled or disabled, so the following # The source is not explicitly enabled or disabled, so the following should return False
# call should raise to skip using it for bootstrapping
assert not spack.bootstrap.core.source_is_enabled(conf) assert not spack.bootstrap.core.source_is_enabled(conf)
# Try to explicitly disable the source and verify that the behavior # Try to explicitly disable the source and verify that the behavior is the same as above
# is the same as above
spack.config.add("bootstrap:trusted:{0}:{1}".format(conf["name"], False)) spack.config.add("bootstrap:trusted:{0}:{1}".format(conf["name"], False))
assert not spack.bootstrap.core.source_is_enabled(conf) assert not spack.bootstrap.core.source_is_enabled(conf)

View File

@ -4,7 +4,6 @@
import os import os
import platform import platform
import posixpath import posixpath
import sys
import pytest import pytest
@ -14,8 +13,6 @@
from llnl.util.filesystem import HeaderList, LibraryList from llnl.util.filesystem import HeaderList, LibraryList
import spack.build_environment import spack.build_environment
import spack.compiler
import spack.compilers
import spack.concretize import spack.concretize
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
@ -97,7 +94,7 @@ def build_environment(working_env):
@pytest.fixture @pytest.fixture
def ensure_env_variables(config, mock_packages, monkeypatch, working_env): def ensure_env_variables(mutable_config, mock_packages, monkeypatch, working_env):
"""Returns a function that takes a dictionary and updates os.environ """Returns a function that takes a dictionary and updates os.environ
for the test lifetime accordingly. Plugs-in mock config and repo. for the test lifetime accordingly. Plugs-in mock config and repo.
""" """
@ -162,19 +159,24 @@ def test_static_to_shared_library(build_environment):
@pytest.mark.regression("8345") @pytest.mark.regression("8345")
@pytest.mark.usefixtures("config", "mock_packages") @pytest.mark.usefixtures("mock_packages")
def test_cc_not_changed_by_modules(monkeypatch, working_env): @pytest.mark.not_on_windows("Module files are not supported on Windows")
s = spack.concretize.concretize_one("cmake") def test_cc_not_changed_by_modules(monkeypatch, mutable_config, working_env, compiler_factory):
pkg = s.package """Tests that external module files that are loaded cannot change the
CC environment variable.
"""
gcc_entry = compiler_factory(spec="gcc@14.0.1 languages=c,c++")
gcc_entry["modules"] = ["some_module"]
mutable_config.set("packages", {"gcc": {"externals": [gcc_entry]}})
def _set_wrong_cc(x): def _set_wrong_cc(x):
os.environ["CC"] = "NOT_THIS_PLEASE" os.environ["CC"] = "NOT_THIS_PLEASE"
os.environ["ANOTHER_VAR"] = "THIS_IS_SET" os.environ["ANOTHER_VAR"] = "THIS_IS_SET"
monkeypatch.setattr(spack.build_environment, "load_module", _set_wrong_cc) monkeypatch.setattr(spack.build_environment, "load_module", _set_wrong_cc)
monkeypatch.setattr(pkg.compiler, "modules", ["some_module"])
spack.build_environment.setup_package(pkg, False) s = spack.concretize.concretize_one("cmake %gcc@14")
spack.build_environment.setup_package(s.package, dirty=False)
assert os.environ["CC"] != "NOT_THIS_PLEASE" assert os.environ["CC"] != "NOT_THIS_PLEASE"
assert os.environ["ANOTHER_VAR"] == "THIS_IS_SET" assert os.environ["ANOTHER_VAR"] == "THIS_IS_SET"
@ -185,7 +187,7 @@ def test_setup_dependent_package_inherited_modules(
): ):
# This will raise on regression # This will raise on regression
s = spack.concretize.concretize_one("cmake-client-inheritor") s = spack.concretize.concretize_one("cmake-client-inheritor")
PackageInstaller([s.package]).install() PackageInstaller([s.package], fake=True).install()
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -265,22 +267,30 @@ def test_setup_dependent_package_inherited_modules(
], ],
) )
def test_compiler_config_modifications( def test_compiler_config_modifications(
initial, modifications, expected, ensure_env_variables, monkeypatch initial,
modifications,
expected,
ensure_env_variables,
compiler_factory,
mutable_config,
monkeypatch,
): ):
# Set the environment as per prerequisites # Set the environment as per prerequisites
ensure_env_variables(initial) ensure_env_variables(initial)
gcc_entry = compiler_factory(spec="gcc@14.0.1 languages=c,c++")
gcc_entry["extra_attributes"]["environment"] = modifications
mutable_config.set("packages", {"gcc": {"externals": [gcc_entry]}})
def platform_pathsep(pathlist): def platform_pathsep(pathlist):
if Path.platform_path == Path.windows: if Path.platform_path == Path.windows:
pathlist = pathlist.replace(":", ";") pathlist = pathlist.replace(":", ";")
return convert_to_platform_path(pathlist) return convert_to_platform_path(pathlist)
# Monkeypatch a pkg.compiler.environment with the required modifications pkg = spack.concretize.concretize_one("cmake %gcc@14").package
pkg = spack.concretize.concretize_one("cmake").package
monkeypatch.setattr(pkg.compiler, "environment", modifications)
# Trigger the modifications # Trigger the modifications
spack.build_environment.setup_package(pkg, False) spack.build_environment.setup_package(pkg, dirty=False)
# Check they were applied # Check they were applied
for name, value in expected.items(): for name, value in expected.items():
@ -291,25 +301,6 @@ def platform_pathsep(pathlist):
assert name not in os.environ assert name not in os.environ
def test_compiler_custom_env(config, mock_packages, monkeypatch, working_env):
if sys.platform == "win32":
test_path = r"C:\test\path\element\custom-env" + "\\"
else:
test_path = r"/test/path/element/custom-env/"
def custom_env(pkg, env):
env.prepend_path("PATH", test_path)
env.append_flags("ENV_CUSTOM_CC_FLAGS", "--custom-env-flag1")
pkg = spack.concretize.concretize_one("cmake").package
monkeypatch.setattr(pkg.compiler, "setup_custom_environment", custom_env)
spack.build_environment.setup_package(pkg, False)
# Note: trailing slash may be stripped by internal logic
assert test_path[:-1] in os.environ["PATH"]
assert "--custom-env-flag1" in os.environ["ENV_CUSTOM_CC_FLAGS"]
def test_external_config_env(mock_packages, mutable_config, working_env): def test_external_config_env(mock_packages, mutable_config, working_env):
cmake_config = { cmake_config = {
"externals": [ "externals": [
@ -329,24 +320,27 @@ def test_external_config_env(mock_packages, mutable_config, working_env):
@pytest.mark.regression("9107") @pytest.mark.regression("9107")
def test_spack_paths_before_module_paths(config, mock_packages, monkeypatch, working_env): @pytest.mark.not_on_windows("Windows does not support module files")
s = spack.concretize.concretize_one("cmake") def test_spack_paths_before_module_paths(
pkg = s.package mutable_config, mock_packages, compiler_factory, monkeypatch, working_env
):
gcc_entry = compiler_factory(spec="gcc@14.0.1 languages=c,c++")
gcc_entry["modules"] = ["some_module"]
mutable_config.set("packages", {"gcc": {"externals": [gcc_entry]}})
module_path = os.path.join("path", "to", "module") module_path = os.path.join("path", "to", "module")
spack_path = os.path.join(spack.paths.prefix, os.path.join("lib", "spack", "env"))
def _set_wrong_cc(x): def _set_wrong_cc(x):
os.environ["PATH"] = module_path + os.pathsep + os.environ["PATH"] os.environ["PATH"] = module_path + os.pathsep + os.environ["PATH"]
monkeypatch.setattr(spack.build_environment, "load_module", _set_wrong_cc) monkeypatch.setattr(spack.build_environment, "load_module", _set_wrong_cc)
monkeypatch.setattr(pkg.compiler, "modules", ["some_module"])
spack.build_environment.setup_package(pkg, False) s = spack.concretize.concretize_one("cmake")
spack_path = os.path.join(spack.paths.prefix, os.path.join("lib", "spack", "env")) spack.build_environment.setup_package(s.package, dirty=False)
paths = os.environ["PATH"].split(os.pathsep) paths = os.environ["PATH"].split(os.pathsep)
assert paths.index(spack_path) < paths.index(module_path) assert paths.index(spack_path) < paths.index(module_path)
@ -495,14 +489,13 @@ def test_parallel_false_is_not_propagating(default_mock_concretization):
("rpath", "" if platform.system() == "Darwin" else "--disable-new-dtags"), ("rpath", "" if platform.system() == "Darwin" else "--disable-new-dtags"),
], ],
) )
def test_setting_dtags_based_on_config(config_setting, expected_flag, config, mock_packages): def test_setting_dtags_based_on_config(
config_setting, expected_flag, config, mock_packages, working_env
):
# Pick a random package to be able to set compiler's variables # Pick a random package to be able to set compiler's variables
s = spack.concretize.concretize_one("cmake") s = spack.concretize.concretize_one("cmake")
pkg = s.package
env = EnvironmentModifications()
with spack.config.override("config:shared_linking", {"type": config_setting, "bind": False}): with spack.config.override("config:shared_linking", {"type": config_setting, "bind": False}):
spack.build_environment.set_compiler_environment_variables(pkg, env) env = spack.build_environment.setup_package(s.package, dirty=False)
modifications = env.group_by_name() modifications = env.group_by_name()
assert "SPACK_DTAGS_TO_STRIP" in modifications assert "SPACK_DTAGS_TO_STRIP" in modifications
assert "SPACK_DTAGS_TO_ADD" in modifications assert "SPACK_DTAGS_TO_ADD" in modifications
@ -765,59 +758,24 @@ def test_rpath_with_duplicate_link_deps():
@pytest.mark.parametrize( @pytest.mark.parametrize(
"compiler_spec,target_name,expected_flags", "compiler_spec,target_name,expected_flags",
[ [
# Homogeneous compilers # Semver versions
("gcc@4.7.2", "ivybridge", "-march=core-avx-i -mtune=core-avx-i"), ("gcc@4.7.2", "ivybridge", "-march=core-avx-i -mtune=core-avx-i"),
("clang@3.5", "x86_64", "-march=x86-64 -mtune=generic"), ("clang@3.5", "x86_64", "-march=x86-64 -mtune=generic"),
("apple-clang@9.1.0", "x86_64", "-march=x86-64"), ("apple-clang@9.1.0", "x86_64", "-march=x86-64"),
# Mixed toolchain ("gcc@=9.2.0", "haswell", "-march=haswell -mtune=haswell"),
("clang@8.0.0", "broadwell", ""), # Check that custom string versions are accepted
("gcc@=9.2.0-foo", "icelake", "-march=icelake-client -mtune=icelake-client"),
# Check that the special case for Apple's clang is treated correctly
# i.e. it won't try to detect the version again
("apple-clang@=9.1.0", "x86_64", "-march=x86-64"),
# FIXME (compiler as nodes): Check mixed toolchain
# ("clang@8.0.0", "broadwell", ""),
], ],
) )
@pytest.mark.filterwarnings("ignore:microarchitecture specific") @pytest.mark.filterwarnings("ignore:microarchitecture specific")
@pytest.mark.not_on_windows("Windows doesn't support the compiler wrapper") @pytest.mark.not_on_windows("Windows doesn't support the compiler wrapper")
def test_optimization_flags(compiler_spec, target_name, expected_flags, compiler_factory): def test_optimization_flags(compiler_spec, target_name, expected_flags, compiler_factory):
target = archspec.cpu.TARGETS[target_name] target = archspec.cpu.TARGETS[target_name]
compiler_dict = compiler_factory(spec=compiler_spec, operating_system="")["compiler"] compiler = spack.spec.parse_with_version_concrete(compiler_spec)
if compiler_spec == "clang@8.0.0":
compiler_dict["paths"] = {
"cc": "/path/to/clang-8",
"cxx": "/path/to/clang++-8",
"f77": "/path/to/gfortran-9",
"fc": "/path/to/gfortran-9",
}
compiler = spack.compilers.compiler_from_dict(compiler_dict)
opt_flags = spack.build_environment.optimization_flags(compiler, target)
assert opt_flags == expected_flags
@pytest.mark.parametrize(
"compiler_str,real_version,target_str,expected_flags",
[
("gcc@=9.2.0", None, "haswell", "-march=haswell -mtune=haswell"),
# Check that custom string versions are accepted
("gcc@=10foo", "9.2.0", "icelake", "-march=icelake-client -mtune=icelake-client"),
# Check that we run version detection (4.4.0 doesn't support icelake)
("gcc@=4.4.0-special", "9.2.0", "icelake", "-march=icelake-client -mtune=icelake-client"),
# Check that the special case for Apple's clang is treated correctly
# i.e. it won't try to detect the version again
("apple-clang@=9.1.0", None, "x86_64", "-march=x86-64"),
],
)
def test_optimization_flags_with_custom_versions(
compiler_str,
real_version,
target_str,
expected_flags,
monkeypatch,
mutable_config,
compiler_factory,
):
target = archspec.cpu.TARGETS[target_str]
compiler_dict = compiler_factory(spec=compiler_str, operating_system="redhat6")
mutable_config.set("compilers", [compiler_dict])
if real_version:
monkeypatch.setattr(spack.compiler.Compiler, "get_real_version", lambda x: real_version)
compiler = spack.compilers.compiler_from_dict(compiler_dict["compiler"])
opt_flags = spack.build_environment.optimization_flags(compiler, target) opt_flags = spack.build_environment.optimization_flags(compiler, target)
assert opt_flags == expected_flags assert opt_flags == expected_flags

View File

@ -301,22 +301,29 @@ def __call__(self, *args, **kwargs):
def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo): def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo):
"""Test that given an active environment and list of touched pkgs, """Tests that, given an active environment and list of touched pkgs, we get the right
we get the right list of possibly-changed env specs""" list of possibly-changed env specs.
The test concretizes the following environment:
[ ] hypre@=0.2.15+shared build_system=generic
[bl ] ^openblas-with-lapack@=0.2.15 build_system=generic
[ ] mpileaks@=2.3~debug~opt+shared+static build_system=generic
[bl ] ^callpath@=1.0 build_system=generic
[bl ] ^dyninst@=8.2 build_system=generic
[bl ] ^libdwarf@=20130729 build_system=generic
[bl ] ^libelf@=0.8.13 build_system=generic
[b ] ^gcc@=10.2.1 build_system=generic languages='c,c++,fortran'
[ l ] ^gcc-runtime@=10.2.1 build_system=generic
[bl ] ^mpich@=3.0.4~debug build_system=generic
and simulates a change in libdwarf.
"""
e1 = ev.create("test") e1 = ev.create("test")
e1.add("mpileaks") e1.add("mpileaks")
e1.add("hypre") e1.add("hypre")
e1.concretize() e1.concretize()
# Concretizing the above environment results in the following graphs:
# mpileaks -> mpich (provides mpi virtual dep of mpileaks)
# -> callpath -> dyninst -> libelf
# -> libdwarf -> libelf
# -> mpich (provides mpi dep of callpath)
# hypre -> openblas-with-lapack (provides lapack and blas virtual deps of hypre)
touched = ["libdwarf"] touched = ["libdwarf"]
# Make sure we return the correct set of possibly affected specs, # Make sure we return the correct set of possibly affected specs,
@ -328,17 +335,25 @@ def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo):
# no spec traversals. Passing any other number yields differing # no spec traversals. Passing any other number yields differing
# numbers of possibly affected specs. # numbers of possibly affected specs.
full_set = set(["mpileaks", "mpich", "callpath", "dyninst", "libdwarf", "libelf"]) full_set = {
empty_set = set([]) "mpileaks",
depth_2_set = set(["mpich", "callpath", "dyninst", "libdwarf", "libelf"]) "mpich",
depth_1_set = set(["dyninst", "libdwarf", "libelf"]) "callpath",
depth_0_set = set(["libdwarf", "libelf"]) "dyninst",
"libdwarf",
"libelf",
"gcc",
"gcc-runtime",
}
depth_2_set = {"mpich", "callpath", "dyninst", "libdwarf", "libelf", "gcc", "gcc-runtime"}
depth_1_set = {"dyninst", "libdwarf", "libelf", "gcc", "gcc-runtime"}
depth_0_set = {"libdwarf", "libelf", "gcc", "gcc-runtime"}
expectations = { expectations = {
None: full_set, None: full_set,
3: full_set, 3: full_set,
100: full_set, 100: full_set,
-1: empty_set, -1: set(),
0: depth_0_set, 0: depth_0_set,
1: depth_1_set, 1: depth_1_set,
2: depth_2_set, 2: depth_2_set,
@ -346,8 +361,7 @@ def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo):
for key, val in expectations.items(): for key, val in expectations.items():
affected_specs = ci.get_spec_filter_list(e1, touched, dependent_traverse_depth=key) affected_specs = ci.get_spec_filter_list(e1, touched, dependent_traverse_depth=key)
affected_pkg_names = set([s.name for s in affected_specs]) affected_pkg_names = {s.name for s in affected_specs}
print(f"{key}: {affected_pkg_names}")
assert affected_pkg_names == val assert affected_pkg_names == val

View File

@ -182,9 +182,9 @@ def test_ci_generate_with_env(ci_generate_test, tmp_path, mock_binary_index):
assert yaml_contents["workflow"]["rules"] == [{"when": "always"}] assert yaml_contents["workflow"]["rules"] == [{"when": "always"}]
assert "stages" in yaml_contents assert "stages" in yaml_contents
assert len(yaml_contents["stages"]) == 5 assert len(yaml_contents["stages"]) == 6
assert yaml_contents["stages"][0] == "stage-0" assert yaml_contents["stages"][0] == "stage-0"
assert yaml_contents["stages"][4] == "stage-rebuild-index" assert yaml_contents["stages"][5] == "stage-rebuild-index"
assert "rebuild-index" in yaml_contents assert "rebuild-index" in yaml_contents
rebuild_job = yaml_contents["rebuild-index"] rebuild_job = yaml_contents["rebuild-index"]

View File

@ -10,7 +10,6 @@
import spack.compilers.config import spack.compilers.config
import spack.config import spack.config
import spack.main import spack.main
import spack.spec
import spack.util.pattern import spack.util.pattern
import spack.version import spack.version

View File

@ -13,7 +13,7 @@
dependencies = SpackCommand("dependencies") dependencies = SpackCommand("dependencies")
mpis = [ MPIS = [
"intel-parallel-studio", "intel-parallel-studio",
"low-priority-provider", "low-priority-provider",
"mpich", "mpich",
@ -21,16 +21,17 @@
"multi-provider-mpi", "multi-provider-mpi",
"zmpi", "zmpi",
] ]
mpi_deps = ["fake"] COMPILERS = ["gcc", "llvm"]
MPI_DEPS = ["fake"]
@pytest.mark.parametrize( @pytest.mark.parametrize(
"cli_args,expected", "cli_args,expected",
[ [
(["mpileaks"], set(["callpath"] + mpis)), (["mpileaks"], set(["callpath"] + MPIS + COMPILERS)),
( (
["--transitive", "mpileaks"], ["--transitive", "mpileaks"],
set(["callpath", "dyninst", "libdwarf", "libelf"] + mpis + mpi_deps), set(["callpath", "dyninst", "libdwarf", "libelf"] + MPIS + MPI_DEPS + COMPILERS),
), ),
(["--transitive", "--deptype=link,run", "dtbuild1"], {"dtlink2", "dtrun2"}), (["--transitive", "--deptype=link,run", "dtbuild1"], {"dtlink2", "dtrun2"}),
(["--transitive", "--deptype=build", "dtbuild1"], {"dtbuild2", "dtlink2"}), (["--transitive", "--deptype=build", "dtbuild1"], {"dtbuild2", "dtlink2"}),
@ -49,12 +50,11 @@ def test_direct_installed_dependencies(mock_packages, database):
with color_when(False): with color_when(False):
out = dependencies("--installed", "mpileaks^mpich") out = dependencies("--installed", "mpileaks^mpich")
lines = [line for line in out.strip().split("\n") if not line.startswith("--")] root = spack.store.STORE.db.query_one("mpileaks ^mpich")
hashes = set([re.split(r"\s+", line)[0] for line in lines])
expected = set( lines = [line for line in out.strip().split("\n") if line and not line.startswith("--")]
[spack.store.STORE.db.query_one(s).dag_hash(7) for s in ["mpich", "callpath^mpich"]] hashes = {re.split(r"\s+", line)[0] for line in lines}
) expected = {s.dag_hash(7) for s in root.dependencies()}
assert expected == hashes assert expected == hashes
@ -64,14 +64,10 @@ def test_transitive_installed_dependencies(mock_packages, database):
with color_when(False): with color_when(False):
out = dependencies("--installed", "--transitive", "mpileaks^zmpi") out = dependencies("--installed", "--transitive", "mpileaks^zmpi")
lines = [line for line in out.strip().split("\n") if not line.startswith("--")] root = spack.store.STORE.db.query_one("mpileaks ^zmpi")
hashes = set([re.split(r"\s+", line)[0] for line in lines])
expected = set( lines = [line for line in out.strip().split("\n") if line and not line.startswith("--")]
[ hashes = {re.split(r"\s+", line)[0] for line in lines}
spack.store.STORE.db.query_one(s).dag_hash(7) expected = {s.dag_hash(7) for s in root.traverse(root=False)}
for s in ["zmpi", "callpath^zmpi", "fake", "dyninst", "libdwarf", "libelf"]
]
)
assert expected == hashes assert expected == hashes

View File

@ -223,14 +223,12 @@ def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages):
for dep in ("mpileaks", "callpath", "dyninst", "libelf", "libdwarf", "mpich") for dep in ("mpileaks", "callpath", "dyninst", "libelf", "libdwarf", "mpich")
) )
assert all( assert all(
len([diff for diff in result["intersect"] if diff[0] == attr]) == 6 len([diff for diff in result["intersect"] if diff[0] == attr]) == 7
for attr in ( for attr in (
"version", "version",
"node_target", "node_target",
"node_platform", "node_platform",
"node_os", "node_os",
"node_compiler",
"node_compiler_version",
"node", "node",
"package_hash", "package_hash",
"hash", "hash",

View File

@ -170,7 +170,7 @@ def _check_json_output(spec_list):
def _check_json_output_deps(spec_list): def _check_json_output_deps(spec_list):
assert len(spec_list) == 13 assert len(spec_list) == 15
names = [spec["name"] for spec in spec_list] names = [spec["name"] for spec in spec_list]
assert names.count("mpileaks") == 3 assert names.count("mpileaks") == 3
@ -272,6 +272,8 @@ def test_find_format_deps(database, config):
dyninst-8.2 dyninst-8.2
libdwarf-20130729 libdwarf-20130729
libelf-0.8.13 libelf-0.8.13
gcc-10.2.1
gcc-runtime-10.2.1
zmpi-1.0 zmpi-1.0
fake-1.0 fake-1.0
@ -282,24 +284,21 @@ def test_find_format_deps(database, config):
@pytest.mark.db @pytest.mark.db
def test_find_format_deps_paths(database, config): def test_find_format_deps_paths(database, config):
output = find("-dp", "--format", "{name}-{version}", "mpileaks", "^zmpi") output = find("-dp", "--format", "{name}-{version}", "mpileaks", "^zmpi")
mpileaks = spack.concretize.concretize_one("mpileaks ^zmpi")
spec = spack.concretize.concretize_one("mpileaks ^zmpi")
prefixes = [s.prefix for s in spec.traverse()]
assert ( assert (
output output
== """\ == f"""\
mpileaks-2.3 {0} mpileaks-2.3 {mpileaks.prefix}
callpath-1.0 {1} callpath-1.0 {mpileaks['callpath'].prefix}
dyninst-8.2 {2} dyninst-8.2 {mpileaks['dyninst'].prefix}
libdwarf-20130729 {3} libdwarf-20130729 {mpileaks['libdwarf'].prefix}
libelf-0.8.13 {4} libelf-0.8.13 {mpileaks['libelf'].prefix}
zmpi-1.0 {5} gcc-10.2.1 {mpileaks['gcc'].prefix}
fake-1.0 {6} gcc-runtime-10.2.1 {mpileaks['gcc-runtime'].prefix}
zmpi-1.0 {mpileaks['zmpi'].prefix}
fake-1.0 {mpileaks['fake'].prefix}
""".format( """
*prefixes
)
) )
@ -317,12 +316,6 @@ def test_find_very_long(database, config):
) )
@pytest.mark.db
def test_find_show_compiler(database, config):
output = find("--no-groups", "--show-full-compiler", "mpileaks")
assert "mpileaks@2.3%gcc@10.2.1" in output
@pytest.mark.db @pytest.mark.db
def test_find_not_found(database, config, capsys): def test_find_not_found(database, config, capsys):
with capsys.disabled(): with capsys.disabled():
@ -464,7 +457,7 @@ def test_environment_with_version_range_in_compiler_doesnt_fail(tmp_path):
with test_environment: with test_environment:
output = find() output = find()
assert "zlib%gcc@12.1.0" in output assert "zlib" in output
_pkga = ( _pkga = (

View File

@ -21,7 +21,8 @@
@pytest.mark.db @pytest.mark.db
def test_gc_without_build_dependency(mutable_database): def test_gc_without_build_dependency(mutable_database):
assert "There are no unused specs." in gc("-yb") assert "There are no unused specs." in gc("-yb")
assert "There are no unused specs." in gc("-y") # 'gcc' is a pure build dependency in the DB
assert "There are no unused specs." not in gc("-y")
@pytest.mark.db @pytest.mark.db
@ -60,7 +61,7 @@ def test_gc_with_environment(mutable_database, mutable_mock_env_path):
add("cmake") add("cmake")
install() install()
assert mutable_database.query_local("cmake") assert mutable_database.query_local("cmake")
output = gc("-y") output = gc("-by")
assert "Restricting garbage collection" in output assert "Restricting garbage collection" in output
assert "There are no unused specs" in output assert "There are no unused specs" in output

View File

@ -54,14 +54,14 @@ def test_install_package_and_dependency(
): ):
log = "test" log = "test"
with tmpdir.as_cwd(): with tmpdir.as_cwd():
install("--log-format=junit", "--log-file={0}".format(log), "libdwarf") install("--fake", "--log-format=junit", f"--log-file={log}", "libdwarf")
files = tmpdir.listdir() files = tmpdir.listdir()
filename = tmpdir.join("{0}.xml".format(log)) filename = tmpdir.join(f"{log}.xml")
assert filename in files assert filename in files
content = filename.open().read() content = filename.open().read()
assert 'tests="2"' in content assert 'tests="3"' in content
assert 'failures="0"' in content assert 'failures="0"' in content
assert 'errors="0"' in content assert 'errors="0"' in content
@ -97,20 +97,21 @@ def test_install_package_already_installed(
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
): ):
with tmpdir.as_cwd(): with tmpdir.as_cwd():
install("libdwarf") install("--fake", "libdwarf")
install("--log-format=junit", "--log-file=test.xml", "libdwarf") install("--fake", "--log-format=junit", "--log-file=test.xml", "libdwarf")
files = tmpdir.listdir() files = tmpdir.listdir()
filename = tmpdir.join("test.xml") filename = tmpdir.join("test.xml")
assert filename in files assert filename in files
content = filename.open().read() content = filename.open().read()
assert 'tests="2"' in content print(content)
assert 'tests="4"' in content
assert 'failures="0"' in content assert 'failures="0"' in content
assert 'errors="0"' in content assert 'errors="0"' in content
skipped = [line for line in content.split("\n") if "skipped" in line] skipped = [line for line in content.split("\n") if "skipped" in line]
assert len(skipped) == 2 assert len(skipped) == 4
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -183,8 +184,8 @@ def test_install_with_source(mock_packages, mock_archive, mock_fetch, install_mo
def test_install_env_variables(mock_packages, mock_archive, mock_fetch, install_mockery): def test_install_env_variables(mock_packages, mock_archive, mock_fetch, install_mockery):
spec = spack.concretize.concretize_one("libdwarf") spec = spack.concretize.concretize_one("pkg-c")
install("libdwarf") install("pkg-c")
assert os.path.isfile(spec.package.install_env_path) assert os.path.isfile(spec.package.install_env_path)
@ -203,10 +204,9 @@ def test_show_log_on_error(mock_packages, mock_archive, mock_fetch, install_mock
def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mockery): def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mockery):
# Try to install a spec and then to reinstall it. """Tests installing a spec, and then re-installing it in the same prefix."""
spec = spack.concretize.concretize_one("libdwarf") spec = spack.concretize.concretize_one("pkg-c")
install("pkg-c")
install("libdwarf")
# Ignore manifest and install times # Ignore manifest and install times
manifest = os.path.join( manifest = os.path.join(
@ -228,7 +228,7 @@ def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mock
assert bad_md5 != expected_md5 assert bad_md5 != expected_md5
install("--overwrite", "-y", "libdwarf") install("--overwrite", "-y", "pkg-c")
assert os.path.exists(spec.prefix) assert os.path.exists(spec.prefix)
assert fs.hash_directory(spec.prefix, ignore=ignores) == expected_md5 assert fs.hash_directory(spec.prefix, ignore=ignores) == expected_md5
@ -236,12 +236,10 @@ def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mock
def test_install_overwrite_not_installed(mock_packages, mock_archive, mock_fetch, install_mockery): def test_install_overwrite_not_installed(mock_packages, mock_archive, mock_fetch, install_mockery):
# Try to install a spec and then to reinstall it. """Tests that overwrite doesn't fail if the package is not installed"""
spec = spack.concretize.concretize_one("libdwarf") spec = spack.concretize.concretize_one("pkg-c")
assert not os.path.exists(spec.prefix) assert not os.path.exists(spec.prefix)
install("--overwrite", "-y", "pkg-c")
install("--overwrite", "-y", "libdwarf")
assert os.path.exists(spec.prefix) assert os.path.exists(spec.prefix)
@ -272,12 +270,10 @@ def test_install_commit(mock_git_version_info, install_mockery, mock_packages, m
def test_install_overwrite_multiple(mock_packages, mock_archive, mock_fetch, install_mockery): def test_install_overwrite_multiple(mock_packages, mock_archive, mock_fetch, install_mockery):
# Try to install a spec and then to reinstall it. # Try to install a spec and then to reinstall it.
libdwarf = spack.concretize.concretize_one("libdwarf") libdwarf = spack.concretize.concretize_one("libdwarf")
install("libdwarf")
cmake = spack.concretize.concretize_one("cmake") cmake = spack.concretize.concretize_one("cmake")
install("cmake") install("--fake", "libdwarf")
install("--fake", "cmake")
ld_manifest = os.path.join( ld_manifest = os.path.join(
libdwarf.prefix, libdwarf.prefix,
@ -313,7 +309,7 @@ def test_install_overwrite_multiple(mock_packages, mock_archive, mock_fetch, ins
assert bad_libdwarf_md5 != expected_libdwarf_md5 assert bad_libdwarf_md5 != expected_libdwarf_md5
assert bad_cmake_md5 != expected_cmake_md5 assert bad_cmake_md5 != expected_cmake_md5
install("--overwrite", "-y", "libdwarf", "cmake") install("--fake", "--overwrite", "-y", "libdwarf", "cmake")
assert os.path.exists(libdwarf.prefix) assert os.path.exists(libdwarf.prefix)
assert os.path.exists(cmake.prefix) assert os.path.exists(cmake.prefix)
@ -548,10 +544,10 @@ def test_cdash_upload_build_error(tmpdir, mock_fetch, install_mockery, capfd):
def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery, capfd): def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery, capfd):
# capfd interferes with Spack's capturing of e.g., Build.xml output # capfd interferes with Spack's capturing of e.g., Build.xml output
with capfd.disabled(), tmpdir.as_cwd(): with capfd.disabled(), tmpdir.as_cwd():
install("--log-file=cdash_reports", "--log-format=cdash", "pkg-a") install("--log-file=cdash_reports", "--log-format=cdash", "pkg-c")
report_dir = tmpdir.join("cdash_reports") report_dir = tmpdir.join("cdash_reports")
assert report_dir in tmpdir.listdir() assert report_dir in tmpdir.listdir()
report_file = report_dir.join("pkg-a_Build.xml") report_file = report_dir.join("Build.xml")
assert report_file in report_dir.listdir() assert report_file in report_dir.listdir()
content = report_file.open().read() content = report_file.open().read()
assert "</Build>" in content assert "</Build>" in content
@ -568,14 +564,14 @@ def test_cdash_upload_extra_params(tmpdir, mock_fetch, install_mockery, capfd):
"--cdash-build=my_custom_build", "--cdash-build=my_custom_build",
"--cdash-site=my_custom_site", "--cdash-site=my_custom_site",
"--cdash-track=my_custom_track", "--cdash-track=my_custom_track",
"pkg-a", "pkg-c",
) )
report_dir = tmpdir.join("cdash_reports") report_dir = tmpdir.join("cdash_reports")
assert report_dir in tmpdir.listdir() assert report_dir in tmpdir.listdir()
report_file = report_dir.join("pkg-a_Build.xml") report_file = report_dir.join("Build.xml")
assert report_file in report_dir.listdir() assert report_file in report_dir.listdir()
content = report_file.open().read() content = report_file.open().read()
assert 'Site BuildName="my_custom_build - pkg-a"' in content assert 'Site BuildName="my_custom_build"' in content
assert 'Name="my_custom_site"' in content assert 'Name="my_custom_site"' in content
assert "-my_custom_track" in content assert "-my_custom_track" in content
@ -585,17 +581,17 @@ def test_cdash_buildstamp_param(tmpdir, mock_fetch, install_mockery, capfd):
# capfd interferes with Spack's capture of e.g., Build.xml output # capfd interferes with Spack's capture of e.g., Build.xml output
with capfd.disabled(), tmpdir.as_cwd(): with capfd.disabled(), tmpdir.as_cwd():
cdash_track = "some_mocked_track" cdash_track = "some_mocked_track"
buildstamp_format = "%Y%m%d-%H%M-{0}".format(cdash_track) buildstamp_format = f"%Y%m%d-%H%M-{cdash_track}"
buildstamp = time.strftime(buildstamp_format, time.localtime(int(time.time()))) buildstamp = time.strftime(buildstamp_format, time.localtime(int(time.time())))
install( install(
"--log-file=cdash_reports", "--log-file=cdash_reports",
"--log-format=cdash", "--log-format=cdash",
"--cdash-buildstamp={0}".format(buildstamp), f"--cdash-buildstamp={buildstamp}",
"pkg-a", "pkg-c",
) )
report_dir = tmpdir.join("cdash_reports") report_dir = tmpdir.join("cdash_reports")
assert report_dir in tmpdir.listdir() assert report_dir in tmpdir.listdir()
report_file = report_dir.join("pkg-a_Build.xml") report_file = report_dir.join("Build.xml")
assert report_file in report_dir.listdir() assert report_file in report_dir.listdir()
content = report_file.open().read() content = report_file.open().read()
assert buildstamp in content assert buildstamp in content
@ -609,8 +605,7 @@ def test_cdash_install_from_spec_json(
with capfd.disabled(), tmpdir.as_cwd(): with capfd.disabled(), tmpdir.as_cwd():
spec_json_path = str(tmpdir.join("spec.json")) spec_json_path = str(tmpdir.join("spec.json"))
pkg_spec = spack.concretize.concretize_one("pkg-a") pkg_spec = spack.concretize.concretize_one("pkg-c")
with open(spec_json_path, "w", encoding="utf-8") as fd: with open(spec_json_path, "w", encoding="utf-8") as fd:
fd.write(pkg_spec.to_json(hash=ht.dag_hash)) fd.write(pkg_spec.to_json(hash=ht.dag_hash))
@ -626,7 +621,7 @@ def test_cdash_install_from_spec_json(
report_dir = tmpdir.join("cdash_reports") report_dir = tmpdir.join("cdash_reports")
assert report_dir in tmpdir.listdir() assert report_dir in tmpdir.listdir()
report_file = report_dir.join("pkg-a_Configure.xml") report_file = report_dir.join("Configure.xml")
assert report_file in report_dir.listdir() assert report_file in report_dir.listdir()
content = report_file.open().read() content = report_file.open().read()
install_command_regex = re.compile( install_command_regex = re.compile(
@ -635,7 +630,7 @@ def test_cdash_install_from_spec_json(
m = install_command_regex.search(content) m = install_command_regex.search(content)
assert m assert m
install_command = m.group(1) install_command = m.group(1)
assert "pkg-a@" in install_command assert "pkg-c@" in install_command
@pytest.mark.disable_clean_stage_check @pytest.mark.disable_clean_stage_check
@ -672,7 +667,7 @@ def test_cache_only_fails(tmpdir, mock_fetch, install_mockery, capfd):
with capfd.disabled(): with capfd.disabled():
out = install("--cache-only", "libdwarf", fail_on_error=False) out = install("--cache-only", "libdwarf", fail_on_error=False)
assert "Failed to install libelf" in out assert "Failed to install gcc-runtime" in out
assert "Skipping build of libdwarf" in out assert "Skipping build of libdwarf" in out
assert "was not installed" in out assert "was not installed" in out
@ -806,12 +801,12 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
# Activate the environment # Activate the environment
with e: with e:
# Assert using --no-add with a spec not in the env fails # Assert using --no-add with a spec not in the env fails
inst_out = install("--no-add", "boost", fail_on_error=False, output=str) inst_out = install("--fake", "--no-add", "boost", fail_on_error=False, output=str)
assert "You can add specs to the environment with 'spack add " in inst_out assert "You can add specs to the environment with 'spack add " in inst_out
# Without --add, ensure that two packages "a" get installed # Without --add, ensure that two packages "a" get installed
inst_out = install("pkg-a", output=str) inst_out = install("--fake", "pkg-a", output=str)
assert len([x for x in e.all_specs() if x.installed and x.name == "pkg-a"]) == 2 assert len([x for x in e.all_specs() if x.installed and x.name == "pkg-a"]) == 2
# Install an unambiguous dependency spec (that already exists as a dep # Install an unambiguous dependency spec (that already exists as a dep
@ -845,14 +840,14 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
# root of the environment as well as installed. # root of the environment as well as installed.
assert b_spec not in e.roots() assert b_spec not in e.roots()
install("--add", "pkg-b") install("--fake", "--add", "pkg-b")
assert b_spec in e.roots() assert b_spec in e.roots()
assert b_spec not in e.uninstalled_specs() assert b_spec not in e.uninstalled_specs()
# Install a novel spec with --add and make sure it is added as a root # Install a novel spec with --add and make sure it is added as a root
# and installed. # and installed.
install("--add", "bowtie") install("--fake", "--add", "bowtie")
assert any([s.name == "bowtie" for s in e.roots()]) assert any([s.name == "bowtie" for s in e.roots()])
assert not any([s.name == "bowtie" for s in e.uninstalled_specs()]) assert not any([s.name == "bowtie" for s in e.uninstalled_specs()])
@ -880,7 +875,7 @@ def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, monkeypatch, capf
# capfd interferes with Spack's capturing # capfd interferes with Spack's capturing
with tmpdir.as_cwd(), capfd.disabled(): with tmpdir.as_cwd(), capfd.disabled():
monkeypatch.setenv("SPACK_CDASH_AUTH_TOKEN", "asdf") monkeypatch.setenv("SPACK_CDASH_AUTH_TOKEN", "asdf")
out = install("-v", "--log-file=cdash_reports", "--log-format=cdash", "pkg-a") out = install("--fake", "-v", "--log-file=cdash_reports", "--log-format=cdash", "pkg-a")
assert "Using CDash auth token from environment" in out assert "Using CDash auth token from environment" in out
@ -941,7 +936,7 @@ def test_install_env_with_tests_all(
with ev.read("test"): with ev.read("test"):
test_dep = spack.concretize.concretize_one("test-dependency") test_dep = spack.concretize.concretize_one("test-dependency")
add("depb") add("depb")
install("--test", "all") install("--fake", "--test", "all")
assert os.path.exists(test_dep.prefix) assert os.path.exists(test_dep.prefix)
@ -953,7 +948,7 @@ def test_install_env_with_tests_root(
with ev.read("test"): with ev.read("test"):
test_dep = spack.concretize.concretize_one("test-dependency") test_dep = spack.concretize.concretize_one("test-dependency")
add("depb") add("depb")
install("--test", "root") install("--fake", "--test", "root")
assert not os.path.exists(test_dep.prefix) assert not os.path.exists(test_dep.prefix)

View File

@ -29,7 +29,7 @@ def test_manpath_trailing_colon(
# Test that the commands generated by load add the MANPATH prefix # Test that the commands generated by load add the MANPATH prefix
# inspections. Also test that Spack correctly preserves the default/existing # inspections. Also test that Spack correctly preserves the default/existing
# manpath search path via a trailing colon # manpath search path via a trailing colon
install("mpileaks") install("--fake", "mpileaks")
sh_out = load(shell, "mpileaks") sh_out = load(shell, "mpileaks")
lines = [line.strip("\n") for line in sh_out.split(commandsep)] lines = [line.strip("\n") for line in sh_out.split(commandsep)]
@ -48,7 +48,7 @@ def test_load_recursive(install_mockery, mock_fetch, mock_archive, mock_packages
def test_load_shell(shell, set_command): def test_load_shell(shell, set_command):
"""Test that `spack load` applies prefix inspections of its required runtime deps in """Test that `spack load` applies prefix inspections of its required runtime deps in
topo-order""" topo-order"""
install("mpileaks") install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks") mpileaks_spec = spack.concretize.concretize_one("mpileaks")
# Ensure our reference variable is clean. # Ensure our reference variable is clean.
@ -117,7 +117,7 @@ def test_load_includes_run_env(
"""Tests that environment changes from the package's """Tests that environment changes from the package's
`setup_run_environment` method are added to the user environment in `setup_run_environment` method are added to the user environment in
addition to the prefix inspections""" addition to the prefix inspections"""
install("mpileaks") install("--fake", "mpileaks")
shell_out = load(shell, "mpileaks") shell_out = load(shell, "mpileaks")
@ -127,8 +127,8 @@ def test_load_includes_run_env(
def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages): def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages):
"""Test with and without the --first option""" """Test with and without the --first option"""
shell = "--bat" if sys.platform == "win32" else "--sh" shell = "--bat" if sys.platform == "win32" else "--sh"
install("libelf@0.8.12") install("--fake", "libelf@0.8.12")
install("libelf@0.8.13") install("--fake", "libelf@0.8.13")
# Now there are two versions of libelf, which should cause an error # Now there are two versions of libelf, which should cause an error
out = load(shell, "libelf", fail_on_error=False) out = load(shell, "libelf", fail_on_error=False)
@ -141,7 +141,7 @@ def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages):
def test_load_fails_no_shell(install_mockery, mock_fetch, mock_archive, mock_packages): def test_load_fails_no_shell(install_mockery, mock_fetch, mock_archive, mock_packages):
"""Test that spack load prints an error message without a shell.""" """Test that spack load prints an error message without a shell."""
install("mpileaks") install("--fake", "mpileaks")
out = load("mpileaks", fail_on_error=False) out = load("mpileaks", fail_on_error=False)
assert "To set up shell support" in out assert "To set up shell support" in out
@ -167,7 +167,7 @@ def test_unload(
): ):
"""Tests that any variables set in the user environment are undone by the """Tests that any variables set in the user environment are undone by the
unload command""" unload command"""
install("mpileaks") install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks") mpileaks_spec = spack.concretize.concretize_one("mpileaks")
# Set so unload has something to do # Set so unload has something to do
@ -188,7 +188,7 @@ def test_unload_fails_no_shell(
install_mockery, mock_fetch, mock_archive, mock_packages, working_env install_mockery, mock_fetch, mock_archive, mock_packages, working_env
): ):
"""Test that spack unload prints an error message without a shell.""" """Test that spack unload prints an error message without a shell."""
install("mpileaks") install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks") mpileaks_spec = spack.concretize.concretize_one("mpileaks")
os.environ[uenv.spack_loaded_hashes_var] = mpileaks_spec.dag_hash() os.environ[uenv.spack_loaded_hashes_var] = mpileaks_spec.dag_hash()

View File

@ -36,8 +36,8 @@ def mock_spec():
def test_location_first(install_mockery, mock_fetch, mock_archive, mock_packages): def test_location_first(install_mockery, mock_fetch, mock_archive, mock_packages):
"""Test with and without the --first option""" """Test with and without the --first option"""
install = SpackCommand("install") install = SpackCommand("install")
install("libelf@0.8.12") install("--fake", "libelf@0.8.12")
install("libelf@0.8.13") install("--fake", "libelf@0.8.13")
# This would normally return an error without --first # This would normally return an error without --first
assert location("--first", "--install-dir", "libelf") assert location("--first", "--install-dir", "libelf")

View File

@ -54,19 +54,19 @@ def disable_capture(capfd):
def test_logs_cmd_errors(install_mockery, mock_fetch, mock_archive, mock_packages): def test_logs_cmd_errors(install_mockery, mock_fetch, mock_archive, mock_packages):
spec = spack.concretize.concretize_one("libelf") spec = spack.concretize.concretize_one("pkg-c")
assert not spec.installed assert not spec.installed
with pytest.raises(spack.main.SpackCommandError, match="is not installed or staged"): with pytest.raises(spack.main.SpackCommandError, match="is not installed or staged"):
logs("libelf") logs("pkg-c")
with pytest.raises(spack.main.SpackCommandError, match="Too many specs"): with pytest.raises(spack.main.SpackCommandError, match="Too many specs"):
logs("libelf mpi") logs("pkg-c mpi")
install("libelf") install("pkg-c")
os.remove(spec.package.install_log_path) os.remove(spec.package.install_log_path)
with pytest.raises(spack.main.SpackCommandError, match="No logs are available"): with pytest.raises(spack.main.SpackCommandError, match="No logs are available"):
logs("libelf") logs("pkg-c")
def _write_string_to_path(string, path): def _write_string_to_path(string, path):
@ -98,7 +98,7 @@ def test_dump_logs(install_mockery, mock_fetch, mock_archive, mock_packages, dis
spack.cmd.logs._logs(cmdline_spec, concrete_spec) spack.cmd.logs._logs(cmdline_spec, concrete_spec)
assert _rewind_collect_and_decode(redirected_stdout) == stage_log_content assert _rewind_collect_and_decode(redirected_stdout) == stage_log_content
install("libelf") install("--fake", "libelf")
# Sanity check: make sure a path is recorded, regardless of whether # Sanity check: make sure a path is recorded, regardless of whether
# it exists (if it does exist, we will overwrite it with content # it exists (if it does exist, we will overwrite it with content

View File

@ -11,7 +11,13 @@
maintainers = spack.main.SpackCommand("maintainers") maintainers = spack.main.SpackCommand("maintainers")
MAINTAINED_PACKAGES = ["maintainers-1", "maintainers-2", "maintainers-3", "py-extension1"] MAINTAINED_PACKAGES = [
"gcc-runtime",
"maintainers-1",
"maintainers-2",
"maintainers-3",
"py-extension1",
]
def split(output): def split(output):
@ -34,6 +40,8 @@ def test_all(mock_packages, capfd):
with capfd.disabled(): with capfd.disabled():
out = split(maintainers("--all")) out = split(maintainers("--all"))
assert out == [ assert out == [
"gcc-runtime:",
"haampie",
"maintainers-1:", "maintainers-1:",
"user1,", "user1,",
"user2", "user2",
@ -59,6 +67,8 @@ def test_all_by_user(mock_packages, capfd):
with capfd.disabled(): with capfd.disabled():
out = split(maintainers("--all", "--by-user")) out = split(maintainers("--all", "--by-user"))
assert out == [ assert out == [
"haampie:",
"gcc-runtime",
"user0:", "user0:",
"maintainers-3", "maintainers-3",
"user1:", "user1:",

View File

@ -30,7 +30,7 @@ def test_mark_all_explicit(mutable_database):
mark("-e", "-a") mark("-e", "-a")
gc("-y") gc("-y")
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 15 assert len(all_specs) == 16
@pytest.mark.db @pytest.mark.db
@ -47,7 +47,7 @@ def test_mark_one_explicit(mutable_database):
uninstall("-y", "-a", "mpileaks") uninstall("-y", "-a", "mpileaks")
gc("-y") gc("-y")
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 3 assert len(all_specs) == 4
@pytest.mark.db @pytest.mark.db
@ -55,7 +55,7 @@ def test_mark_one_implicit(mutable_database):
mark("-i", "externaltest") mark("-i", "externaltest")
gc("-y") gc("-y")
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 14 assert len(all_specs) == 15
@pytest.mark.db @pytest.mark.db
@ -64,4 +64,4 @@ def test_mark_all_implicit_then_explicit(mutable_database):
mark("-e", "-a") mark("-e", "-a")
gc("-y") gc("-y")
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 15 assert len(all_specs) == 16

View File

@ -353,7 +353,7 @@ def test_mirror_destroy(
spec_name = "libdwarf" spec_name = "libdwarf"
# Put a binary package in a buildcache # Put a binary package in a buildcache
install("--no-cache", spec_name) install("--fake", "--no-cache", spec_name)
buildcache("push", "-u", "-f", mirror_dir.strpath, spec_name) buildcache("push", "-u", "-f", mirror_dir.strpath, spec_name)
contents = os.listdir(mirror_dir.strpath) contents = os.listdir(mirror_dir.strpath)

View File

@ -14,13 +14,10 @@
def test_reindex_basic(mock_packages, mock_archive, mock_fetch, install_mockery): def test_reindex_basic(mock_packages, mock_archive, mock_fetch, install_mockery):
install("libelf@0.8.13") install("--fake", "libelf@0.8.13")
install("libelf@0.8.12") install("--fake", "libelf@0.8.12")
all_installed = spack.store.STORE.db.query() all_installed = spack.store.STORE.db.query()
reindex() reindex()
assert spack.store.STORE.db.query() == all_installed assert spack.store.STORE.db.query() == all_installed
@ -35,23 +32,19 @@ def _clear_db(tmp_path):
def test_reindex_db_deleted(mock_packages, mock_archive, mock_fetch, install_mockery, tmp_path): def test_reindex_db_deleted(mock_packages, mock_archive, mock_fetch, install_mockery, tmp_path):
install("libelf@0.8.13") install("--fake", "libelf@0.8.13")
install("libelf@0.8.12") install("--fake", "libelf@0.8.12")
all_installed = spack.store.STORE.db.query() all_installed = spack.store.STORE.db.query()
_clear_db(tmp_path) _clear_db(tmp_path)
reindex() reindex()
assert spack.store.STORE.db.query() == all_installed assert spack.store.STORE.db.query() == all_installed
def test_reindex_with_deprecated_packages( def test_reindex_with_deprecated_packages(
mock_packages, mock_archive, mock_fetch, install_mockery, tmp_path mock_packages, mock_archive, mock_fetch, install_mockery, tmp_path
): ):
install("libelf@0.8.13") install("--fake", "libelf@0.8.13")
install("libelf@0.8.12") install("--fake", "libelf@0.8.12")
deprecate("-y", "libelf@0.8.12", "libelf@0.8.13") deprecate("-y", "libelf@0.8.12", "libelf@0.8.13")

View File

@ -105,7 +105,11 @@ def test_stage_full_env(mutable_mock_env_path, monkeypatch):
e.concretize() e.concretize()
# list all the package names that should be staged # list all the package names that should be staged
expected = set(dep.name for dep in spack.traverse.traverse_nodes(e.concrete_roots())) expected, externals = set(), set()
for dep in spack.traverse.traverse_nodes(e.concrete_roots()):
expected.add(dep.name)
if dep.external:
externals.add(dep.name)
# pop the package name from the list instead of actually staging # pop the package name from the list instead of actually staging
def fake_stage(pkg, mirror_only=False): def fake_stage(pkg, mirror_only=False):
@ -116,8 +120,7 @@ def fake_stage(pkg, mirror_only=False):
with e: with e:
stage() stage()
# assert that all were staged assert expected == externals
assert len(expected) == 0
@pytest.mark.disable_clean_stage_check @pytest.mark.disable_clean_stage_check

View File

@ -51,7 +51,7 @@ def test_test_dup_alias(
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery, capfd mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery, capfd
): ):
"""Ensure re-using an alias fails with suggestion to change.""" """Ensure re-using an alias fails with suggestion to change."""
install("libdwarf") install("--fake", "libdwarf")
# Run the (no) tests with the alias once # Run the (no) tests with the alias once
spack_test("run", "--alias", "libdwarf", "libdwarf") spack_test("run", "--alias", "libdwarf", "libdwarf")

View File

@ -77,9 +77,8 @@ def test_recursive_uninstall(mutable_database):
"""Test recursive uninstall.""" """Test recursive uninstall."""
uninstall("-y", "-a", "--dependents", "callpath") uninstall("-y", "-a", "--dependents", "callpath")
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 9
# query specs with multiple configurations # query specs with multiple configurations
all_specs = spack.store.STORE.layout.all_specs()
mpileaks_specs = [s for s in all_specs if s.satisfies("mpileaks")] mpileaks_specs = [s for s in all_specs if s.satisfies("mpileaks")]
callpath_specs = [s for s in all_specs if s.satisfies("callpath")] callpath_specs = [s for s in all_specs if s.satisfies("callpath")]
mpi_specs = [s for s in all_specs if s.satisfies("mpi")] mpi_specs = [s for s in all_specs if s.satisfies("mpi")]
@ -91,23 +90,21 @@ def test_recursive_uninstall(mutable_database):
@pytest.mark.db @pytest.mark.db
@pytest.mark.regression("3690") @pytest.mark.regression("3690")
@pytest.mark.parametrize("constraint,expected_number_of_specs", [("dyninst", 8), ("libelf", 6)]) @pytest.mark.parametrize("constraint,expected_number_of_specs", [("dyninst", 9), ("libelf", 7)])
def test_uninstall_spec_with_multiple_roots( def test_uninstall_spec_with_multiple_roots(
constraint, expected_number_of_specs, mutable_database constraint, expected_number_of_specs, mutable_database
): ):
uninstall("-y", "-a", "--dependents", constraint) uninstall("-y", "-a", "--dependents", constraint)
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == expected_number_of_specs assert len(all_specs) == expected_number_of_specs
@pytest.mark.db @pytest.mark.db
@pytest.mark.parametrize("constraint,expected_number_of_specs", [("dyninst", 14), ("libelf", 14)]) @pytest.mark.parametrize("constraint,expected_number_of_specs", [("dyninst", 15), ("libelf", 15)])
def test_force_uninstall_spec_with_ref_count_not_zero( def test_force_uninstall_spec_with_ref_count_not_zero(
constraint, expected_number_of_specs, mutable_database constraint, expected_number_of_specs, mutable_database
): ):
uninstall("-f", "-y", constraint) uninstall("-f", "-y", constraint)
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == expected_number_of_specs assert len(all_specs) == expected_number_of_specs
@ -173,7 +170,7 @@ def db_specs():
all_specs, mpileaks_specs, callpath_specs, mpi_specs = db_specs() all_specs, mpileaks_specs, callpath_specs, mpi_specs = db_specs()
total_specs = len(all_specs) total_specs = len(all_specs)
assert total_specs == 14 assert total_specs == 15
assert len(mpileaks_specs) == 3 assert len(mpileaks_specs) == 3
assert len(callpath_specs) == 2 assert len(callpath_specs) == 2
assert len(mpi_specs) == 3 assert len(mpi_specs) == 3

View File

@ -76,7 +76,7 @@ def test_single_file_verify_cmd(tmpdir):
def test_single_spec_verify_cmd(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery): def test_single_spec_verify_cmd(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
# Test the verify command interface to verify a single spec # Test the verify command interface to verify a single spec
install("libelf") install("--fake", "libelf")
s = spack.concretize.concretize_one("libelf") s = spack.concretize.concretize_one("libelf")
prefix = s.prefix prefix = s.prefix
hash = s.dag_hash() hash = s.dag_hash()

View File

@ -30,26 +30,26 @@
commands = ["hardlink", "symlink", "hard", "add", "copy", "relocate"] commands = ["hardlink", "symlink", "hard", "add", "copy", "relocate"]
def create_projection_file(tmpdir, projection): def create_projection_file(tmp_path, projection):
if "projections" not in projection: if "projections" not in projection:
projection = {"projections": projection} projection = {"projections": projection}
projection_file = tmp_path / "projection" / "projection.yaml"
projection_file = tmpdir.mkdir("projection").join("projection.yaml") projection_file.parent.mkdir(parents=True, exist_ok=True)
projection_file.write(s_yaml.dump(projection)) projection_file.write_text(s_yaml.dump(projection))
return projection_file return projection_file
@pytest.mark.parametrize("cmd", commands) @pytest.mark.parametrize("cmd", commands)
def test_view_link_type(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd): def test_view_link_type(tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
install("libdwarf") install("--fake", "libdwarf")
viewpath = str(tmpdir.mkdir("view_{0}".format(cmd))) view_dir = tmp_path / f"view_{cmd}"
view(cmd, viewpath, "libdwarf") view(cmd, str(view_dir), "libdwarf")
package_prefix = os.path.join(viewpath, "libdwarf") package_bin = view_dir / "bin" / "libdwarf"
assert os.path.exists(package_prefix) assert package_bin.exists()
# Check that we use symlinks for and only for the appropriate subcommands # Check that we use symlinks for and only for the appropriate subcommands
is_link_cmd = cmd in ("symlink", "add") is_link_cmd = cmd in ("symlink", "add")
assert os.path.islink(package_prefix) == is_link_cmd assert os.path.islink(str(package_bin)) == is_link_cmd
@pytest.mark.parametrize("add_cmd", commands) @pytest.mark.parametrize("add_cmd", commands)
@ -67,60 +67,60 @@ def test_view_link_type_remove(
@pytest.mark.parametrize("cmd", commands) @pytest.mark.parametrize("cmd", commands)
def test_view_projections(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd): def test_view_projections(tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
install("libdwarf@20130207") install("--fake", "libdwarf@20130207")
view_dir = tmp_path / f"view_{cmd}"
viewpath = str(tmpdir.mkdir("view_{0}".format(cmd)))
view_projection = {"projections": {"all": "{name}-{version}"}} view_projection = {"projections": {"all": "{name}-{version}"}}
projection_file = create_projection_file(tmpdir, view_projection) projection_file = create_projection_file(tmp_path, view_projection)
view(cmd, viewpath, "--projection-file={0}".format(projection_file), "libdwarf") view(cmd, str(view_dir), f"--projection-file={projection_file}", "libdwarf")
package_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf") package_bin = view_dir / "libdwarf-20130207" / "bin" / "libdwarf"
assert os.path.exists(package_prefix) assert package_bin.exists()
# Check that we use symlinks for and only for the appropriate subcommands # Check that we use symlinks for and only for the appropriate subcommands
is_symlink_cmd = cmd in ("symlink", "add") is_symlink_cmd = cmd in ("symlink", "add")
assert os.path.islink(package_prefix) == is_symlink_cmd assert package_bin.is_symlink() == is_symlink_cmd
def test_view_multiple_projections( def test_view_multiple_projections(
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery
): ):
install("libdwarf@20130207") install("--fake", "libdwarf@20130207")
install("extendee@1.0%gcc") install("--fake", "extendee@1.0")
view_dir = tmp_path / "view"
viewpath = str(tmpdir.mkdir("view"))
view_projection = s_yaml.syaml_dict( view_projection = s_yaml.syaml_dict(
[("extendee", "{name}-{compiler.name}"), ("all", "{name}-{version}")] [("extendee", "{name}-{architecture.platform}"), ("all", "{name}-{version}")]
) )
projection_file = create_projection_file(tmpdir, view_projection) projection_file = create_projection_file(tmp_path, view_projection)
view("add", viewpath, "--projection-file={0}".format(projection_file), "libdwarf", "extendee") view("add", str(view_dir), f"--projection-file={projection_file}", "libdwarf", "extendee")
libdwarf_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf") libdwarf_prefix = view_dir / "libdwarf-20130207" / "bin"
extendee_prefix = os.path.join(viewpath, "extendee-gcc/bin") extendee_prefix = view_dir / "extendee-test" / "bin"
assert os.path.exists(libdwarf_prefix) assert libdwarf_prefix.exists()
assert os.path.exists(extendee_prefix) assert extendee_prefix.exists()
def test_view_multiple_projections_all_first( def test_view_multiple_projections_all_first(
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery
): ):
install("libdwarf@20130207") install("--fake", "libdwarf@20130207")
install("extendee@1.0%gcc") install("--fake", "extendee@1.0")
view_dir = tmp_path / "view"
viewpath = str(tmpdir.mkdir("view"))
view_projection = s_yaml.syaml_dict( view_projection = s_yaml.syaml_dict(
[("all", "{name}-{version}"), ("extendee", "{name}-{compiler.name}")] [("all", "{name}-{version}"), ("extendee", "{name}-{architecture.platform}")]
) )
projection_file = create_projection_file(tmpdir, view_projection) projection_file = create_projection_file(tmp_path, view_projection)
view("add", viewpath, "--projection-file={0}".format(projection_file), "libdwarf", "extendee") view("add", str(view_dir), f"--projection-file={projection_file}", "libdwarf", "extendee")
libdwarf_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf") libdwarf_prefix = view_dir / "libdwarf-20130207" / "bin"
extendee_prefix = os.path.join(viewpath, "extendee-gcc/bin") extendee_prefix = view_dir / "extendee-test" / "bin"
assert os.path.exists(libdwarf_prefix) assert libdwarf_prefix.exists()
assert os.path.exists(extendee_prefix) assert extendee_prefix.exists()
def test_view_external(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery): def test_view_external(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):

View File

@ -1,5 +1,4 @@
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other # Copyright Spack Project Developers. See COPYRIGHT file for details.
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import copy import copy
@ -74,6 +73,7 @@ def test_compile_dummy_c_source_no_verbose_flags(self, mock_gcc, monkeypatch):
detector = spack.compilers.libraries.CompilerPropertyDetector(mock_gcc) detector = spack.compilers.libraries.CompilerPropertyDetector(mock_gcc)
assert detector._compile_dummy_c_source() is None assert detector._compile_dummy_c_source() is None
@pytest.mark.not_on_windows("Module files are not supported on Windows")
def test_compile_dummy_c_source_load_env(self, mock_gcc, monkeypatch, tmp_path): def test_compile_dummy_c_source_load_env(self, mock_gcc, monkeypatch, tmp_path):
gcc = tmp_path / "gcc" gcc = tmp_path / "gcc"
gcc.write_text( gcc.write_text(
@ -104,10 +104,13 @@ def module(*args):
@pytest.mark.not_on_windows("Not supported on Windows") @pytest.mark.not_on_windows("Not supported on Windows")
def test_implicit_rpaths(self, mock_gcc, dirs_with_libfiles, monkeypatch): def test_implicit_rpaths(self, mock_gcc, dirs_with_libfiles, monkeypatch):
lib_to_dirs, all_dirs = dirs_with_libfiles lib_to_dirs, all_dirs = dirs_with_libfiles
monkeypatch.setattr(spack.compilers.libraries.CompilerPropertyDetector, "_CACHE", {})
detector = spack.compilers.libraries.CompilerPropertyDetector(mock_gcc) detector = spack.compilers.libraries.CompilerPropertyDetector(mock_gcc)
detector._CACHE[mock_gcc.dag_hash()] = "ld " + " ".join(f"-L{d}" for d in all_dirs) monkeypatch.setattr(
spack.compilers.libraries.CompilerPropertyDetector,
"_compile_dummy_c_source",
lambda self: "ld " + " ".join(f"-L{d}" for d in all_dirs),
)
retrieved_rpaths = detector.implicit_rpaths() retrieved_rpaths = detector.implicit_rpaths()
assert set(retrieved_rpaths) == set(lib_to_dirs["libstdc++"] + lib_to_dirs["libgfortran"]) assert set(retrieved_rpaths) == set(lib_to_dirs["libstdc++"] + lib_to_dirs["libgfortran"])

View File

@ -17,8 +17,6 @@
from spack.environment.environment import ViewDescriptor from spack.environment.environment import ViewDescriptor
from spack.version import Version from spack.version import Version
pytestmark = [pytest.mark.usefixtures("enable_runtimes")]
def _concretize_with_reuse(*, root_str, reused_str): def _concretize_with_reuse(*, root_str, reused_str):
reused_spec = spack.concretize.concretize_one(reused_str) reused_spec = spack.concretize.concretize_one(reused_str)
@ -36,14 +34,6 @@ def runtime_repo(mutable_config):
yield mock_repo yield mock_repo
@pytest.fixture
def enable_runtimes():
original = spack.solver.asp.WITH_RUNTIME
spack.solver.asp.WITH_RUNTIME = True
yield
spack.solver.asp.WITH_RUNTIME = original
def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo): def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo):
s = spack.concretize.concretize_one("pkg-a%gcc@10.2.1 ^pkg-b%gcc@9.4.0") s = spack.concretize.concretize_one("pkg-a%gcc@10.2.1 ^pkg-b%gcc@9.4.0")
a, b = s["pkg-a"], s["pkg-b"] a, b = s["pkg-a"], s["pkg-b"]

View File

@ -401,24 +401,6 @@ def test_spec_flags_maintain_order(self, mutable_config, gcc11_with_flags):
s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags") s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags")
) )
# FIXME (compiler as nodes): revisit this test
# def test_compiler_flags_differ_identical_compilers(self, mutable_config, clang12_with_flags):
# mutable_config.set("compilers", [clang12_with_flags])
# # Correct arch to use test compiler that has flags
# spec = Spec("pkg-a %clang@12.2.0 platform=test os=fe target=fe")
#
# # Get the compiler that matches the spec (
# compiler = spack.compilers.config.compiler_for_spec("clang@=12.2.0", spec.architecture)
#
# # Configure spack to have two identical compilers with different flags
# default_dict = spack.compilers.config._to_dict(compiler)
# different_dict = copy.deepcopy(default_dict)
# different_dict["compiler"]["flags"] = {"cflags": "-O2"}
#
# with spack.config.override("compilers", [different_dict]):
# spec = spack.concretize.concretize_one(spec)
# assert spec.satisfies("cflags=-O2")
@pytest.mark.parametrize( @pytest.mark.parametrize(
"spec_str,expected,not_expected", "spec_str,expected,not_expected",
[ [
@ -459,11 +441,13 @@ def test_compiler_flag_propagation(self, spec_str, expected, not_expected):
for constraint in not_expected: for constraint in not_expected:
assert not root.satisfies(constraint) assert not root.satisfies(constraint)
@pytest.mark.xfail(reason="FIXME (compiler as nodes): flaky test, revisit")
def test_mixing_compilers_only_affects_subdag(self): def test_mixing_compilers_only_affects_subdag(self):
"""Tests that, when we mix compilers, the one with lower penalty is used for nodes """Tests that, when we mix compilers, the one with lower penalty is used for nodes
where the compiler is not forced. where the compiler is not forced.
""" """
spec = spack.concretize.concretize_one("dt-diamond%clang ^dt-diamond-bottom%gcc") spec = spack.concretize.concretize_one("dt-diamond%clang ^dt-diamond-bottom%gcc")
for x in spec.traverse(deptype=("link", "run")): for x in spec.traverse(deptype=("link", "run")):
if "c" not in x or not x.name.startswith("dt-diamond"): if "c" not in x or not x.name.startswith("dt-diamond"):
continue continue
@ -471,8 +455,7 @@ def test_mixing_compilers_only_affects_subdag(self):
assert bool(x.dependencies(name="llvm", deptype="build")) is not expected_gcc assert bool(x.dependencies(name="llvm", deptype="build")) is not expected_gcc
assert bool(x.dependencies(name="gcc", deptype="build")) is expected_gcc assert bool(x.dependencies(name="gcc", deptype="build")) is expected_gcc
assert x.satisfies("%clang") is not expected_gcc assert x.satisfies("%clang") is not expected_gcc
# FIXME (compiler as nodes): satisfies semantic should be only for direct build deps assert x.satisfies("%gcc") is expected_gcc
# assert x.satisfies("%gcc") is expected_gcc
def test_compiler_inherited_upwards(self): def test_compiler_inherited_upwards(self):
spec = spack.concretize.concretize_one("dt-diamond ^dt-diamond-bottom%clang") spec = spack.concretize.concretize_one("dt-diamond ^dt-diamond-bottom%clang")
@ -724,7 +707,7 @@ def test_concretize_propagate_variant_second_level_dep_not_in_source(self):
def test_no_matching_compiler_specs(self): def test_no_matching_compiler_specs(self):
s = Spec("pkg-a %gcc@0.0.0") s = Spec("pkg-a %gcc@0.0.0")
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError): with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
s.concretize() spack.concretize.concretize_one(s)
def test_no_compilers_for_arch(self): def test_no_compilers_for_arch(self):
s = Spec("pkg-a arch=linux-rhel0-x86_64") s = Spec("pkg-a arch=linux-rhel0-x86_64")
@ -937,13 +920,13 @@ def test_noversion_pkg(self, spec):
[ [
( (
"mpileaks%gcc@=4.4.7 ^dyninst@=10.2.1 target=x86_64:", "mpileaks%gcc@=4.4.7 ^dyninst@=10.2.1 target=x86_64:",
"gcc@4.4.7 languages=c,cxx,fortran", "gcc@4.4.7 languages=c,c++,fortran",
"core2", "core2",
), ),
("mpileaks%gcc@=4.8 target=x86_64:", "gcc@4.8 languages=c,cxx,fortran", "haswell"), ("mpileaks%gcc@=4.8 target=x86_64:", "gcc@4.8 languages=c,c++,fortran", "haswell"),
( (
"mpileaks%gcc@=5.3.0 target=x86_64:", "mpileaks%gcc@=5.3.0 target=x86_64:",
"gcc@5.3.0 languages=c,cxx,fortran", "gcc@5.3.0 languages=c,c++,fortran",
"broadwell", "broadwell",
), ),
], ],
@ -990,7 +973,6 @@ def test_concretize_anonymous_dep(self, spec_str):
("bowtie@1.4.0", "%gcc@10.2.1"), ("bowtie@1.4.0", "%gcc@10.2.1"),
# Version with conflicts and no valid gcc select another compiler # Version with conflicts and no valid gcc select another compiler
("bowtie@1.3.0", "%clang@15.0.0"), ("bowtie@1.3.0", "%clang@15.0.0"),
# FIXME (compiler as nodes): does this make sense?
# If a higher gcc is available, with a worse os, still prefer that # If a higher gcc is available, with a worse os, still prefer that
("bowtie@1.2.2", "%gcc@11.1.0"), ("bowtie@1.2.2", "%gcc@11.1.0"),
], ],
@ -1402,8 +1384,7 @@ def test_reuse_with_flags(self, mutable_database, mutable_config):
spack.config.set("concretizer:reuse", True) spack.config.set("concretizer:reuse", True)
spec = spack.concretize.concretize_one("pkg-a cflags=-g cxxflags=-g") spec = spack.concretize.concretize_one("pkg-a cflags=-g cxxflags=-g")
PackageInstaller([spec.package], fake=True, explicit=True).install() PackageInstaller([spec.package], fake=True, explicit=True).install()
testspec = Spec("pkg-a cflags=-g") testspec = spack.concretize.concretize_one("pkg-a cflags=-g")
testspec.concretize()
assert testspec == spec, testspec.tree() assert testspec == spec, testspec.tree()
@pytest.mark.regression("20784") @pytest.mark.regression("20784")
@ -1461,31 +1442,6 @@ def test_external_with_non_default_variant_as_dependency(self):
assert "~bar" in s["external-non-default-variant"] assert "~bar" in s["external-non-default-variant"]
assert s["external-non-default-variant"].external assert s["external-non-default-variant"].external
# FIXME (compiler as nodes): revisit this test
# @pytest.mark.regression("22871")
# @pytest.mark.parametrize(
# "spec_str,expected_os",
# [
# ("mpileaks", "os=debian6"),
# # To trigger the bug in 22871 we need to have the same compiler
# # spec available on both operating systems
# ("mpileaks%gcc@10.2.1 platform=test os=debian6", "os=debian6"),
# ("mpileaks%gcc@10.2.1 platform=test os=redhat6", "os=redhat6"),
# ],
# )
# def test_os_selection_when_multiple_choices_are_possible(
# self, spec_str, expected_os, compiler_factory
# ):
# # GCC 10.2.1 is defined both for debian and for redhat
# with spack.config.override(
# "packages", {"gcc": {"externals": [compiler_factory(spec="gcc@10.2.1 os=redhat6")]}}
# ):
# s = spack.concretize.concretize_one(spec_str)
# for node in s.traverse():
# if node.name == "glibc":
# continue
# assert node.satisfies(expected_os)
@pytest.mark.regression("22718") @pytest.mark.regression("22718")
@pytest.mark.parametrize( @pytest.mark.parametrize(
"spec_str,expected_compiler", "spec_str,expected_compiler",
@ -1783,12 +1739,11 @@ def test_reuse_with_unknown_package_dont_raise(self, tmpdir, temporary_store, mo
(["libdwarf%gcc", "libelf%clang"], {"libdwarf": 1, "libelf": 1}), (["libdwarf%gcc", "libelf%clang"], {"libdwarf": 1, "libelf": 1}),
(["libdwarf%gcc", "libdwarf%clang"], {"libdwarf": 2, "libelf": 1}), (["libdwarf%gcc", "libdwarf%clang"], {"libdwarf": 2, "libelf": 1}),
(["libdwarf^libelf@0.8.12", "libdwarf^libelf@0.8.13"], {"libdwarf": 2, "libelf": 2}), (["libdwarf^libelf@0.8.12", "libdwarf^libelf@0.8.13"], {"libdwarf": 2, "libelf": 2}),
# FIXME (compiler as nodes): fix these (["hdf5", "zmpi"], {"zmpi": 1, "fake": 1}),
# (["hdf5", "zmpi"], 3, 1), (["hdf5", "mpich"], {"mpich": 1}),
# (["hdf5", "mpich"], 2, 1), (["hdf5^zmpi", "mpich"], {"mpi": 2, "mpich": 1, "zmpi": 1, "fake": 1}),
# (["hdf5^zmpi", "mpich"], 4, 1), (["mpi", "zmpi"], {"mpi": 1, "mpich": 0, "zmpi": 1, "fake": 1}),
# (["mpi", "zmpi"], 2, 1), (["mpi", "mpich"], {"mpi": 1, "mpich": 1, "zmpi": 0}),
# (["mpi", "mpich"], 1, 1),
], ],
) )
def test_best_effort_coconcretize(self, specs, checks): def test_best_effort_coconcretize(self, specs, checks):
@ -1800,9 +1755,13 @@ def test_best_effort_coconcretize(self, specs, checks):
for s in result.specs: for s in result.specs:
concrete_specs.update(s.traverse()) concrete_specs.update(s.traverse())
for x in concrete_specs:
print(x.tree(hashes=True))
print()
for matching_spec, expected_count in checks.items(): for matching_spec, expected_count in checks.items():
matches = [x for x in concrete_specs if x.satisfies(matching_spec)] matches = [x for x in concrete_specs if x.satisfies(matching_spec)]
assert len(matches) == expected_count, matching_spec assert len(matches) == expected_count
@pytest.mark.parametrize( @pytest.mark.parametrize(
"specs,expected_spec,occurances", "specs,expected_spec,occurances",
@ -2219,10 +2178,19 @@ def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages):
solver.driver.solve(setup, specs, reuse=[]) solver.driver.solve(setup, specs, reuse=[])
@pytest.mark.regression("43141") @pytest.mark.regression("43141")
def test_clear_error_when_unknown_compiler_requested(self, mock_packages): @pytest.mark.parametrize(
"spec_str,expected_match",
[
# A package does not exist
("pkg-a ^foo", "since 'foo' does not exist"),
# Request a compiler for a package that doesn't need it
("pkg-c %gcc", "according to its recipe"),
],
)
def test_errors_on_statically_checked_preconditions(self, spec_str, expected_match):
"""Tests that the solver can report a case where the compiler cannot be set""" """Tests that the solver can report a case where the compiler cannot be set"""
with pytest.raises(spack.error.UnsatisfiableSpecError, match="since 'foo' does not exist"): with pytest.raises(spack.error.UnsatisfiableSpecError, match=expected_match):
spack.concretize.concretize_one("pkg-a %foo") spack.concretize.concretize_one(spec_str)
@pytest.mark.regression("36339") @pytest.mark.regression("36339")
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -493,7 +493,7 @@ def test_default_requirements_with_all(spec_str, requirement_str, concretize_sco
spec = spack.concretize.concretize_one(spec_str) spec = spack.concretize.concretize_one(spec_str)
assert "c" in spec assert "c" in spec
for s in spec.traverse(): for s in spec.traverse():
if "c" in s: if "c" in s and s.name not in ("gcc", "llvm"):
assert s.satisfies(requirement_str) assert s.satisfies(requirement_str)

View File

@ -275,10 +275,10 @@ def test_add_config_path(mutable_config):
assert set_value == "/path/to/config.yaml" assert set_value == "/path/to/config.yaml"
# Now a package:all setting # Now a package:all setting
path = "packages:all:compiler:[gcc]" path = "packages:all:target:[x86_64]"
spack.config.add(path) spack.config.add(path)
compilers = spack.config.get("packages")["all"]["compiler"] targets = spack.config.get("packages")["all"]["target"]
assert "gcc" in compilers assert "x86_64" in targets
# Try quotes to escape brackets # Try quotes to escape brackets
path = ( path = (
@ -922,7 +922,6 @@ def test_single_file_scope(config, env_yaml):
# from the single-file config # from the single-file config
assert spack.config.get("config:verify_ssl") is False assert spack.config.get("config:verify_ssl") is False
assert spack.config.get("config:dirty") is False assert spack.config.get("config:dirty") is False
assert spack.config.get("packages:all:compiler") == ["gcc@4.5.3", "gcc", "clang"]
# from the lower config scopes # from the lower config scopes
assert spack.config.get("config:checksum") is True assert spack.config.get("config:checksum") is True
@ -946,7 +945,7 @@ def test_single_file_scope_section_override(tmpdir, config):
verify_ssl: False verify_ssl: False
packages:: packages::
all: all:
compiler: [ 'gcc@4.5.3' ] target: [ x86_64 ]
repos: repos:
- /x/y/z - /x/y/z
""" """
@ -959,7 +958,7 @@ def test_single_file_scope_section_override(tmpdir, config):
with spack.config.override(scope): with spack.config.override(scope):
# from the single-file config # from the single-file config
assert spack.config.get("config:verify_ssl") is False assert spack.config.get("config:verify_ssl") is False
assert spack.config.get("packages:all:compiler") == ["gcc@4.5.3"] assert spack.config.get("packages:all:target") == ["x86_64"]
# from the lower config scopes # from the lower config scopes
assert spack.config.get("config:checksum") is True assert spack.config.get("config:checksum") is True
@ -1224,10 +1223,10 @@ def test_user_config_path_is_default_when_env_var_is_empty(working_env):
def test_default_install_tree(monkeypatch, default_config): def test_default_install_tree(monkeypatch, default_config):
s = spack.spec.Spec("nonexistent@x.y.z %none@a.b.c arch=foo-bar-baz") s = spack.spec.Spec("nonexistent@x.y.z arch=foo-bar-baz")
monkeypatch.setattr(s, "dag_hash", lambda length: "abc123") monkeypatch.setattr(s, "dag_hash", lambda length: "abc123")
_, _, projections = spack.store.parse_install_tree(spack.config.get("config")) _, _, projections = spack.store.parse_install_tree(spack.config.get("config"))
assert s.format(projections["all"]) == "foo-bar-baz/none-a.b.c/nonexistent-x.y.z-abc123" assert s.format(projections["all"]) == "foo/baz/nonexistent-x.y.z-abc123"
def test_local_config_can_be_disabled(working_env): def test_local_config_can_be_disabled(working_env):
@ -1298,7 +1297,7 @@ def test_config_collect_urls(mutable_empty_config, mock_spider_configs, url, isf
(github_url.format("tree"), False, False), (github_url.format("tree"), False, False),
(gitlab_url, False, False), (gitlab_url, False, False),
("{0}/README.md".format(github_url.format("blob")), True, True), ("{0}/README.md".format(github_url.format("blob")), True, True),
("{0}/compilers.yaml".format(gitlab_url), True, False), ("{0}/packages.yaml".format(gitlab_url), True, False),
(None, False, True), (None, False, True),
], ],
) )

View File

@ -95,11 +95,11 @@ def upstream_and_downstream_db(tmpdir, gen_mock_layout):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"install_tree,result", "install_tree,result",
[ [
("all", ["pkg-b", "pkg-c"]), ("all", ["pkg-b", "pkg-c", "gcc-runtime", "gcc"]),
("upstream", ["pkg-c"]), ("upstream", ["pkg-c"]),
("local", ["pkg-b"]), ("local", ["pkg-b", "gcc-runtime", "gcc"]),
("{u}", ["pkg-c"]), ("{u}", ["pkg-c"]),
("{d}", ["pkg-b"]), ("{d}", ["pkg-b", "gcc-runtime", "gcc"]),
], ],
ids=["all", "upstream", "local", "upstream_path", "downstream_path"], ids=["all", "upstream", "local", "upstream_path", "downstream_path"],
) )
@ -117,7 +117,7 @@ def test_query_by_install_tree(
down_db.add(b) down_db.add(b)
specs = down_db.query(install_tree=install_tree.format(u=up_db.root, d=down_db.root)) specs = down_db.query(install_tree=install_tree.format(u=up_db.root, d=down_db.root))
assert [s.name for s in specs] == result assert {s.name for s in specs} == set(result)
def test_spec_installed_upstream( def test_spec_installed_upstream(
@ -491,7 +491,7 @@ def test_005_db_exists(database):
def test_010_all_install_sanity(database): def test_010_all_install_sanity(database):
"""Ensure that the install layout reflects what we think it does.""" """Ensure that the install layout reflects what we think it does."""
all_specs = spack.store.STORE.layout.all_specs() all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 15 assert len(all_specs) == 16
# Query specs with multiple configurations # Query specs with multiple configurations
mpileaks_specs = [s for s in all_specs if s.satisfies("mpileaks")] mpileaks_specs = [s for s in all_specs if s.satisfies("mpileaks")]
@ -608,7 +608,7 @@ def test_050_basic_query(database):
"""Ensure querying database is consistent with what is installed.""" """Ensure querying database is consistent with what is installed."""
# query everything # query everything
total_specs = len(spack.store.STORE.db.query()) total_specs = len(spack.store.STORE.db.query())
assert total_specs == 17 assert total_specs == 19
# query specs with multiple configurations # query specs with multiple configurations
mpileaks_specs = database.query("mpileaks") mpileaks_specs = database.query("mpileaks")
@ -827,11 +827,11 @@ def check_unused(roots, deptype, expected):
assert set(u.name for u in unused) == set(expected) assert set(u.name for u in unused) == set(expected)
default_dt = dt.LINK | dt.RUN default_dt = dt.LINK | dt.RUN
check_unused(None, default_dt, ["cmake"]) check_unused(None, default_dt, ["cmake", "gcc"])
check_unused( check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi, externaltest], [si, ml_mpich, ml_mpich2, ml_zmpi, externaltest],
default_dt, default_dt,
["trivial-smoke-test", "cmake"], ["trivial-smoke-test", "cmake", "gcc"],
) )
check_unused( check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi, externaltest], [si, ml_mpich, ml_mpich2, ml_zmpi, externaltest],
@ -846,7 +846,7 @@ def check_unused(roots, deptype, expected):
check_unused( check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi], [si, ml_mpich, ml_mpich2, ml_zmpi],
default_dt, default_dt,
["trivial-smoke-test", "cmake", "externaltest", "externaltool", "externalvirtual"], ["trivial-smoke-test", "cmake", "externaltest", "externaltool", "externalvirtual", "gcc"],
) )
@ -1080,7 +1080,7 @@ def test_check_parents(spec_str, parent_name, expected_nparents, database):
def test_db_all_hashes(database): def test_db_all_hashes(database):
# ensure we get the right number of hashes without a read transaction # ensure we get the right number of hashes without a read transaction
hashes = database.all_hashes() hashes = database.all_hashes()
assert len(hashes) == 17 assert len(hashes) == 19
# and make sure the hashes match # and make sure the hashes match
with database.read_transaction(): with database.read_transaction():

View File

@ -34,11 +34,7 @@ def test_yaml_directory_layout_parameters(tmpdir, default_mock_concretization):
layout_default = DirectoryLayout(str(tmpdir)) layout_default = DirectoryLayout(str(tmpdir))
path_default = layout_default.relative_path_for_spec(spec) path_default = layout_default.relative_path_for_spec(spec)
assert path_default == str( assert path_default == str(
Path( Path(spec.format("{architecture.platform}/{architecture.target}/{name}-{version}-{hash}"))
spec.format(
"{architecture}/" "{compiler.name}-{compiler.version}/" "{name}-{version}-{hash}"
)
)
) )
# Test hash_length parameter works correctly # Test hash_length parameter works correctly

View File

@ -46,44 +46,63 @@ def test_ascii_graph_mpileaks(config, mock_packages, monkeypatch):
graph_str = stream.getvalue() graph_str = stream.getvalue()
graph_str = "\n".join([line.rstrip() for line in graph_str.split("\n")]) graph_str = "\n".join([line.rstrip() for line in graph_str.split("\n")])
print(graph_str)
assert ( assert (
graph_str graph_str
== r"""o mpileaks == r"""o mpileaks
|\ |\
| o callpath
|/|
o | mpich
/
o dyninst
|\
| o libdwarf
|/
o libelf
"""
or graph_str
== r"""o mpileaks
|\
o | callpath
|\|
| o mpich
|
o dyninst
|\
o | libdwarf
|/
o libelf
"""
or graph_str
== r"""o mpileaks
|\
| o callpath
|/|
| o dyninst
| |\ | |\
o | | mpich | | |\
/ / | | | o callpath
| o libdwarf | |_|/|
|/| |/|
| |/|/|
o | | | mpich
|\| | |
| |/ /
|/| |
| | o dyninst
| |/|
|/|/|
| | |\
| | | o libdwarf
| |_|/|
|/| |/|
| |/|/
| | o libelf
| |/|
|/|/
| o gcc-runtime
|/ |/
o libelf o gcc
"""
or graph_str
== r"""o mpileaks
|\
| |\
| | |\
| | | o callpath
| |_|/|
|/| |/|
| |/|/|
| | | o dyninst
| | |/|
| |/|/|
| | | |\
o | | | | mpich
|\| | | |
| |/ / /
|/| | |
| | | o libdwarf
| |_|/|
|/| |/|
| |/|/
| | o libelf
| |/|
|/|/
| o gcc-runtime
|/
o gcc
""" """
) )

View File

@ -1018,8 +1018,8 @@ def test_install_fail_multi(install_mockery, mock_fetch, monkeypatch):
def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys): def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys):
"""Test fail_fast install when an install failure is detected.""" """Test fail_fast install when an install failure is detected."""
b = spack.concretize.concretize_one("pkg-b") # Note: this test depends on the order of the installations
c = spack.concretize.concretize_one("pkg-c") b, c = spack.concretize.concretize_one("pkg-b"), spack.concretize.concretize_one("pkg-c")
b_id, c_id = inst.package_id(b), inst.package_id(c) b_id, c_id = inst.package_id(b), inst.package_id(c)
installer = create_installer([b, c], {"fail_fast": True}) installer = create_installer([b, c], {"fail_fast": True})
@ -1031,9 +1031,9 @@ def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys):
with pytest.raises(spack.error.InstallError, match="after first install failure"): with pytest.raises(spack.error.InstallError, match="after first install failure"):
installer.install() installer.install()
assert b_id in installer.failed, "Expected b to be marked as failed" assert c_id in installer.failed, "Expected b to be marked as failed"
assert c_id not in installer.failed, "Expected no attempt to install pkg-c" assert b_id not in installer.failed, "Expected no attempt to install pkg-c"
assert f"{b_id} failed to install" in capsys.readouterr().err assert f"{c_id} failed to install" in capsys.readouterr().err
def _test_install_fail_fast_on_except_patch(installer, **kwargs): def _test_install_fail_fast_on_except_patch(installer, **kwargs):
@ -1066,10 +1066,11 @@ def test_install_fail_fast_on_except(install_mockery, monkeypatch, capsys):
def test_install_lock_failures(install_mockery, monkeypatch, capfd): def test_install_lock_failures(install_mockery, monkeypatch, capfd):
"""Cover basic install lock failure handling in a single pass.""" """Cover basic install lock failure handling in a single pass."""
# Note: this test relies on installing a package with no dependencies
def _requeued(installer, task, install_status): def _requeued(installer, task, install_status):
tty.msg("requeued {0}".format(task.pkg.spec.name)) tty.msg("requeued {0}".format(task.pkg.spec.name))
installer = create_installer(["pkg-b"], {}) installer = create_installer(["pkg-c"], {})
# Ensure never acquire a lock # Ensure never acquire a lock
monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked) monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked)
@ -1088,13 +1089,14 @@ def _requeued(installer, task, install_status):
def test_install_lock_installed_requeue(install_mockery, monkeypatch, capfd): def test_install_lock_installed_requeue(install_mockery, monkeypatch, capfd):
"""Cover basic install handling for installed package.""" """Cover basic install handling for installed package."""
b = spack.concretize.concretize_one("pkg-b") # Note: this test relies on installing a package with no dependencies
b_pkg_id = inst.package_id(b) concrete_spec = spack.concretize.concretize_one("pkg-c")
installer = create_installer([b]) pkg_id = inst.package_id(concrete_spec)
installer = create_installer([concrete_spec])
def _prep(installer, task): def _prep(installer, task):
installer.installed.add(b_pkg_id) installer.installed.add(pkg_id)
tty.msg(f"{b_pkg_id} is installed") tty.msg(f"{pkg_id} is installed")
# also do not allow the package to be locked again # also do not allow the package to be locked again
monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked) monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked)
@ -1111,7 +1113,7 @@ def _requeued(installer, task, install_status):
with pytest.raises(spack.error.InstallError, match="request failed"): with pytest.raises(spack.error.InstallError, match="request failed"):
installer.install() installer.install()
assert b_pkg_id not in installer.installed assert pkg_id not in installer.installed
expected = ["is installed", "read locked", "requeued"] expected = ["is installed", "read locked", "requeued"]
for exp, ln in zip(expected, capfd.readouterr().out.splitlines()): for exp, ln in zip(expected, capfd.readouterr().out.splitlines()):
@ -1120,6 +1122,7 @@ def _requeued(installer, task, install_status):
def test_install_read_locked_requeue(install_mockery, monkeypatch, capfd): def test_install_read_locked_requeue(install_mockery, monkeypatch, capfd):
"""Cover basic read lock handling for uninstalled package with requeue.""" """Cover basic read lock handling for uninstalled package with requeue."""
# Note: this test relies on installing a package with no dependencies
orig_fn = inst.PackageInstaller._ensure_locked orig_fn = inst.PackageInstaller._ensure_locked
def _read(installer, lock_type, pkg): def _read(installer, lock_type, pkg):
@ -1142,7 +1145,7 @@ def _requeued(installer, task, install_status):
# Ensure don't continually requeue the task # Ensure don't continually requeue the task
monkeypatch.setattr(inst.PackageInstaller, "_requeue_task", _requeued) monkeypatch.setattr(inst.PackageInstaller, "_requeue_task", _requeued)
installer = create_installer(["pkg-b"], {}) installer = create_installer(["pkg-c"], {})
with pytest.raises(spack.error.InstallError, match="request failed"): with pytest.raises(spack.error.InstallError, match="request failed"):
installer.install() installer.install()
@ -1157,7 +1160,8 @@ def _requeued(installer, task, install_status):
def test_install_skip_patch(install_mockery, mock_fetch): def test_install_skip_patch(install_mockery, mock_fetch):
"""Test the path skip_patch install path.""" """Test the path skip_patch install path."""
installer = create_installer(["pkg-b"], {"fake": False, "skip_patch": True}) # Note: this test relies on installing a package with no dependencies
installer = create_installer(["pkg-c"], {"fake": False, "skip_patch": True})
installer.install() installer.install()
assert inst.package_id(installer.build_requests[0].pkg.spec) in installer.installed assert inst.package_id(installer.build_requests[0].pkg.spec) in installer.installed
@ -1177,8 +1181,9 @@ def test_overwrite_install_backup_success(temporary_store, config, mock_packages
When doing an overwrite install that fails, Spack should restore the backup When doing an overwrite install that fails, Spack should restore the backup
of the original prefix, and leave the original spec marked installed. of the original prefix, and leave the original spec marked installed.
""" """
# Note: this test relies on installing a package with no dependencies
# Get a build task. TODO: refactor this to avoid calling internal methods # Get a build task. TODO: refactor this to avoid calling internal methods
installer = create_installer(["pkg-b"]) installer = create_installer(["pkg-c"])
installer._init_queue() installer._init_queue()
task = installer._pop_task() task = installer._pop_task()
@ -1219,6 +1224,7 @@ def test_overwrite_install_backup_failure(temporary_store, config, mock_packages
original prefix. If that fails, the spec is lost, and it should be removed original prefix. If that fails, the spec is lost, and it should be removed
from the database. from the database.
""" """
# Note: this test relies on installing a package with no dependencies
class InstallerThatAccidentallyDeletesTheBackupDir: class InstallerThatAccidentallyDeletesTheBackupDir:
def _install_task(self, task, install_status): def _install_task(self, task, install_status):
@ -1238,7 +1244,7 @@ def remove(self, spec):
self.called = True self.called = True
# Get a build task. TODO: refactor this to avoid calling internal methods # Get a build task. TODO: refactor this to avoid calling internal methods
installer = create_installer(["pkg-b"]) installer = create_installer(["pkg-c"])
installer._init_queue() installer._init_queue()
task = installer._pop_task() task = installer._pop_task()

View File

@ -7,6 +7,7 @@
import pytest import pytest
import spack.compilers.libraries
import spack.paths import spack.paths
from spack.compilers.libraries import parse_non_system_link_dirs from spack.compilers.libraries import parse_non_system_link_dirs

View File

@ -6,7 +6,6 @@
import re import re
import sys import sys
from datetime import datetime, timedelta from datetime import datetime, timedelta
from textwrap import dedent
import pytest import pytest
@ -290,13 +289,6 @@ def inner():
with h.forward("top-level"): with h.forward("top-level"):
raise TypeError("ok") raise TypeError("ok")
assert h.grouped_message(with_tracebacks=False) == dedent(
"""\
due to the following failures:
inner method raised ValueError: wow!
top-level raised TypeError: ok"""
)
def test_grouped_exception_base_type(): def test_grouped_exception_base_type():
h = llnl.util.lang.GroupedExceptionHandler() h = llnl.util.lang.GroupedExceptionHandler()

View File

@ -112,7 +112,7 @@ def test_compilers_provided_different_name(
self, factory, module_configuration, compiler_factory self, factory, module_configuration, compiler_factory
): ):
with spack.config.override( with spack.config.override(
"compilers", [compiler_factory(spec="clang@3.3", operating_system="debian6")] "packages", {"llvm": {"externals": [compiler_factory(spec="llvm@3.3")]}}
): ):
module_configuration("complex_hierarchy") module_configuration("complex_hierarchy")
module, spec = factory("intel-oneapi-compilers%clang@3.3") module, spec = factory("intel-oneapi-compilers%clang@3.3")
@ -120,7 +120,7 @@ def test_compilers_provided_different_name(
provides = module.conf.provides provides = module.conf.provides
assert "compiler" in provides assert "compiler" in provides
assert provides["compiler"] == spack.spec.CompilerSpec("oneapi@=3.0") assert provides["compiler"] == spack.spec.Spec("intel-oneapi-compilers@=3.0")
def test_simple_case(self, modulefile_content, module_configuration): def test_simple_case(self, modulefile_content, module_configuration):
"""Tests the generation of a simple Lua module file.""" """Tests the generation of a simple Lua module file."""
@ -139,7 +139,7 @@ def test_autoload_direct(self, modulefile_content, module_configuration):
module_configuration("autoload_direct") module_configuration("autoload_direct")
content = modulefile_content(mpileaks_spec_string) content = modulefile_content(mpileaks_spec_string)
assert len([x for x in content if "depends_on(" in x]) == 2 assert len([x for x in content if "depends_on(" in x]) == 3
def test_autoload_all(self, modulefile_content, module_configuration): def test_autoload_all(self, modulefile_content, module_configuration):
"""Tests the automatic loading of all dependencies.""" """Tests the automatic loading of all dependencies."""
@ -147,7 +147,7 @@ def test_autoload_all(self, modulefile_content, module_configuration):
module_configuration("autoload_all") module_configuration("autoload_all")
content = modulefile_content(mpileaks_spec_string) content = modulefile_content(mpileaks_spec_string)
assert len([x for x in content if "depends_on(" in x]) == 5 assert len([x for x in content if "depends_on(" in x]) == 6
def test_alter_environment(self, modulefile_content, module_configuration): def test_alter_environment(self, modulefile_content, module_configuration):
"""Tests modifications to run-time environment.""" """Tests modifications to run-time environment."""
@ -265,7 +265,7 @@ def test_exclude(self, modulefile_content, module_configuration):
module_configuration("exclude") module_configuration("exclude")
content = modulefile_content(mpileaks_spec_string) content = modulefile_content(mpileaks_spec_string)
assert len([x for x in content if "depends_on(" in x]) == 1 assert len([x for x in content if "depends_on(" in x]) == 2
def test_no_hash(self, factory, module_configuration): def test_no_hash(self, factory, module_configuration):
"""Makes sure that virtual providers (in the hierarchy) always """Makes sure that virtual providers (in the hierarchy) always
@ -372,7 +372,7 @@ def test_guess_core_compilers(self, factory, module_configuration, monkeypatch):
module_configuration("missing_core_compilers") module_configuration("missing_core_compilers")
# Our mock paths must be detected as system paths # Our mock paths must be detected as system paths
monkeypatch.setattr(spack.util.environment, "SYSTEM_DIRS", ["/path/to"]) monkeypatch.setattr(spack.util.environment, "SYSTEM_DIRS", ["/path/bin"])
# We don't want to really write into user configuration # We don't want to really write into user configuration
# when running tests # when running tests
@ -434,7 +434,7 @@ def test_modules_relative_to_view(
): ):
with ev.create_in_dir(str(tmpdir), with_view=True) as e: with ev.create_in_dir(str(tmpdir), with_view=True) as e:
module_configuration("with_view") module_configuration("with_view")
install("--add", "cmake") install("--fake", "--add", "cmake")
spec = spack.concretize.concretize_one("cmake") spec = spack.concretize.concretize_one("cmake")

View File

@ -45,8 +45,8 @@ def test_autoload_direct(self, modulefile_content, module_configuration):
len([x for x in content if "if {![info exists ::env(LMOD_VERSION_MAJOR)]} {" in x]) len([x for x in content if "if {![info exists ::env(LMOD_VERSION_MAJOR)]} {" in x])
== 1 == 1
) )
assert len([x for x in content if "depends-on " in x]) == 2 assert len([x for x in content if "depends-on " in x]) == 3
assert len([x for x in content if "module load " in x]) == 2 assert len([x for x in content if "module load " in x]) == 3
# dtbuild1 has # dtbuild1 has
# - 1 ('run',) dependency # - 1 ('run',) dependency
@ -76,8 +76,8 @@ def test_autoload_all(self, modulefile_content, module_configuration):
len([x for x in content if "if {![info exists ::env(LMOD_VERSION_MAJOR)]} {" in x]) len([x for x in content if "if {![info exists ::env(LMOD_VERSION_MAJOR)]} {" in x])
== 1 == 1
) )
assert len([x for x in content if "depends-on " in x]) == 5 assert len([x for x in content if "depends-on " in x]) == 6
assert len([x for x in content if "module load " in x]) == 5 assert len([x for x in content if "module load " in x]) == 6
# dtbuild1 has # dtbuild1 has
# - 1 ('run',) dependency # - 1 ('run',) dependency
@ -101,7 +101,7 @@ def test_prerequisites_direct(
module_configuration("prerequisites_direct") module_configuration("prerequisites_direct")
content = modulefile_content(f"mpileaks target={host_architecture_str}") content = modulefile_content(f"mpileaks target={host_architecture_str}")
assert len([x for x in content if "prereq" in x]) == 2 assert len([x for x in content if "prereq" in x]) == 3
def test_prerequisites_all( def test_prerequisites_all(
self, modulefile_content, module_configuration, host_architecture_str self, modulefile_content, module_configuration, host_architecture_str
@ -111,7 +111,7 @@ def test_prerequisites_all(
module_configuration("prerequisites_all") module_configuration("prerequisites_all")
content = modulefile_content(f"mpileaks target={host_architecture_str}") content = modulefile_content(f"mpileaks target={host_architecture_str}")
assert len([x for x in content if "prereq" in x]) == 5 assert len([x for x in content if "prereq" in x]) == 6
def test_alter_environment(self, modulefile_content, module_configuration): def test_alter_environment(self, modulefile_content, module_configuration):
"""Tests modifications to run-time environment.""" """Tests modifications to run-time environment."""
@ -236,14 +236,14 @@ def test_exclude(self, modulefile_content, module_configuration, host_architectu
module_configuration("exclude") module_configuration("exclude")
content = modulefile_content("mpileaks ^zmpi") content = modulefile_content("mpileaks ^zmpi")
assert len([x for x in content if "module load " in x]) == 1 assert len([x for x in content if "module load " in x]) == 2
with pytest.raises(FileNotFoundError): with pytest.raises(FileNotFoundError):
modulefile_content(f"callpath target={host_architecture_str}") modulefile_content(f"callpath target={host_architecture_str}")
content = modulefile_content(f"zmpi target={host_architecture_str}") content = modulefile_content(f"zmpi target={host_architecture_str}")
assert len([x for x in content if "module load " in x]) == 1 assert len([x for x in content if "module load " in x]) == 2
def test_naming_scheme_compat(self, factory, module_configuration): def test_naming_scheme_compat(self, factory, module_configuration):
"""Tests backwards compatibility for naming_scheme key""" """Tests backwards compatibility for naming_scheme key"""
@ -481,8 +481,8 @@ def test_autoload_with_constraints(self, modulefile_content, module_configuratio
# Test the mpileaks that should have the autoloaded dependencies # Test the mpileaks that should have the autoloaded dependencies
content = modulefile_content("mpileaks ^mpich2") content = modulefile_content("mpileaks ^mpich2")
assert len([x for x in content if "depends-on " in x]) == 2 assert len([x for x in content if "depends-on " in x]) == 3
assert len([x for x in content if "module load " in x]) == 2 assert len([x for x in content if "module load " in x]) == 3
# Test the mpileaks that should NOT have the autoloaded dependencies # Test the mpileaks that should NOT have the autoloaded dependencies
content = modulefile_content("mpileaks ^mpich") content = modulefile_content("mpileaks ^mpich")

View File

@ -7,7 +7,6 @@
import pytest import pytest
import spack.concretize import spack.concretize
import spack.config
import spack.platforms import spack.platforms
from spack.multimethod import NoSuchMethodError from spack.multimethod import NoSuchMethodError
@ -53,7 +52,7 @@ def test_no_version_match(pkg_name):
# Constraints on compilers with a default # Constraints on compilers with a default
("%gcc", "has_a_default", "gcc"), ("%gcc", "has_a_default", "gcc"),
("%clang", "has_a_default", "clang"), ("%clang", "has_a_default", "clang"),
("%apple-clang os=elcapitan", "has_a_default", "default"), ("%gcc@9", "has_a_default", "default"),
# Constraints on dependencies # Constraints on dependencies
("^zmpi", "different_by_dep", "zmpi"), ("^zmpi", "different_by_dep", "zmpi"),
("^mpich", "different_by_dep", "mpich"), ("^mpich", "different_by_dep", "mpich"),
@ -68,13 +67,9 @@ def test_no_version_match(pkg_name):
], ],
) )
def test_multimethod_calls( def test_multimethod_calls(
pkg_name, constraint_str, method_name, expected_result, compiler_factory pkg_name, constraint_str, method_name, expected_result, default_mock_concretization
): ):
# Add apple-clang, as it is required by one of the tests s = default_mock_concretization(f"{pkg_name}{constraint_str}")
with spack.config.override(
"compilers", [compiler_factory(spec="apple-clang@9.1.0", operating_system="elcapitan")]
):
s = spack.concretize.concretize_one(pkg_name + constraint_str)
msg = f"Method {method_name} from {s} is giving a wrong result" msg = f"Method {method_name} from {s} is giving a wrong result"
assert getattr(s.package, method_name)() == expected_result, msg assert getattr(s.package, method_name)() == expected_result, msg

View File

@ -16,7 +16,6 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import spack.binary_distribution import spack.binary_distribution
import spack.compilers.config
import spack.concretize import spack.concretize
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
@ -30,21 +29,28 @@
from spack.solver.input_analysis import NoStaticAnalysis, StaticAnalysis from spack.solver.input_analysis import NoStaticAnalysis, StaticAnalysis
@pytest.fixture(scope="module")
def compiler_names(mock_repo_path):
return [spec.name for spec in mock_repo_path.providers_for("c")]
@pytest.fixture() @pytest.fixture()
def mpileaks_possible_deps(mock_packages, mpi_names): def mpileaks_possible_deps(mock_packages, mpi_names, compiler_names):
possible = { possible = {
"callpath": set(["dyninst"] + mpi_names), "callpath": set(["dyninst"] + mpi_names + compiler_names),
"low-priority-provider": set(), "low-priority-provider": set(),
"dyninst": set(["libdwarf", "libelf"]), "dyninst": set(["libdwarf", "libelf"] + compiler_names),
"fake": set(), "fake": set(),
"gcc": set(),
"intel-parallel-studio": set(), "intel-parallel-studio": set(),
"libdwarf": set(["libelf"]), "libdwarf": set(["libelf"] + compiler_names),
"libelf": set(), "libelf": set(compiler_names),
"mpich": set(), "llvm": set(),
"mpich2": set(), "mpich": set(compiler_names),
"mpileaks": set(["callpath"] + mpi_names), "mpich2": set(compiler_names),
"mpileaks": set(["callpath"] + mpi_names + compiler_names),
"multi-provider-mpi": set(), "multi-provider-mpi": set(),
"zmpi": set(["fake"]), "zmpi": set(["fake"] + compiler_names),
} }
return possible return possible
@ -76,6 +82,8 @@ def mpi_names(mock_inspector):
{ {
"fake", "fake",
"mpileaks", "mpileaks",
"gcc",
"llvm",
"multi-provider-mpi", "multi-provider-mpi",
"callpath", "callpath",
"dyninst", "dyninst",
@ -113,8 +121,13 @@ def test_possible_dependencies(pkg_name, fn_kwargs, expected, mock_runtimes, moc
def test_possible_dependencies_virtual(mock_inspector, mock_packages, mock_runtimes, mpi_names): def test_possible_dependencies_virtual(mock_inspector, mock_packages, mock_runtimes, mpi_names):
expected = set(mpi_names) expected = set(mpi_names)
for name in mpi_names: for name in mpi_names:
expected.update(dep for dep in mock_packages.get_pkg_class(name).dependencies_by_name()) expected.update(
dep
for dep in mock_packages.get_pkg_class(name).dependencies_by_name()
if not mock_packages.is_virtual(dep)
)
expected.update(mock_runtimes) expected.update(mock_runtimes)
expected.update(s.name for s in mock_packages.providers_for("c"))
real_pkgs, *_ = mock_inspector.possible_dependencies( real_pkgs, *_ = mock_inspector.possible_dependencies(
"mpi", transitive=False, allowed_deps=dt.ALL "mpi", transitive=False, allowed_deps=dt.ALL
@ -284,11 +297,9 @@ def test_package_fetcher_fails():
def test_package_test_no_compilers(mock_packages, monkeypatch, capfd): def test_package_test_no_compilers(mock_packages, monkeypatch, capfd):
def compilers(compiler, arch_spec): """Ensures that a test which needs the compiler, and build dependencies, to run, is skipped
return None if no compiler is available.
"""
monkeypatch.setattr(spack.compilers.config, "compilers_for_spec", compilers)
s = spack.spec.Spec("pkg-a") s = spack.spec.Spec("pkg-a")
pkg = BaseTestPackage(s) pkg = BaseTestPackage(s)
pkg.test_requires_compiler = True pkg.test_requires_compiler = True

View File

@ -69,7 +69,7 @@ def test_inheritance_of_directives(self):
# Check dictionaries that should have been filled by directives # Check dictionaries that should have been filled by directives
dependencies = pkg_cls.dependencies_by_name() dependencies = pkg_cls.dependencies_by_name()
assert len(dependencies) == 3 assert len(dependencies) == 4
assert "cmake" in dependencies assert "cmake" in dependencies
assert "openblas" in dependencies assert "openblas" in dependencies
assert "mpi" in dependencies assert "mpi" in dependencies

View File

@ -9,6 +9,7 @@
import spack.concretize import spack.concretize
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.installer
import spack.repo import spack.repo
import spack.util.hash as hashutil import spack.util.hash as hashutil
import spack.version import spack.version
@ -80,8 +81,7 @@ def test_test_deptype(tmpdir):
assert "z" not in spec assert "z" not in spec
@pytest.mark.usefixtures("config") def test_installed_deps(monkeypatch, install_mockery):
def test_installed_deps(monkeypatch, mock_packages):
"""Ensure that concrete specs and their build deps don't constrain solves. """Ensure that concrete specs and their build deps don't constrain solves.
Preinstall a package ``c`` that has a constrained build dependency on ``d``, then Preinstall a package ``c`` that has a constrained build dependency on ``d``, then
@ -101,7 +101,7 @@ def test_installed_deps(monkeypatch, mock_packages):
# |/ \| c --> d build # |/ \| c --> d build
# d e c --> e build/link # d e c --> e build/link
# #
a, b, c, d, e = ["installed-deps-%s" % s for s in "abcde"] a, b, c, d, e = [f"installed-deps-{s}" for s in "abcde"]
# install C, which will force d's version to be 2 # install C, which will force d's version to be 2
# BUT d is only a build dependency of C, so it won't constrain # BUT d is only a build dependency of C, so it won't constrain
@ -110,19 +110,12 @@ def test_installed_deps(monkeypatch, mock_packages):
c_spec = spack.concretize.concretize_one(c) c_spec = spack.concretize.concretize_one(c)
assert c_spec[d].version == spack.version.Version("2") assert c_spec[d].version == spack.version.Version("2")
installed_names = [s.name for s in c_spec.traverse()] spack.installer.PackageInstaller([c_spec.package], fake=True, explicit=True).install()
def _mock_installed(self):
return self.name in installed_names
monkeypatch.setattr(Spec, "installed", _mock_installed)
# install A, which depends on B, C, D, and E, and force A to # install A, which depends on B, C, D, and E, and force A to
# use the installed C. It should *not* force A to use the installed D # use the installed C. It should *not* force A to use the installed D
# *if* we're doing a fresh installation. # *if* we're doing a fresh installation.
a_spec = Spec(a) a_spec = spack.concretize.concretize_one(f"{a} ^/{c_spec.dag_hash()}")
a_spec._add_dependency(c_spec, depflag=dt.BUILD | dt.LINK, virtuals=())
a_spec = spack.concretize.concretize_one(a_spec)
assert spack.version.Version("2") == a_spec[c][d].version assert spack.version.Version("2") == a_spec[c][d].version
assert spack.version.Version("2") == a_spec[e].version assert spack.version.Version("2") == a_spec[e].version
assert spack.version.Version("3") == a_spec[b][d].version assert spack.version.Version("3") == a_spec[b][d].version
@ -183,120 +176,231 @@ def test_conflicting_package_constraints(self, set_dependency):
with pytest.raises(spack.error.UnsatisfiableSpecError): with pytest.raises(spack.error.UnsatisfiableSpecError):
spack.concretize.concretize_one(spec) spack.concretize.concretize_one(spec)
def test_preorder_node_traversal(self): @pytest.mark.parametrize(
dag = spack.concretize.concretize_one("mpileaks ^zmpi") "pairs,traverse_kwargs",
[
# Preorder node traversal
(
[
(0, "mpileaks"),
(1, "callpath"),
(2, "dyninst"),
(3, "gcc"),
(3, "gcc-runtime"),
(3, "libdwarf"),
(4, "libelf"),
(2, "zmpi"),
(3, "fake"),
],
{},
),
# Preorder edge traversal
(
[
(0, "mpileaks"),
(1, "callpath"),
(2, "dyninst"),
(3, "gcc"),
(3, "gcc-runtime"),
(4, "gcc"),
(3, "libdwarf"),
(4, "gcc"),
(4, "gcc-runtime"),
(4, "libelf"),
(5, "gcc"),
(5, "gcc-runtime"),
(3, "libelf"),
(2, "gcc"),
(2, "gcc-runtime"),
(2, "zmpi"),
(3, "fake"),
(3, "gcc"),
(3, "gcc-runtime"),
(1, "gcc"),
(1, "gcc-runtime"),
(1, "zmpi"),
],
{"cover": "edges"},
),
# Preorder path traversal
(
[
(0, "mpileaks"),
(1, "callpath"),
(2, "dyninst"),
(3, "gcc"),
(3, "gcc-runtime"),
(4, "gcc"),
(3, "libdwarf"),
(4, "gcc"),
(4, "gcc-runtime"),
(5, "gcc"),
(4, "libelf"),
(5, "gcc"),
(5, "gcc-runtime"),
(6, "gcc"),
(3, "libelf"),
(4, "gcc"),
(4, "gcc-runtime"),
(5, "gcc"),
(2, "gcc"),
(2, "gcc-runtime"),
(3, "gcc"),
(2, "zmpi"),
(3, "fake"),
(3, "gcc"),
(3, "gcc-runtime"),
(4, "gcc"),
(1, "gcc"),
(1, "gcc-runtime"),
(2, "gcc"),
(1, "zmpi"),
(2, "fake"),
(2, "gcc"),
(2, "gcc-runtime"),
(3, "gcc"),
],
{"cover": "paths"},
),
# Postorder node traversal
(
[
(3, "gcc"),
(3, "gcc-runtime"),
(4, "libelf"),
(3, "libdwarf"),
(2, "dyninst"),
(3, "fake"),
(2, "zmpi"),
(1, "callpath"),
(0, "mpileaks"),
],
{"order": "post"},
),
# Postorder edge traversal
(
[
(3, "gcc"),
(4, "gcc"),
(3, "gcc-runtime"),
(4, "gcc"),
(4, "gcc-runtime"),
(5, "gcc"),
(5, "gcc-runtime"),
(4, "libelf"),
(3, "libdwarf"),
(3, "libelf"),
(2, "dyninst"),
(2, "gcc"),
(2, "gcc-runtime"),
(3, "fake"),
(3, "gcc"),
(3, "gcc-runtime"),
(2, "zmpi"),
(1, "callpath"),
(1, "gcc"),
(1, "gcc-runtime"),
(1, "zmpi"),
(0, "mpileaks"),
],
{"cover": "edges", "order": "post"},
),
# Postorder path traversal
(
[
(3, "gcc"),
(4, "gcc"),
(3, "gcc-runtime"),
(4, "gcc"),
(5, "gcc"),
(4, "gcc-runtime"),
(5, "gcc"),
(6, "gcc"),
(5, "gcc-runtime"),
(4, "libelf"),
(3, "libdwarf"),
(4, "gcc"),
(5, "gcc"),
(4, "gcc-runtime"),
(3, "libelf"),
(2, "dyninst"),
(2, "gcc"),
(3, "gcc"),
(2, "gcc-runtime"),
(3, "fake"),
(3, "gcc"),
(4, "gcc"),
(3, "gcc-runtime"),
(2, "zmpi"),
(1, "callpath"),
(1, "gcc"),
(2, "gcc"),
(1, "gcc-runtime"),
(2, "fake"),
(2, "gcc"),
(3, "gcc"),
(2, "gcc-runtime"),
(1, "zmpi"),
(0, "mpileaks"),
],
{"cover": "paths", "order": "post"},
),
],
)
def test_traversal(self, pairs, traverse_kwargs, default_mock_concretization):
r"""Tests different traversals of the following graph
names = ["mpileaks", "callpath", "dyninst", "libdwarf", "libelf", "zmpi", "fake"] o mpileaks
pairs = list(zip([0, 1, 2, 3, 4, 2, 3], names)) |\
| |\
| | |\
| | | |\
| | | | o callpath
| |_|_|/|
|/| |_|/|
| |/| |/|
| | |/|/|
o | | | | zmpi
|\| | | |
|\ \ \ \ \
| |_|/ / /
|/| | | |
| |\ \ \ \
| | |_|/ /
| |/| | |
| | o | | fake
| | / /
| | | o dyninst
| |_|/|
|/| |/|
| |/|/|
| | | |\
| | | | o libdwarf
| |_|_|/|
|/| |_|/|
| |/| |/|
| | |/|/
| | | o libel
| |_|/|
|/| |/|
| |/|/
o | | gcc-runtime
|\| |
| |/
|/|
o | glibc
/
o gcc
"""
dag = default_mock_concretization("mpileaks ^zmpi")
names = [x for _, x in pairs]
traversal = dag.traverse() traversal = dag.traverse(**traverse_kwargs, depth=True)
assert [x.name for x in traversal] == names
traversal = dag.traverse(depth=True)
assert [(x, y.name) for x, y in traversal] == pairs assert [(x, y.name) for x, y in traversal] == pairs
def test_preorder_edge_traversal(self): traversal = dag.traverse(**traverse_kwargs)
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
names = [
"mpileaks",
"callpath",
"dyninst",
"libdwarf",
"libelf",
"libelf",
"zmpi",
"fake",
"zmpi",
]
pairs = list(zip([0, 1, 2, 3, 4, 3, 2, 3, 1], names))
traversal = dag.traverse(cover="edges")
assert [x.name for x in traversal] == names assert [x.name for x in traversal] == names
traversal = dag.traverse(cover="edges", depth=True)
assert [(x, y.name) for x, y in traversal] == pairs
def test_preorder_path_traversal(self):
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
names = [
"mpileaks",
"callpath",
"dyninst",
"libdwarf",
"libelf",
"libelf",
"zmpi",
"fake",
"zmpi",
"fake",
]
pairs = list(zip([0, 1, 2, 3, 4, 3, 2, 3, 1, 2], names))
traversal = dag.traverse(cover="paths")
assert [x.name for x in traversal] == names
traversal = dag.traverse(cover="paths", depth=True)
assert [(x, y.name) for x, y in traversal] == pairs
def test_postorder_node_traversal(self):
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
names = ["libelf", "libdwarf", "dyninst", "fake", "zmpi", "callpath", "mpileaks"]
pairs = list(zip([4, 3, 2, 3, 2, 1, 0], names))
traversal = dag.traverse(order="post")
assert [x.name for x in traversal] == names
traversal = dag.traverse(depth=True, order="post")
assert [(x, y.name) for x, y in traversal] == pairs
def test_postorder_edge_traversal(self):
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
names = [
"libelf",
"libdwarf",
"libelf",
"dyninst",
"fake",
"zmpi",
"callpath",
"zmpi",
"mpileaks",
]
pairs = list(zip([4, 3, 3, 2, 3, 2, 1, 1, 0], names))
traversal = dag.traverse(cover="edges", order="post")
assert [x.name for x in traversal] == names
traversal = dag.traverse(cover="edges", depth=True, order="post")
assert [(x, y.name) for x, y in traversal] == pairs
def test_postorder_path_traversal(self):
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
names = [
"libelf",
"libdwarf",
"libelf",
"dyninst",
"fake",
"zmpi",
"callpath",
"fake",
"zmpi",
"mpileaks",
]
pairs = list(zip([4, 3, 3, 2, 3, 2, 1, 2, 1, 0], names))
traversal = dag.traverse(cover="paths", order="post")
assert [x.name for x in traversal] == names
traversal = dag.traverse(cover="paths", depth=True, order="post")
assert [(x, y.name) for x, y in traversal] == pairs
def test_dependents_and_dependencies_are_correct(self): def test_dependents_and_dependencies_are_correct(self):
spec = Spec.from_literal( spec = Spec.from_literal(
{ {
@ -739,10 +843,10 @@ def test_spec_tree_respect_deptypes(self):
"query,expected_length,expected_satisfies", "query,expected_length,expected_satisfies",
[ [
({"virtuals": ["mpi"]}, 1, ["mpich", "mpi"]), ({"virtuals": ["mpi"]}, 1, ["mpich", "mpi"]),
({"depflag": dt.BUILD}, 2, ["mpich", "mpi", "callpath"]), ({"depflag": dt.BUILD}, 3, ["mpich", "mpi", "callpath"]),
({"depflag": dt.BUILD, "virtuals": ["mpi"]}, 1, ["mpich", "mpi"]), ({"depflag": dt.BUILD, "virtuals": ["mpi"]}, 1, ["mpich", "mpi"]),
({"depflag": dt.LINK}, 2, ["mpich", "mpi", "callpath"]), ({"depflag": dt.LINK}, 3, ["mpich", "mpi", "callpath"]),
({"depflag": dt.BUILD | dt.LINK}, 2, ["mpich", "mpi", "callpath"]), ({"depflag": dt.BUILD | dt.LINK}, 4, ["mpich", "mpi", "callpath"]),
({"virtuals": ["lapack"]}, 0, []), ({"virtuals": ["lapack"]}, 0, []),
], ],
) )
@ -751,12 +855,14 @@ def test_query_dependency_edges(
): ):
"""Tests querying edges to dependencies on the following DAG: """Tests querying edges to dependencies on the following DAG:
[ ] mpileaks@=2.3 - [ ] mpileaks@2.3
[bl ] ^callpath@=1.0 - [bl ] ^callpath@1.0
[bl ] ^dyninst@=8.2 - [bl ] ^dyninst@8.2
[bl ] ^libdwarf@=20130729 - [bl ] ^libdwarf@20130729
[bl ] ^libelf@=0.8.13 - [bl ] ^libelf@0.8.13
[bl ] ^mpich@=3.0.4 [e] [b ] ^gcc@10.1.0
- [ l ] ^gcc-runtime@10.1.0
- [bl ] ^mpich@3.0.4~debug
""" """
mpileaks = default_mock_concretization("mpileaks") mpileaks = default_mock_concretization("mpileaks")
edges = mpileaks.edges_to_dependencies(**query) edges = mpileaks.edges_to_dependencies(**query)
@ -822,8 +928,8 @@ def test_synthetic_construction_of_split_dependencies_from_same_package(mock_pac
root.add_dependency_edge(build_spec, depflag=dt.BUILD, virtuals=()) root.add_dependency_edge(build_spec, depflag=dt.BUILD, virtuals=())
# Check dependencies from the perspective of root # Check dependencies from the perspective of root
assert len(root.dependencies()) == 2 assert len(root.dependencies()) == 4
assert all(x.name == "pkg-c" for x in root.dependencies()) assert len([x for x in root.dependencies() if x.name == "pkg-c"]) == 2
assert "@2.0" in root.dependencies(name="pkg-c", deptype=dt.BUILD)[0] assert "@2.0" in root.dependencies(name="pkg-c", deptype=dt.BUILD)[0]
assert "@1.0" in root.dependencies(name="pkg-c", deptype=dt.LINK | dt.RUN)[0] assert "@1.0" in root.dependencies(name="pkg-c", deptype=dt.LINK | dt.RUN)[0]
@ -847,8 +953,7 @@ def test_synthetic_construction_bootstrapping(mock_packages, config):
root.add_dependency_edge(bootstrap, depflag=dt.BUILD, virtuals=()) root.add_dependency_edge(bootstrap, depflag=dt.BUILD, virtuals=())
assert len(root.dependencies()) == 1 assert len([x for x in root.dependencies() if x.name == "pkg-b"]) == 1
assert root.dependencies()[0].name == "pkg-b"
assert root.name == "pkg-b" assert root.name == "pkg-b"
@ -867,8 +972,8 @@ def test_addition_of_different_deptypes_in_multiple_calls(mock_packages, config)
root.add_dependency_edge(bootstrap, depflag=current_depflag, virtuals=()) root.add_dependency_edge(bootstrap, depflag=current_depflag, virtuals=())
# Check edges in dependencies # Check edges in dependencies
assert len(root.edges_to_dependencies()) == 1 assert len(root.edges_to_dependencies(name="pkg-b")) == 1
forward_edge = root.edges_to_dependencies(depflag=current_depflag)[0] forward_edge = root.edges_to_dependencies(depflag=current_depflag, name="pkg-b")[0]
assert current_depflag & forward_edge.depflag assert current_depflag & forward_edge.depflag
assert id(forward_edge.parent) == id(root) assert id(forward_edge.parent) == id(root)
assert id(forward_edge.spec) == id(bootstrap) assert id(forward_edge.spec) == id(bootstrap)

View File

@ -18,15 +18,7 @@
import spack.variant import spack.variant
import spack.version as vn import spack.version as vn
from spack.error import SpecError, UnsatisfiableSpecError from spack.error import SpecError, UnsatisfiableSpecError
from spack.spec import ( from spack.spec import ArchSpec, DependencySpec, Spec, SpecFormatSigilError, SpecFormatStringError
ArchSpec,
CompilerSpec,
DependencySpec,
Spec,
SpecFormatSigilError,
SpecFormatStringError,
UnsupportedCompilerError,
)
from spack.variant import ( from spack.variant import (
InvalidVariantValueError, InvalidVariantValueError,
MultipleValuesInExclusiveVariantError, MultipleValuesInExclusiveVariantError,
@ -460,8 +452,6 @@ def test_concrete_specs_which_satisfies_abstract(self, lhs, rhs, default_mock_co
("foo platform=linux", "platform=test os=redhat6 target=x86"), ("foo platform=linux", "platform=test os=redhat6 target=x86"),
("foo os=redhat6", "platform=test os=debian6 target=x86_64"), ("foo os=redhat6", "platform=test os=debian6 target=x86_64"),
("foo target=x86_64", "platform=test os=redhat6 target=x86"), ("foo target=x86_64", "platform=test os=redhat6 target=x86"),
("foo%intel", "%gcc"),
("foo%intel", "%gcc"),
("foo%gcc@4.3", "%gcc@4.4:4.6"), ("foo%gcc@4.3", "%gcc@4.4:4.6"),
("foo@4.0%gcc", "@1:3%gcc"), ("foo@4.0%gcc", "@1:3%gcc"),
("foo@4.0%gcc@4.5", "@1:3%gcc@4.4:4.6"), ("foo@4.0%gcc@4.5", "@1:3%gcc@4.4:4.6"),
@ -937,7 +927,6 @@ def check_prop(check_spec, fmt_str, prop, getter):
"{name}", "{name}",
"{version}", "{version}",
"{@version}", "{@version}",
"{%compiler}",
"{namespace}", "{namespace}",
"{ namespace=namespace}", "{ namespace=namespace}",
"{ namespace =namespace}", "{ namespace =namespace}",
@ -1513,15 +1502,16 @@ def test_unsatisfiable_virtual_deps_bindings(self, spec_str):
("git-test@git.foo/bar", "{name}-{version}", str(pathlib.Path("git-test-git.foo_bar"))), ("git-test@git.foo/bar", "{name}-{version}", str(pathlib.Path("git-test-git.foo_bar"))),
("git-test@git.foo/bar", "{name}-{version}-{/hash}", None), ("git-test@git.foo/bar", "{name}-{version}-{/hash}", None),
("git-test@git.foo/bar", "{name}/{version}", str(pathlib.Path("git-test", "git.foo_bar"))), ("git-test@git.foo/bar", "{name}/{version}", str(pathlib.Path("git-test", "git.foo_bar"))),
# {compiler} is 'none' if a package does not depend on C, C++, or Fortran
( (
"git-test@{0}=1.0%gcc".format("a" * 40), f"git-test@{'a' * 40}=1.0%gcc",
"{name}/{version}/{compiler}", "{name}/{version}/{compiler}",
str(pathlib.Path("git-test", "{0}_1.0".format("a" * 40), "gcc")), str(pathlib.Path("git-test", f"{'a' * 40}_1.0", "none")),
), ),
( (
"git-test@git.foo/bar=1.0%gcc", "git-test@git.foo/bar=1.0%gcc",
"{name}/{version}/{compiler}", "{name}/{version}/{compiler}",
str(pathlib.Path("git-test", "git.foo_bar_1.0", "gcc")), str(pathlib.Path("git-test", "git.foo_bar_1.0", "none")),
), ),
], ],
) )
@ -1705,12 +1695,18 @@ def test_call_dag_hash_on_old_dag_hash_spec(mock_packages, default_mock_concreti
def test_spec_trim(mock_packages, config): def test_spec_trim(mock_packages, config):
top = spack.concretize.concretize_one("dt-diamond") top = spack.concretize.concretize_one("dt-diamond")
top.trim("dt-diamond-left") top.trim("dt-diamond-left")
remaining = set(x.name for x in top.traverse()) remaining = {x.name for x in top.traverse()}
assert set(["dt-diamond", "dt-diamond-right", "dt-diamond-bottom"]) == remaining assert {
"dt-diamond",
"dt-diamond-right",
"dt-diamond-bottom",
"gcc-runtime",
"gcc",
} == remaining
top.trim("dt-diamond-right") top.trim("dt-diamond-right")
remaining = set(x.name for x in top.traverse()) remaining = {x.name for x in top.traverse()}
assert set(["dt-diamond"]) == remaining assert {"dt-diamond", "gcc-runtime", "gcc"} == remaining
@pytest.mark.regression("30861") @pytest.mark.regression("30861")
@ -1740,11 +1736,6 @@ def test_concretize_partial_old_dag_hash_spec(mock_packages, config):
assert not getattr(spec["dt-diamond-bottom"], "_package_hash", None) assert not getattr(spec["dt-diamond-bottom"], "_package_hash", None)
def test_unsupported_compiler():
with pytest.raises(UnsupportedCompilerError):
Spec("gcc%fake-compiler").validate_or_raise()
def test_package_hash_affects_dunder_and_dag_hash(mock_packages, default_mock_concretization): def test_package_hash_affects_dunder_and_dag_hash(mock_packages, default_mock_concretization):
a1 = default_mock_concretization("pkg-a") a1 = default_mock_concretization("pkg-a")
a2 = default_mock_concretization("pkg-a") a2 = default_mock_concretization("pkg-a")
@ -1817,10 +1808,10 @@ def test_abstract_contains_semantic(lhs, rhs, expected, mock_packages):
(ArchSpec, "None-ubuntu20.04-None", "None-ubuntu20.04-None", (True, True, True)), (ArchSpec, "None-ubuntu20.04-None", "None-ubuntu20.04-None", (True, True, True)),
(ArchSpec, "None-ubuntu20.04-None", "None-ubuntu22.04-None", (False, False, False)), (ArchSpec, "None-ubuntu20.04-None", "None-ubuntu22.04-None", (False, False, False)),
# Compiler # Compiler
(CompilerSpec, "gcc", "clang", (False, False, False)), (Spec, "gcc", "clang", (False, False, False)),
(CompilerSpec, "gcc", "gcc@5", (True, False, True)), (Spec, "gcc", "gcc@5", (True, False, True)),
(CompilerSpec, "gcc@5", "gcc@5.3", (True, False, True)), (Spec, "gcc@5", "gcc@5.3", (True, False, True)),
(CompilerSpec, "gcc@5", "gcc@5-tag", (True, False, True)), (Spec, "gcc@5", "gcc@5-tag", (True, False, True)),
# Flags (flags are a map, so for convenience we initialize a full Spec) # Flags (flags are a map, so for convenience we initialize a full Spec)
# Note: the semantic is that of sv variants, not mv variants # Note: the semantic is that of sv variants, not mv variants
(Spec, "cppflags=-foo", "cppflags=-bar", (True, False, False)), (Spec, "cppflags=-foo", "cppflags=-bar", (True, False, False)),
@ -1886,8 +1877,8 @@ def test_intersects_and_satisfies(factory, lhs_str, rhs_str, results):
"None-ubuntu20.04-nocona,haswell", "None-ubuntu20.04-nocona,haswell",
), ),
# Compiler # Compiler
(CompilerSpec, "gcc@5", "gcc@5-tag", True, "gcc@5-tag"), (Spec, "foo %gcc@5", "foo %gcc@5-tag", True, "foo %gcc@5-tag"),
(CompilerSpec, "gcc@5", "gcc@5", False, "gcc@5"), (Spec, "foo %gcc@5", "foo %gcc@5", False, "foo %gcc@5"),
# Flags # Flags
(Spec, "cppflags=-foo", "cppflags=-foo", False, "cppflags=-foo"), (Spec, "cppflags=-foo", "cppflags=-foo", False, "cppflags=-foo"),
(Spec, "cppflags=-foo", "cflags=-foo", True, "cppflags=-foo cflags=-foo"), (Spec, "cppflags=-foo", "cflags=-foo", True, "cppflags=-foo cflags=-foo"),

View File

@ -818,9 +818,7 @@ def test_dep_spec_by_hash(database, config):
assert "zmpi" in mpileaks_hash_fake assert "zmpi" in mpileaks_hash_fake
assert mpileaks_hash_fake["zmpi"] == spack.spec.Spec("zmpi") assert mpileaks_hash_fake["zmpi"] == spack.spec.Spec("zmpi")
mpileaks_hash_zmpi = SpecParser( mpileaks_hash_zmpi = SpecParser(f"mpileaks ^ /{zmpi.dag_hash()}").next_spec()
f"mpileaks %{mpileaks_zmpi.compiler} ^ /{zmpi.dag_hash()}"
).next_spec()
mpileaks_hash_zmpi.replace_hash() mpileaks_hash_zmpi.replace_hash()
assert "zmpi" in mpileaks_hash_zmpi assert "zmpi" in mpileaks_hash_zmpi
assert mpileaks_hash_zmpi["zmpi"] == zmpi assert mpileaks_hash_zmpi["zmpi"] == zmpi

View File

@ -85,7 +85,7 @@ def test_tag_get_available(tags, expected, mock_packages):
def test_tag_get_installed_packages(mock_packages, mock_archive, mock_fetch, install_mockery): def test_tag_get_installed_packages(mock_packages, mock_archive, mock_fetch, install_mockery):
install("mpich") install("--fake", "mpich")
for skip in [False, True]: for skip in [False, True]:
all_pkgs = spack.tag.packages_with_tags(None, True, skip) all_pkgs = spack.tag.packages_with_tags(None, True, skip)