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
import spack.compilers.libraries
import spack.config
import spack.package_base
import spack.paths
import spack.util.executable

View File

@ -21,7 +21,7 @@
from spack.error import SpackError
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.compilers.flags
import spack.config
import spack.deptypes as dt
import spack.error
import spack.hash_types as ht

View File

@ -11,7 +11,7 @@
import spack.config
import spack.deptypes as dt
from spack.installer import PackageInstaller
from spack.solver.asp import SolverError
from spack.solver.asp import SolverError, UnsatisfiableSpecError
from spack.spec import Spec
@ -65,7 +65,7 @@ def test_splice_installed_hash(install_specs, mutable_config):
mutable_config.set("packages", packages_config)
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)
_enable_splicing()
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"]))
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)
_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"]))
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)
_enable_splicing()
@ -202,7 +202,7 @@ def test_manyvariant_matching_variant_splice(
original = install_specs(original_spec)[0]
mutable_config.set("packages", {"depends-on-manyvariants": {"buildable": False}})
with pytest.raises(SolverError):
with pytest.raises((UnsatisfiableSpecError, SolverError)):
spack.concretize.concretize_one(goal_spec)
_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"""
opt_dir = tmpdir.join("opt")
original_store, spack.store.STORE = spack.store.STORE, spack.store.Store(
str(opt_dir),
projections={
"all": "{name}/{version}/{architecture}-{compiler.name}-{compiler.version}-{hash}"
},
str(opt_dir), projections={"all": "{name}-{version}-{hash:4}"}
)
try:
yield spack.store
@ -389,7 +386,7 @@ def test_spec_needs_rebuild(monkeypatch, tmpdir):
s = spack.concretize.concretize_one("libdwarf")
# Install a package
install_cmd(s.name)
install_cmd("--fake", s.name)
# Put installed package in the buildcache
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")
# Install a package
install_cmd("--no-cache", s.name)
install_cmd("--fake", "--no-cache", s.name)
# Create a buildcache and update index
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
compressed archive file containing the install tree. This test
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")
mirror_url = "file://{0}".format(legacy_layout_dir)
mirror_url = f"file://{legacy_layout_dir}"
filename = (
"test-debian6-core2-gcc-4.5.0-archive-files-2.0-"
"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)
output = install_cmd("--no-check-signature", "--cache-only", "-f", spec_json_path, output=str)
mirror_cmd("rm", "--scope=site", "test-legacy-layout")
expect_line = (
"Extracting archive-files-2.0-" "l3vdiqvbobmspwyb4q2b62fz6nitd4hk from binary cache"
)
expect_line = "Extracting archive-files-2.0-l3vdiqvbobmspwyb4q2b62fz6nitd4hk from binary cache"
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)
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
spec = Spec("gmake@4.4.1%gcc@13.1.0 arch=linux-ubuntu23.04-zen2")
spec._mark_concrete()
spec = spack.concretize.concretize_one("pkg-c")
spec_dict = spec.to_dict()
spec_dict["buildcache_layout_version"] = layout_version

View File

@ -13,6 +13,8 @@
import spack.store
import spack.util.path
from .conftest import _true
@pytest.fixture
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()
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'):
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"):
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
conf = next(iter(spack.bootstrap.core.bootstrapping_sources()))
# The source is not explicitly enabled or disabled, so the following
# call should raise to skip using it for bootstrapping
# The source is not explicitly enabled or disabled, so the following should return False
assert not spack.bootstrap.core.source_is_enabled(conf)
# Try to explicitly disable the source and verify that the behavior
# is the same as above
# Try to explicitly disable the source and verify that the behavior is the same as above
spack.config.add("bootstrap:trusted:{0}:{1}".format(conf["name"], False))
assert not spack.bootstrap.core.source_is_enabled(conf)

View File

@ -4,7 +4,6 @@
import os
import platform
import posixpath
import sys
import pytest
@ -14,8 +13,6 @@
from llnl.util.filesystem import HeaderList, LibraryList
import spack.build_environment
import spack.compiler
import spack.compilers
import spack.concretize
import spack.config
import spack.deptypes as dt
@ -97,7 +94,7 @@ def build_environment(working_env):
@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
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.usefixtures("config", "mock_packages")
def test_cc_not_changed_by_modules(monkeypatch, working_env):
s = spack.concretize.concretize_one("cmake")
pkg = s.package
@pytest.mark.usefixtures("mock_packages")
@pytest.mark.not_on_windows("Module files are not supported on Windows")
def test_cc_not_changed_by_modules(monkeypatch, mutable_config, working_env, compiler_factory):
"""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):
os.environ["CC"] = "NOT_THIS_PLEASE"
os.environ["ANOTHER_VAR"] = "THIS_IS_SET"
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["ANOTHER_VAR"] == "THIS_IS_SET"
@ -185,7 +187,7 @@ def test_setup_dependent_package_inherited_modules(
):
# This will raise on regression
s = spack.concretize.concretize_one("cmake-client-inheritor")
PackageInstaller([s.package]).install()
PackageInstaller([s.package], fake=True).install()
@pytest.mark.parametrize(
@ -265,22 +267,30 @@ def test_setup_dependent_package_inherited_modules(
],
)
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
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):
if Path.platform_path == Path.windows:
pathlist = pathlist.replace(":", ";")
return convert_to_platform_path(pathlist)
# Monkeypatch a pkg.compiler.environment with the required modifications
pkg = spack.concretize.concretize_one("cmake").package
monkeypatch.setattr(pkg.compiler, "environment", modifications)
pkg = spack.concretize.concretize_one("cmake %gcc@14").package
# Trigger the modifications
spack.build_environment.setup_package(pkg, False)
spack.build_environment.setup_package(pkg, dirty=False)
# Check they were applied
for name, value in expected.items():
@ -291,25 +301,6 @@ def platform_pathsep(pathlist):
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):
cmake_config = {
"externals": [
@ -329,24 +320,27 @@ def test_external_config_env(mock_packages, mutable_config, working_env):
@pytest.mark.regression("9107")
def test_spack_paths_before_module_paths(config, mock_packages, monkeypatch, working_env):
s = spack.concretize.concretize_one("cmake")
pkg = s.package
@pytest.mark.not_on_windows("Windows does not support module files")
def test_spack_paths_before_module_paths(
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")
spack_path = os.path.join(spack.paths.prefix, os.path.join("lib", "spack", "env"))
def _set_wrong_cc(x):
os.environ["PATH"] = module_path + os.pathsep + os.environ["PATH"]
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)
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"),
],
)
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
s = spack.concretize.concretize_one("cmake")
pkg = s.package
env = EnvironmentModifications()
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()
assert "SPACK_DTAGS_TO_STRIP" in modifications
assert "SPACK_DTAGS_TO_ADD" in modifications
@ -765,59 +758,24 @@ def test_rpath_with_duplicate_link_deps():
@pytest.mark.parametrize(
"compiler_spec,target_name,expected_flags",
[
# Homogeneous compilers
# Semver versions
("gcc@4.7.2", "ivybridge", "-march=core-avx-i -mtune=core-avx-i"),
("clang@3.5", "x86_64", "-march=x86-64 -mtune=generic"),
("apple-clang@9.1.0", "x86_64", "-march=x86-64"),
# Mixed toolchain
("clang@8.0.0", "broadwell", ""),
("gcc@=9.2.0", "haswell", "-march=haswell -mtune=haswell"),
# 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.not_on_windows("Windows doesn't support the compiler wrapper")
def test_optimization_flags(compiler_spec, target_name, expected_flags, compiler_factory):
target = archspec.cpu.TARGETS[target_name]
compiler_dict = compiler_factory(spec=compiler_spec, operating_system="")["compiler"]
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"])
compiler = spack.spec.parse_with_version_concrete(compiler_spec)
opt_flags = spack.build_environment.optimization_flags(compiler, target)
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):
"""Test that given an active environment and list of touched pkgs,
we get the right list of possibly-changed env specs"""
"""Tests that, given an active environment and list of touched pkgs, we get the right
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.add("mpileaks")
e1.add("hypre")
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"]
# 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
# numbers of possibly affected specs.
full_set = set(["mpileaks", "mpich", "callpath", "dyninst", "libdwarf", "libelf"])
empty_set = set([])
depth_2_set = set(["mpich", "callpath", "dyninst", "libdwarf", "libelf"])
depth_1_set = set(["dyninst", "libdwarf", "libelf"])
depth_0_set = set(["libdwarf", "libelf"])
full_set = {
"mpileaks",
"mpich",
"callpath",
"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 = {
None: full_set,
3: full_set,
100: full_set,
-1: empty_set,
-1: set(),
0: depth_0_set,
1: depth_1_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():
affected_specs = ci.get_spec_filter_list(e1, touched, dependent_traverse_depth=key)
affected_pkg_names = set([s.name for s in affected_specs])
print(f"{key}: {affected_pkg_names}")
affected_pkg_names = {s.name for s in affected_specs}
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 "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"][4] == "stage-rebuild-index"
assert yaml_contents["stages"][5] == "stage-rebuild-index"
assert "rebuild-index" in yaml_contents
rebuild_job = yaml_contents["rebuild-index"]

View File

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

View File

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

View File

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

View File

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

View File

@ -54,14 +54,14 @@ def test_install_package_and_dependency(
):
log = "test"
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()
filename = tmpdir.join("{0}.xml".format(log))
filename = tmpdir.join(f"{log}.xml")
assert filename in files
content = filename.open().read()
assert 'tests="2"' in content
assert 'tests="3"' in content
assert 'failures="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
):
with tmpdir.as_cwd():
install("libdwarf")
install("--log-format=junit", "--log-file=test.xml", "libdwarf")
install("--fake", "libdwarf")
install("--fake", "--log-format=junit", "--log-file=test.xml", "libdwarf")
files = tmpdir.listdir()
filename = tmpdir.join("test.xml")
assert filename in files
content = filename.open().read()
assert 'tests="2"' in content
print(content)
assert 'tests="4"' in content
assert 'failures="0"' in content
assert 'errors="0"' in content
skipped = [line for line in content.split("\n") if "skipped" in line]
assert len(skipped) == 2
assert len(skipped) == 4
@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):
spec = spack.concretize.concretize_one("libdwarf")
install("libdwarf")
spec = spack.concretize.concretize_one("pkg-c")
install("pkg-c")
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):
# Try to install a spec and then to reinstall it.
spec = spack.concretize.concretize_one("libdwarf")
install("libdwarf")
"""Tests installing a spec, and then re-installing it in the same prefix."""
spec = spack.concretize.concretize_one("pkg-c")
install("pkg-c")
# Ignore manifest and install times
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
install("--overwrite", "-y", "libdwarf")
install("--overwrite", "-y", "pkg-c")
assert os.path.exists(spec.prefix)
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):
# Try to install a spec and then to reinstall it.
spec = spack.concretize.concretize_one("libdwarf")
"""Tests that overwrite doesn't fail if the package is not installed"""
spec = spack.concretize.concretize_one("pkg-c")
assert not os.path.exists(spec.prefix)
install("--overwrite", "-y", "libdwarf")
install("--overwrite", "-y", "pkg-c")
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):
# Try to install a spec and then to reinstall it.
libdwarf = spack.concretize.concretize_one("libdwarf")
install("libdwarf")
cmake = spack.concretize.concretize_one("cmake")
install("cmake")
install("--fake", "libdwarf")
install("--fake", "cmake")
ld_manifest = os.path.join(
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_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(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):
# capfd interferes with Spack's capturing of e.g., Build.xml output
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")
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()
content = report_file.open().read()
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-site=my_custom_site",
"--cdash-track=my_custom_track",
"pkg-a",
"pkg-c",
)
report_dir = tmpdir.join("cdash_reports")
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()
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 "-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
with capfd.disabled(), tmpdir.as_cwd():
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())))
install(
"--log-file=cdash_reports",
"--log-format=cdash",
"--cdash-buildstamp={0}".format(buildstamp),
"pkg-a",
f"--cdash-buildstamp={buildstamp}",
"pkg-c",
)
report_dir = tmpdir.join("cdash_reports")
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()
content = report_file.open().read()
assert buildstamp in content
@ -609,8 +605,7 @@ def test_cdash_install_from_spec_json(
with capfd.disabled(), tmpdir.as_cwd():
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:
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")
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()
content = report_file.open().read()
install_command_regex = re.compile(
@ -635,7 +630,7 @@ def test_cdash_install_from_spec_json(
m = install_command_regex.search(content)
assert m
install_command = m.group(1)
assert "pkg-a@" in install_command
assert "pkg-c@" in install_command
@pytest.mark.disable_clean_stage_check
@ -672,7 +667,7 @@ def test_cache_only_fails(tmpdir, mock_fetch, install_mockery, capfd):
with capfd.disabled():
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 "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
with e:
# 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
# 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
# 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.
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 not in e.uninstalled_specs()
# Install a novel spec with --add and make sure it is added as a root
# and installed.
install("--add", "bowtie")
install("--fake", "--add", "bowtie")
assert any([s.name == "bowtie" for s in e.roots()])
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
with tmpdir.as_cwd(), capfd.disabled():
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
@ -941,7 +936,7 @@ def test_install_env_with_tests_all(
with ev.read("test"):
test_dep = spack.concretize.concretize_one("test-dependency")
add("depb")
install("--test", "all")
install("--fake", "--test", "all")
assert os.path.exists(test_dep.prefix)
@ -953,7 +948,7 @@ def test_install_env_with_tests_root(
with ev.read("test"):
test_dep = spack.concretize.concretize_one("test-dependency")
add("depb")
install("--test", "root")
install("--fake", "--test", "root")
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
# inspections. Also test that Spack correctly preserves the default/existing
# manpath search path via a trailing colon
install("mpileaks")
install("--fake", "mpileaks")
sh_out = load(shell, "mpileaks")
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):
"""Test that `spack load` applies prefix inspections of its required runtime deps in
topo-order"""
install("mpileaks")
install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
# Ensure our reference variable is clean.
@ -117,7 +117,7 @@ def test_load_includes_run_env(
"""Tests that environment changes from the package's
`setup_run_environment` method are added to the user environment in
addition to the prefix inspections"""
install("mpileaks")
install("--fake", "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):
"""Test with and without the --first option"""
shell = "--bat" if sys.platform == "win32" else "--sh"
install("libelf@0.8.12")
install("libelf@0.8.13")
install("--fake", "libelf@0.8.12")
install("--fake", "libelf@0.8.13")
# Now there are two versions of libelf, which should cause an error
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):
"""Test that spack load prints an error message without a shell."""
install("mpileaks")
install("--fake", "mpileaks")
out = load("mpileaks", fail_on_error=False)
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
unload command"""
install("mpileaks")
install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
# 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
):
"""Test that spack unload prints an error message without a shell."""
install("mpileaks")
install("--fake", "mpileaks")
mpileaks_spec = spack.concretize.concretize_one("mpileaks")
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):
"""Test with and without the --first option"""
install = SpackCommand("install")
install("libelf@0.8.12")
install("libelf@0.8.13")
install("--fake", "libelf@0.8.12")
install("--fake", "libelf@0.8.13")
# This would normally return an error without --first
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):
spec = spack.concretize.concretize_one("libelf")
spec = spack.concretize.concretize_one("pkg-c")
assert not spec.installed
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"):
logs("libelf mpi")
logs("pkg-c mpi")
install("libelf")
install("pkg-c")
os.remove(spec.package.install_log_path)
with pytest.raises(spack.main.SpackCommandError, match="No logs are available"):
logs("libelf")
logs("pkg-c")
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)
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
# it exists (if it does exist, we will overwrite it with content

View File

@ -11,7 +11,13 @@
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):
@ -34,6 +40,8 @@ def test_all(mock_packages, capfd):
with capfd.disabled():
out = split(maintainers("--all"))
assert out == [
"gcc-runtime:",
"haampie",
"maintainers-1:",
"user1,",
"user2",
@ -59,6 +67,8 @@ def test_all_by_user(mock_packages, capfd):
with capfd.disabled():
out = split(maintainers("--all", "--by-user"))
assert out == [
"haampie:",
"gcc-runtime",
"user0:",
"maintainers-3",
"user1:",

View File

@ -30,7 +30,7 @@ def test_mark_all_explicit(mutable_database):
mark("-e", "-a")
gc("-y")
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 15
assert len(all_specs) == 16
@pytest.mark.db
@ -47,7 +47,7 @@ def test_mark_one_explicit(mutable_database):
uninstall("-y", "-a", "mpileaks")
gc("-y")
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 3
assert len(all_specs) == 4
@pytest.mark.db
@ -55,7 +55,7 @@ def test_mark_one_implicit(mutable_database):
mark("-i", "externaltest")
gc("-y")
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 14
assert len(all_specs) == 15
@pytest.mark.db
@ -64,4 +64,4 @@ def test_mark_all_implicit_then_explicit(mutable_database):
mark("-e", "-a")
gc("-y")
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"
# 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)
contents = os.listdir(mirror_dir.strpath)

View File

@ -14,13 +14,10 @@
def test_reindex_basic(mock_packages, mock_archive, mock_fetch, install_mockery):
install("libelf@0.8.13")
install("libelf@0.8.12")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.12")
all_installed = spack.store.STORE.db.query()
reindex()
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):
install("libelf@0.8.13")
install("libelf@0.8.12")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.12")
all_installed = spack.store.STORE.db.query()
_clear_db(tmp_path)
reindex()
assert spack.store.STORE.db.query() == all_installed
def test_reindex_with_deprecated_packages(
mock_packages, mock_archive, mock_fetch, install_mockery, tmp_path
):
install("libelf@0.8.13")
install("libelf@0.8.12")
install("--fake", "libelf@0.8.13")
install("--fake", "libelf@0.8.12")
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()
# 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
def fake_stage(pkg, mirror_only=False):
@ -116,8 +120,7 @@ def fake_stage(pkg, mirror_only=False):
with e:
stage()
# assert that all were staged
assert len(expected) == 0
assert expected == externals
@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
):
"""Ensure re-using an alias fails with suggestion to change."""
install("libdwarf")
install("--fake", "libdwarf")
# Run the (no) tests with the alias once
spack_test("run", "--alias", "libdwarf", "libdwarf")

View File

@ -77,9 +77,8 @@ def test_recursive_uninstall(mutable_database):
"""Test recursive uninstall."""
uninstall("-y", "-a", "--dependents", "callpath")
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 9
# 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")]
callpath_specs = [s for s in all_specs if s.satisfies("callpath")]
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.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(
constraint, expected_number_of_specs, mutable_database
):
uninstall("-y", "-a", "--dependents", constraint)
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == expected_number_of_specs
@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(
constraint, expected_number_of_specs, mutable_database
):
uninstall("-f", "-y", constraint)
all_specs = spack.store.STORE.layout.all_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()
total_specs = len(all_specs)
assert total_specs == 14
assert total_specs == 15
assert len(mpileaks_specs) == 3
assert len(callpath_specs) == 2
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):
# Test the verify command interface to verify a single spec
install("libelf")
install("--fake", "libelf")
s = spack.concretize.concretize_one("libelf")
prefix = s.prefix
hash = s.dag_hash()

View File

@ -30,26 +30,26 @@
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:
projection = {"projections": projection}
projection_file = tmpdir.mkdir("projection").join("projection.yaml")
projection_file.write(s_yaml.dump(projection))
projection_file = tmp_path / "projection" / "projection.yaml"
projection_file.parent.mkdir(parents=True, exist_ok=True)
projection_file.write_text(s_yaml.dump(projection))
return projection_file
@pytest.mark.parametrize("cmd", commands)
def test_view_link_type(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
install("libdwarf")
viewpath = str(tmpdir.mkdir("view_{0}".format(cmd)))
view(cmd, viewpath, "libdwarf")
package_prefix = os.path.join(viewpath, "libdwarf")
assert os.path.exists(package_prefix)
def test_view_link_type(tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
install("--fake", "libdwarf")
view_dir = tmp_path / f"view_{cmd}"
view(cmd, str(view_dir), "libdwarf")
package_bin = view_dir / "bin" / "libdwarf"
assert package_bin.exists()
# Check that we use symlinks for and only for the appropriate subcommands
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)
@ -67,60 +67,60 @@ def test_view_link_type_remove(
@pytest.mark.parametrize("cmd", commands)
def test_view_projections(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
install("libdwarf@20130207")
def test_view_projections(tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
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}"}}
projection_file = create_projection_file(tmpdir, view_projection)
view(cmd, viewpath, "--projection-file={0}".format(projection_file), "libdwarf")
projection_file = create_projection_file(tmp_path, view_projection)
view(cmd, str(view_dir), f"--projection-file={projection_file}", "libdwarf")
package_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf")
assert os.path.exists(package_prefix)
package_bin = view_dir / "libdwarf-20130207" / "bin" / "libdwarf"
assert package_bin.exists()
# Check that we use symlinks for and only for the appropriate subcommands
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(
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
tmp_path, mock_packages, mock_archive, mock_fetch, install_mockery
):
install("libdwarf@20130207")
install("extendee@1.0%gcc")
install("--fake", "libdwarf@20130207")
install("--fake", "extendee@1.0")
view_dir = tmp_path / "view"
viewpath = str(tmpdir.mkdir("view"))
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)
view("add", viewpath, "--projection-file={0}".format(projection_file), "libdwarf", "extendee")
projection_file = create_projection_file(tmp_path, view_projection)
view("add", str(view_dir), f"--projection-file={projection_file}", "libdwarf", "extendee")
libdwarf_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf")
extendee_prefix = os.path.join(viewpath, "extendee-gcc/bin")
assert os.path.exists(libdwarf_prefix)
assert os.path.exists(extendee_prefix)
libdwarf_prefix = view_dir / "libdwarf-20130207" / "bin"
extendee_prefix = view_dir / "extendee-test" / "bin"
assert libdwarf_prefix.exists()
assert extendee_prefix.exists()
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("extendee@1.0%gcc")
install("--fake", "libdwarf@20130207")
install("--fake", "extendee@1.0")
view_dir = tmp_path / "view"
viewpath = str(tmpdir.mkdir("view"))
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)
view("add", viewpath, "--projection-file={0}".format(projection_file), "libdwarf", "extendee")
projection_file = create_projection_file(tmp_path, view_projection)
view("add", str(view_dir), f"--projection-file={projection_file}", "libdwarf", "extendee")
libdwarf_prefix = os.path.join(viewpath, "libdwarf-20130207/libdwarf")
extendee_prefix = os.path.join(viewpath, "extendee-gcc/bin")
assert os.path.exists(libdwarf_prefix)
assert os.path.exists(extendee_prefix)
libdwarf_prefix = view_dir / "libdwarf-20130207" / "bin"
extendee_prefix = view_dir / "extendee-test" / "bin"
assert libdwarf_prefix.exists()
assert extendee_prefix.exists()
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
# Spack Project Developers. See the top-level COPYRIGHT file for details.
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
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)
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):
gcc = tmp_path / "gcc"
gcc.write_text(
@ -104,10 +104,13 @@ def module(*args):
@pytest.mark.not_on_windows("Not supported on Windows")
def test_implicit_rpaths(self, mock_gcc, dirs_with_libfiles, monkeypatch):
lib_to_dirs, all_dirs = dirs_with_libfiles
monkeypatch.setattr(spack.compilers.libraries.CompilerPropertyDetector, "_CACHE", {})
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()
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.version import Version
pytestmark = [pytest.mark.usefixtures("enable_runtimes")]
def _concretize_with_reuse(*, root_str, reused_str):
reused_spec = spack.concretize.concretize_one(reused_str)
@ -36,14 +34,6 @@ def runtime_repo(mutable_config):
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):
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"]

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")
)
# 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(
"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:
assert not root.satisfies(constraint)
@pytest.mark.xfail(reason="FIXME (compiler as nodes): flaky test, revisit")
def test_mixing_compilers_only_affects_subdag(self):
"""Tests that, when we mix compilers, the one with lower penalty is used for nodes
where the compiler is not forced.
"""
spec = spack.concretize.concretize_one("dt-diamond%clang ^dt-diamond-bottom%gcc")
for x in spec.traverse(deptype=("link", "run")):
if "c" not in x or not x.name.startswith("dt-diamond"):
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="gcc", deptype="build")) is 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):
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):
s = Spec("pkg-a %gcc@0.0.0")
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
s.concretize()
spack.concretize.concretize_one(s)
def test_no_compilers_for_arch(self):
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:",
"gcc@4.4.7 languages=c,cxx,fortran",
"gcc@4.4.7 languages=c,c++,fortran",
"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:",
"gcc@5.3.0 languages=c,cxx,fortran",
"gcc@5.3.0 languages=c,c++,fortran",
"broadwell",
),
],
@ -990,7 +973,6 @@ def test_concretize_anonymous_dep(self, spec_str):
("bowtie@1.4.0", "%gcc@10.2.1"),
# Version with conflicts and no valid gcc select another compiler
("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
("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)
spec = spack.concretize.concretize_one("pkg-a cflags=-g cxxflags=-g")
PackageInstaller([spec.package], fake=True, explicit=True).install()
testspec = Spec("pkg-a cflags=-g")
testspec.concretize()
testspec = spack.concretize.concretize_one("pkg-a cflags=-g")
assert testspec == spec, testspec.tree()
@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 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.parametrize(
"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", "libdwarf%clang"], {"libdwarf": 2, "libelf": 1}),
(["libdwarf^libelf@0.8.12", "libdwarf^libelf@0.8.13"], {"libdwarf": 2, "libelf": 2}),
# FIXME (compiler as nodes): fix these
# (["hdf5", "zmpi"], 3, 1),
# (["hdf5", "mpich"], 2, 1),
# (["hdf5^zmpi", "mpich"], 4, 1),
# (["mpi", "zmpi"], 2, 1),
# (["mpi", "mpich"], 1, 1),
(["hdf5", "zmpi"], {"zmpi": 1, "fake": 1}),
(["hdf5", "mpich"], {"mpich": 1}),
(["hdf5^zmpi", "mpich"], {"mpi": 2, "mpich": 1, "zmpi": 1, "fake": 1}),
(["mpi", "zmpi"], {"mpi": 1, "mpich": 0, "zmpi": 1, "fake": 1}),
(["mpi", "mpich"], {"mpi": 1, "mpich": 1, "zmpi": 0}),
],
)
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:
concrete_specs.update(s.traverse())
for x in concrete_specs:
print(x.tree(hashes=True))
print()
for matching_spec, expected_count in checks.items():
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(
"specs,expected_spec,occurances",
@ -2219,10 +2178,19 @@ def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages):
solver.driver.solve(setup, specs, reuse=[])
@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"""
with pytest.raises(spack.error.UnsatisfiableSpecError, match="since 'foo' does not exist"):
spack.concretize.concretize_one("pkg-a %foo")
with pytest.raises(spack.error.UnsatisfiableSpecError, match=expected_match):
spack.concretize.concretize_one(spec_str)
@pytest.mark.regression("36339")
@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)
assert "c" in spec
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)

View File

@ -275,10 +275,10 @@ def test_add_config_path(mutable_config):
assert set_value == "/path/to/config.yaml"
# Now a package:all setting
path = "packages:all:compiler:[gcc]"
path = "packages:all:target:[x86_64]"
spack.config.add(path)
compilers = spack.config.get("packages")["all"]["compiler"]
assert "gcc" in compilers
targets = spack.config.get("packages")["all"]["target"]
assert "x86_64" in targets
# Try quotes to escape brackets
path = (
@ -922,7 +922,6 @@ def test_single_file_scope(config, env_yaml):
# from the single-file config
assert spack.config.get("config:verify_ssl") 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
assert spack.config.get("config:checksum") is True
@ -946,7 +945,7 @@ def test_single_file_scope_section_override(tmpdir, config):
verify_ssl: False
packages::
all:
compiler: [ 'gcc@4.5.3' ]
target: [ x86_64 ]
repos:
- /x/y/z
"""
@ -959,7 +958,7 @@ def test_single_file_scope_section_override(tmpdir, config):
with spack.config.override(scope):
# from the single-file config
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
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):
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")
_, _, 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):
@ -1298,7 +1297,7 @@ def test_config_collect_urls(mutable_empty_config, mock_spider_configs, url, isf
(github_url.format("tree"), False, False),
(gitlab_url, False, False),
("{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),
],
)

View File

@ -95,11 +95,11 @@ def upstream_and_downstream_db(tmpdir, gen_mock_layout):
@pytest.mark.parametrize(
"install_tree,result",
[
("all", ["pkg-b", "pkg-c"]),
("all", ["pkg-b", "pkg-c", "gcc-runtime", "gcc"]),
("upstream", ["pkg-c"]),
("local", ["pkg-b"]),
("local", ["pkg-b", "gcc-runtime", "gcc"]),
("{u}", ["pkg-c"]),
("{d}", ["pkg-b"]),
("{d}", ["pkg-b", "gcc-runtime", "gcc"]),
],
ids=["all", "upstream", "local", "upstream_path", "downstream_path"],
)
@ -117,7 +117,7 @@ def test_query_by_install_tree(
down_db.add(b)
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(
@ -491,7 +491,7 @@ def test_005_db_exists(database):
def test_010_all_install_sanity(database):
"""Ensure that the install layout reflects what we think it does."""
all_specs = spack.store.STORE.layout.all_specs()
assert len(all_specs) == 15
assert len(all_specs) == 16
# Query specs with multiple configurations
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."""
# query everything
total_specs = len(spack.store.STORE.db.query())
assert total_specs == 17
assert total_specs == 19
# query specs with multiple configurations
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)
default_dt = dt.LINK | dt.RUN
check_unused(None, default_dt, ["cmake"])
check_unused(None, default_dt, ["cmake", "gcc"])
check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi, externaltest],
default_dt,
["trivial-smoke-test", "cmake"],
["trivial-smoke-test", "cmake", "gcc"],
)
check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi, externaltest],
@ -846,7 +846,7 @@ def check_unused(roots, deptype, expected):
check_unused(
[si, ml_mpich, ml_mpich2, ml_zmpi],
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):
# ensure we get the right number of hashes without a read transaction
hashes = database.all_hashes()
assert len(hashes) == 17
assert len(hashes) == 19
# and make sure the hashes match
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))
path_default = layout_default.relative_path_for_spec(spec)
assert path_default == str(
Path(
spec.format(
"{architecture}/" "{compiler.name}-{compiler.version}/" "{name}-{version}-{hash}"
)
)
Path(spec.format("{architecture.platform}/{architecture.target}/{name}-{version}-{hash}"))
)
# 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 = "\n".join([line.rstrip() for line in graph_str.split("\n")])
print(graph_str)
assert (
graph_str
== 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 libdwarf
| | |\
| | | o callpath
| |_|/|
|/| |/|
| |/|/|
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):
"""Test fail_fast install when an install failure is detected."""
b = spack.concretize.concretize_one("pkg-b")
c = spack.concretize.concretize_one("pkg-c")
# Note: this test depends on the order of the installations
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)
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"):
installer.install()
assert b_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 f"{b_id} failed to install" in capsys.readouterr().err
assert c_id in installer.failed, "Expected b to be marked as failed"
assert b_id not in installer.failed, "Expected no attempt to install pkg-c"
assert f"{c_id} failed to install" in capsys.readouterr().err
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):
"""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):
tty.msg("requeued {0}".format(task.pkg.spec.name))
installer = create_installer(["pkg-b"], {})
installer = create_installer(["pkg-c"], {})
# Ensure never acquire a lock
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):
"""Cover basic install handling for installed package."""
b = spack.concretize.concretize_one("pkg-b")
b_pkg_id = inst.package_id(b)
installer = create_installer([b])
# Note: this test relies on installing a package with no dependencies
concrete_spec = spack.concretize.concretize_one("pkg-c")
pkg_id = inst.package_id(concrete_spec)
installer = create_installer([concrete_spec])
def _prep(installer, task):
installer.installed.add(b_pkg_id)
tty.msg(f"{b_pkg_id} is installed")
installer.installed.add(pkg_id)
tty.msg(f"{pkg_id} is installed")
# also do not allow the package to be locked again
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"):
installer.install()
assert b_pkg_id not in installer.installed
assert pkg_id not in installer.installed
expected = ["is installed", "read locked", "requeued"]
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):
"""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
def _read(installer, lock_type, pkg):
@ -1142,7 +1145,7 @@ def _requeued(installer, task, install_status):
# Ensure don't continually requeue the task
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"):
installer.install()
@ -1157,7 +1160,8 @@ def _requeued(installer, task, install_status):
def test_install_skip_patch(install_mockery, mock_fetch):
"""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()
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
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
installer = create_installer(["pkg-b"])
installer = create_installer(["pkg-c"])
installer._init_queue()
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
from the database.
"""
# Note: this test relies on installing a package with no dependencies
class InstallerThatAccidentallyDeletesTheBackupDir:
def _install_task(self, task, install_status):
@ -1238,7 +1244,7 @@ def remove(self, spec):
self.called = True
# 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()
task = installer._pop_task()

View File

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

View File

@ -6,7 +6,6 @@
import re
import sys
from datetime import datetime, timedelta
from textwrap import dedent
import pytest
@ -290,13 +289,6 @@ def inner():
with h.forward("top-level"):
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():
h = llnl.util.lang.GroupedExceptionHandler()

View File

@ -112,7 +112,7 @@ def test_compilers_provided_different_name(
self, factory, module_configuration, compiler_factory
):
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, spec = factory("intel-oneapi-compilers%clang@3.3")
@ -120,7 +120,7 @@ def test_compilers_provided_different_name(
provides = module.conf.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):
"""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")
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):
"""Tests the automatic loading of all dependencies."""
@ -147,7 +147,7 @@ def test_autoload_all(self, modulefile_content, module_configuration):
module_configuration("autoload_all")
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):
"""Tests modifications to run-time environment."""
@ -265,7 +265,7 @@ def test_exclude(self, modulefile_content, module_configuration):
module_configuration("exclude")
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):
"""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")
# 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
# 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:
module_configuration("with_view")
install("--add", "cmake")
install("--fake", "--add", "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])
== 1
)
assert len([x for x in content if "depends-on " in x]) == 2
assert len([x for x in content if "module load " 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]) == 3
# dtbuild1 has
# - 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])
== 1
)
assert len([x for x in content if "depends-on " in x]) == 5
assert len([x for x in content if "module load " 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]) == 6
# dtbuild1 has
# - 1 ('run',) dependency
@ -101,7 +101,7 @@ def test_prerequisites_direct(
module_configuration("prerequisites_direct")
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(
self, modulefile_content, module_configuration, host_architecture_str
@ -111,7 +111,7 @@ def test_prerequisites_all(
module_configuration("prerequisites_all")
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):
"""Tests modifications to run-time environment."""
@ -236,14 +236,14 @@ def test_exclude(self, modulefile_content, module_configuration, host_architectu
module_configuration("exclude")
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):
modulefile_content(f"callpath 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):
"""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
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 "module load " 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]) == 3
# Test the mpileaks that should NOT have the autoloaded dependencies
content = modulefile_content("mpileaks ^mpich")

View File

@ -7,7 +7,6 @@
import pytest
import spack.concretize
import spack.config
import spack.platforms
from spack.multimethod import NoSuchMethodError
@ -53,7 +52,7 @@ def test_no_version_match(pkg_name):
# Constraints on compilers with a default
("%gcc", "has_a_default", "gcc"),
("%clang", "has_a_default", "clang"),
("%apple-clang os=elcapitan", "has_a_default", "default"),
("%gcc@9", "has_a_default", "default"),
# Constraints on dependencies
("^zmpi", "different_by_dep", "zmpi"),
("^mpich", "different_by_dep", "mpich"),
@ -68,13 +67,9 @@ def test_no_version_match(pkg_name):
],
)
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
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)
s = default_mock_concretization(f"{pkg_name}{constraint_str}")
msg = f"Method {method_name} from {s} is giving a wrong result"
assert getattr(s.package, method_name)() == expected_result, msg

View File

@ -16,7 +16,6 @@
import llnl.util.filesystem as fs
import spack.binary_distribution
import spack.compilers.config
import spack.concretize
import spack.deptypes as dt
import spack.error
@ -30,21 +29,28 @@
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()
def mpileaks_possible_deps(mock_packages, mpi_names):
def mpileaks_possible_deps(mock_packages, mpi_names, compiler_names):
possible = {
"callpath": set(["dyninst"] + mpi_names),
"callpath": set(["dyninst"] + mpi_names + compiler_names),
"low-priority-provider": set(),
"dyninst": set(["libdwarf", "libelf"]),
"dyninst": set(["libdwarf", "libelf"] + compiler_names),
"fake": set(),
"gcc": set(),
"intel-parallel-studio": set(),
"libdwarf": set(["libelf"]),
"libelf": set(),
"mpich": set(),
"mpich2": set(),
"mpileaks": set(["callpath"] + mpi_names),
"libdwarf": set(["libelf"] + compiler_names),
"libelf": set(compiler_names),
"llvm": set(),
"mpich": set(compiler_names),
"mpich2": set(compiler_names),
"mpileaks": set(["callpath"] + mpi_names + compiler_names),
"multi-provider-mpi": set(),
"zmpi": set(["fake"]),
"zmpi": set(["fake"] + compiler_names),
}
return possible
@ -76,6 +82,8 @@ def mpi_names(mock_inspector):
{
"fake",
"mpileaks",
"gcc",
"llvm",
"multi-provider-mpi",
"callpath",
"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):
expected = set(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(s.name for s in mock_packages.providers_for("c"))
real_pkgs, *_ = mock_inspector.possible_dependencies(
"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 compilers(compiler, arch_spec):
return None
monkeypatch.setattr(spack.compilers.config, "compilers_for_spec", compilers)
"""Ensures that a test which needs the compiler, and build dependencies, to run, is skipped
if no compiler is available.
"""
s = spack.spec.Spec("pkg-a")
pkg = BaseTestPackage(s)
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
dependencies = pkg_cls.dependencies_by_name()
assert len(dependencies) == 3
assert len(dependencies) == 4
assert "cmake" in dependencies
assert "openblas" in dependencies
assert "mpi" in dependencies

View File

@ -9,6 +9,7 @@
import spack.concretize
import spack.deptypes as dt
import spack.error
import spack.installer
import spack.repo
import spack.util.hash as hashutil
import spack.version
@ -80,8 +81,7 @@ def test_test_deptype(tmpdir):
assert "z" not in spec
@pytest.mark.usefixtures("config")
def test_installed_deps(monkeypatch, mock_packages):
def test_installed_deps(monkeypatch, install_mockery):
"""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
@ -101,7 +101,7 @@ def test_installed_deps(monkeypatch, mock_packages):
# |/ \| c --> d build
# 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
# 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)
assert c_spec[d].version == spack.version.Version("2")
installed_names = [s.name for s in c_spec.traverse()]
def _mock_installed(self):
return self.name in installed_names
monkeypatch.setattr(Spec, "installed", _mock_installed)
spack.installer.PackageInstaller([c_spec.package], fake=True, explicit=True).install()
# 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
# *if* we're doing a fresh installation.
a_spec = Spec(a)
a_spec._add_dependency(c_spec, depflag=dt.BUILD | dt.LINK, virtuals=())
a_spec = spack.concretize.concretize_one(a_spec)
a_spec = spack.concretize.concretize_one(f"{a} ^/{c_spec.dag_hash()}")
assert spack.version.Version("2") == a_spec[c][d].version
assert spack.version.Version("2") == a_spec[e].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):
spack.concretize.concretize_one(spec)
def test_preorder_node_traversal(self):
dag = spack.concretize.concretize_one("mpileaks ^zmpi")
@pytest.mark.parametrize(
"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"]
pairs = list(zip([0, 1, 2, 3, 4, 2, 3], names))
o mpileaks
|\
| |\
| | |\
| | | |\
| | | | 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()
assert [x.name for x in traversal] == names
traversal = dag.traverse(depth=True)
traversal = dag.traverse(**traverse_kwargs, depth=True)
assert [(x, y.name) for x, y in traversal] == pairs
def test_preorder_edge_traversal(self):
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")
traversal = dag.traverse(**traverse_kwargs)
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):
spec = Spec.from_literal(
{
@ -739,10 +843,10 @@ def test_spec_tree_respect_deptypes(self):
"query,expected_length,expected_satisfies",
[
({"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.LINK}, 2, ["mpich", "mpi", "callpath"]),
({"depflag": dt.BUILD | dt.LINK}, 2, ["mpich", "mpi", "callpath"]),
({"depflag": dt.LINK}, 3, ["mpich", "mpi", "callpath"]),
({"depflag": dt.BUILD | dt.LINK}, 4, ["mpich", "mpi", "callpath"]),
({"virtuals": ["lapack"]}, 0, []),
],
)
@ -751,12 +855,14 @@ def test_query_dependency_edges(
):
"""Tests querying edges to dependencies on the following DAG:
[ ] mpileaks@=2.3
[bl ] ^callpath@=1.0
[bl ] ^dyninst@=8.2
[bl ] ^libdwarf@=20130729
[bl ] ^libelf@=0.8.13
[bl ] ^mpich@=3.0.4
- [ ] mpileaks@2.3
- [bl ] ^callpath@1.0
- [bl ] ^dyninst@8.2
- [bl ] ^libdwarf@20130729
- [bl ] ^libelf@0.8.13
[e] [b ] ^gcc@10.1.0
- [ l ] ^gcc-runtime@10.1.0
- [bl ] ^mpich@3.0.4~debug
"""
mpileaks = default_mock_concretization("mpileaks")
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=())
# Check dependencies from the perspective of root
assert len(root.dependencies()) == 2
assert all(x.name == "pkg-c" for x in root.dependencies())
assert len(root.dependencies()) == 4
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 "@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=())
assert len(root.dependencies()) == 1
assert root.dependencies()[0].name == "pkg-b"
assert len([x for x in root.dependencies() if x.name == "pkg-b"]) == 1
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=())
# Check edges in dependencies
assert len(root.edges_to_dependencies()) == 1
forward_edge = root.edges_to_dependencies(depflag=current_depflag)[0]
assert len(root.edges_to_dependencies(name="pkg-b")) == 1
forward_edge = root.edges_to_dependencies(depflag=current_depflag, name="pkg-b")[0]
assert current_depflag & forward_edge.depflag
assert id(forward_edge.parent) == id(root)
assert id(forward_edge.spec) == id(bootstrap)

View File

@ -18,15 +18,7 @@
import spack.variant
import spack.version as vn
from spack.error import SpecError, UnsatisfiableSpecError
from spack.spec import (
ArchSpec,
CompilerSpec,
DependencySpec,
Spec,
SpecFormatSigilError,
SpecFormatStringError,
UnsupportedCompilerError,
)
from spack.spec import ArchSpec, DependencySpec, Spec, SpecFormatSigilError, SpecFormatStringError
from spack.variant import (
InvalidVariantValueError,
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 os=redhat6", "platform=test os=debian6 target=x86_64"),
("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@4.0%gcc", "@1:3%gcc"),
("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}",
"{version}",
"{@version}",
"{%compiler}",
"{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}-{/hash}", None),
("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}",
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",
"{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):
top = spack.concretize.concretize_one("dt-diamond")
top.trim("dt-diamond-left")
remaining = set(x.name for x in top.traverse())
assert set(["dt-diamond", "dt-diamond-right", "dt-diamond-bottom"]) == remaining
remaining = {x.name for x in top.traverse()}
assert {
"dt-diamond",
"dt-diamond-right",
"dt-diamond-bottom",
"gcc-runtime",
"gcc",
} == remaining
top.trim("dt-diamond-right")
remaining = set(x.name for x in top.traverse())
assert set(["dt-diamond"]) == remaining
remaining = {x.name for x in top.traverse()}
assert {"dt-diamond", "gcc-runtime", "gcc"} == remaining
@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)
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):
a1 = 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-ubuntu22.04-None", (False, False, False)),
# Compiler
(CompilerSpec, "gcc", "clang", (False, False, False)),
(CompilerSpec, "gcc", "gcc@5", (True, False, True)),
(CompilerSpec, "gcc@5", "gcc@5.3", (True, False, True)),
(CompilerSpec, "gcc@5", "gcc@5-tag", (True, False, True)),
(Spec, "gcc", "clang", (False, False, False)),
(Spec, "gcc", "gcc@5", (True, False, True)),
(Spec, "gcc@5", "gcc@5.3", (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)
# Note: the semantic is that of sv variants, not mv variants
(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",
),
# Compiler
(CompilerSpec, "gcc@5", "gcc@5-tag", True, "gcc@5-tag"),
(CompilerSpec, "gcc@5", "gcc@5", False, "gcc@5"),
(Spec, "foo %gcc@5", "foo %gcc@5-tag", True, "foo %gcc@5-tag"),
(Spec, "foo %gcc@5", "foo %gcc@5", False, "foo %gcc@5"),
# Flags
(Spec, "cppflags=-foo", "cppflags=-foo", False, "cppflags=-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 mpileaks_hash_fake["zmpi"] == spack.spec.Spec("zmpi")
mpileaks_hash_zmpi = SpecParser(
f"mpileaks %{mpileaks_zmpi.compiler} ^ /{zmpi.dag_hash()}"
).next_spec()
mpileaks_hash_zmpi = SpecParser(f"mpileaks ^ /{zmpi.dag_hash()}").next_spec()
mpileaks_hash_zmpi.replace_hash()
assert "zmpi" in mpileaks_hash_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):
install("mpich")
install("--fake", "mpich")
for skip in [False, True]:
all_pkgs = spack.tag.packages_with_tags(None, True, skip)