Fix wrong hash in spliced specs, and improve unit-tests (#48574)
Modifications: * Fix a severe bug where a spliced spec has the same hash as the original build spec * Removed CacheManager in favor of install_mockery. The latter sets up a temporary store, and removes it at the end of the test. * Deleted a couple of helper functions e.g. _has_dependencies * Checked that SolverException is raised, rather than Exception (more specific) * Extended, and renamed the splicing_setup fixture (now called install_specs) * Added more specific assertions in each test One test is currently flaky, due to some instability when sorting multiple specs. It's currently marked xfail
This commit is contained in:
parent
00e804a94b
commit
59a71959e7
@ -3653,6 +3653,7 @@ def _resolve_automatic_splices(self):
|
||||
):
|
||||
continue
|
||||
new_spec = spec.copy(deps=False)
|
||||
new_spec.clear_caches(ignore=("package_hash",))
|
||||
new_spec.build_spec = spec
|
||||
for edge in spec.edges_to_dependencies():
|
||||
depflag = edge.depflag & ~dt.BUILD
|
||||
|
@ -3591,25 +3591,16 @@ def patches(self):
|
||||
|
||||
return self._patches
|
||||
|
||||
def _dup(self, other, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, cleardeps=True):
|
||||
"""Copy the spec other into self. This is an overwriting
|
||||
copy. It does not copy any dependents (parents), but by default
|
||||
copies dependencies.
|
||||
|
||||
To duplicate an entire DAG, call _dup() on the root of the DAG.
|
||||
def _dup(self, other: "Spec", deps: Union[bool, dt.DepTypes, dt.DepFlag] = True) -> bool:
|
||||
"""Copies "other" into self, by overwriting all attributes.
|
||||
|
||||
Args:
|
||||
other (Spec): spec to be copied onto ``self``
|
||||
deps: if True copies all the dependencies. If
|
||||
False copies None. If deptype/depflag, copy matching types.
|
||||
cleardeps (bool): if True clears the dependencies of ``self``,
|
||||
before possibly copying the dependencies of ``other`` onto
|
||||
``self``
|
||||
other: spec to be copied onto ``self``
|
||||
deps: if True copies all the dependencies. If False copies None.
|
||||
If deptype, or depflag, copy matching types.
|
||||
|
||||
Returns:
|
||||
True if ``self`` changed because of the copy operation,
|
||||
False otherwise.
|
||||
|
||||
True if ``self`` changed because of the copy operation, False otherwise.
|
||||
"""
|
||||
# We don't count dependencies as changes here
|
||||
changed = True
|
||||
@ -3634,14 +3625,15 @@ def _dup(self, other, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, clearde
|
||||
self.versions = other.versions.copy()
|
||||
self.architecture = other.architecture.copy() if other.architecture else None
|
||||
self.compiler = other.compiler.copy() if other.compiler else None
|
||||
if cleardeps:
|
||||
self._dependents = _EdgeMap(store_by_child=False)
|
||||
self._dependencies = _EdgeMap(store_by_child=True)
|
||||
self.compiler_flags = other.compiler_flags.copy()
|
||||
self.compiler_flags.spec = self
|
||||
self.variants = other.variants.copy()
|
||||
self._build_spec = other._build_spec
|
||||
|
||||
# Clear dependencies
|
||||
self._dependents = _EdgeMap(store_by_child=False)
|
||||
self._dependencies = _EdgeMap(store_by_child=True)
|
||||
|
||||
# FIXME: we manage _patches_in_order_of_appearance specially here
|
||||
# to keep it from leaking out of spec.py, but we should figure
|
||||
# out how to handle it more elegantly in the Variant classes.
|
||||
@ -4524,7 +4516,7 @@ def mask_build_deps(in_spec):
|
||||
|
||||
return spec
|
||||
|
||||
def clear_caches(self, ignore=()):
|
||||
def clear_caches(self, ignore: Tuple[str, ...] = ()) -> None:
|
||||
"""
|
||||
Clears all cached hashes in a Spec, while preserving other properties.
|
||||
"""
|
||||
|
@ -10,33 +10,11 @@
|
||||
import spack.concretize
|
||||
import spack.config
|
||||
import spack.deptypes as dt
|
||||
import spack.solver.asp
|
||||
from spack.installer import PackageInstaller
|
||||
from spack.solver.asp import SolverError
|
||||
from spack.spec import Spec
|
||||
|
||||
|
||||
class CacheManager:
|
||||
def __init__(self, specs: List[str]) -> None:
|
||||
self.req_specs = specs
|
||||
self.concr_specs: List[Spec]
|
||||
self.concr_specs = []
|
||||
|
||||
def __enter__(self):
|
||||
self.concr_specs = [spack.concretize.concretize_one(s) for s in self.req_specs]
|
||||
for s in self.concr_specs:
|
||||
PackageInstaller([s.package], fake=True, explicit=True).install()
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
for s in self.concr_specs:
|
||||
s.package.do_uninstall()
|
||||
|
||||
|
||||
# MacOS and Windows only work if you pass this function pointer rather than a
|
||||
# closure
|
||||
def _mock_has_runtime_dependencies(_x):
|
||||
return True
|
||||
|
||||
|
||||
def _make_specs_non_buildable(specs: List[str]):
|
||||
output_config = {}
|
||||
for spec in specs:
|
||||
@ -45,203 +23,263 @@ def _make_specs_non_buildable(specs: List[str]):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def splicing_setup(mutable_database, mock_packages, monkeypatch):
|
||||
spack.config.set("concretizer:reuse", True)
|
||||
monkeypatch.setattr(
|
||||
spack.solver.asp, "_has_runtime_dependencies", _mock_has_runtime_dependencies
|
||||
)
|
||||
def install_specs(
|
||||
mutable_database,
|
||||
mock_packages,
|
||||
mutable_config,
|
||||
do_not_check_runtimes_on_reuse,
|
||||
install_mockery,
|
||||
):
|
||||
"""Returns a function that concretizes and installs a list of abstract specs"""
|
||||
mutable_config.set("concretizer:reuse", True)
|
||||
|
||||
def _impl(*specs_str):
|
||||
concrete_specs = [Spec(s).concretized() for s in specs_str]
|
||||
PackageInstaller([s.package for s in concrete_specs], fake=True, explicit=True).install()
|
||||
return concrete_specs
|
||||
|
||||
return _impl
|
||||
|
||||
|
||||
def _enable_splicing():
|
||||
spack.config.set("concretizer:splice", {"automatic": True})
|
||||
|
||||
|
||||
def _has_build_dependency(spec: Spec, name: str):
|
||||
return any(s.name == name for s in spec.dependencies(None, dt.BUILD))
|
||||
@pytest.mark.parametrize("spec_str", ["splice-z", "splice-h@1"])
|
||||
def test_spec_reuse(spec_str, install_specs, mutable_config):
|
||||
"""Tests reuse of splice-z, without splicing, as a root and as a dependency of splice-h"""
|
||||
splice_z = install_specs("splice-z@1.0.0+compat")[0]
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
concrete = spack.concretize.concretize_one(spec_str)
|
||||
assert concrete["splice-z"].satisfies(splice_z)
|
||||
|
||||
|
||||
def test_simple_reuse(splicing_setup):
|
||||
with CacheManager(["splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
assert spack.concretize.concretize_one("splice-z").satisfies(Spec("splice-z"))
|
||||
|
||||
|
||||
def test_simple_dep_reuse(splicing_setup):
|
||||
with CacheManager(["splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-z"]))
|
||||
assert spack.concretize.concretize_one("splice-h@1").satisfies(Spec("splice-h@1"))
|
||||
|
||||
|
||||
def test_splice_installed_hash(splicing_setup):
|
||||
cache = [
|
||||
@pytest.mark.regression("48578")
|
||||
def test_splice_installed_hash(install_specs, mutable_config):
|
||||
"""Tests splicing the dependency of an installed spec, for another installed spec"""
|
||||
splice_t, splice_h = install_specs(
|
||||
"splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0",
|
||||
"splice-h@1.0.2+compat ^splice-z@1.0.0",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
packages_config = _make_specs_non_buildable(["splice-t", "splice-h"])
|
||||
spack.config.set("packages", packages_config)
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0")
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
_enable_splicing()
|
||||
assert spack.concretize.concretize_one(goal_spec).satisfies(goal_spec)
|
||||
)
|
||||
packages_config = _make_specs_non_buildable(["splice-t", "splice-h"])
|
||||
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):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t has a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
# splice-h is reused, so the hash should stay the same
|
||||
assert concrete["splice-h"].satisfies(splice_h)
|
||||
assert concrete["splice-h"].build_spec.satisfies(splice_h)
|
||||
assert concrete["splice-h"].dag_hash() == splice_h.dag_hash()
|
||||
|
||||
|
||||
def test_splice_build_splice_node(splicing_setup):
|
||||
with CacheManager(["splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat"]):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-t"]))
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.0+compat")
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
_enable_splicing()
|
||||
assert spack.concretize.concretize_one(goal_spec).satisfies(goal_spec)
|
||||
def test_splice_build_splice_node(install_specs, mutable_config):
|
||||
"""Tests splicing the dependency of an installed spec, for a spec that is yet to be built"""
|
||||
splice_t = install_specs("splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat")[0]
|
||||
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):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t has a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
# splice-h should be different
|
||||
assert concrete["splice-h"].dag_hash() != splice_t["splice-h"].dag_hash()
|
||||
assert concrete["splice-h"].build_spec.dag_hash() == concrete["splice-h"].dag_hash()
|
||||
|
||||
|
||||
def test_double_splice(splicing_setup):
|
||||
cache = [
|
||||
@pytest.mark.xfail(reason="the spliced splice-h has sometimes the original splice-h hash")
|
||||
def test_double_splice(install_specs, mutable_config):
|
||||
"""Tests splicing two dependencies of an installed spec, for other installed specs"""
|
||||
splice_t, splice_h, splice_z = install_specs(
|
||||
"splice-t@1 ^splice-h@1.0.0+compat ^splice-z@1.0.0+compat",
|
||||
"splice-h@1.0.2+compat ^splice-z@1.0.1+compat",
|
||||
"splice-z@1.0.2+compat",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_builds_config = _make_specs_non_buildable(["splice-t", "splice-h", "splice-z"])
|
||||
spack.config.set("packages", freeze_builds_config)
|
||||
goal_spec = Spec("splice-t@1 ^splice-h@1.0.2+compat ^splice-z@1.0.2+compat")
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
_enable_splicing()
|
||||
assert spack.concretize.concretize_one(goal_spec).satisfies(goal_spec)
|
||||
)
|
||||
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):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
concrete = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
# splice-t and splice-h have a dependency that is changing, thus its hash should be different
|
||||
assert concrete.dag_hash() != splice_t.dag_hash()
|
||||
assert concrete.build_spec.satisfies(splice_t)
|
||||
assert not concrete.satisfies(splice_t)
|
||||
|
||||
assert concrete["splice-h"].dag_hash() != splice_h.dag_hash()
|
||||
assert concrete["splice-h"].build_spec.satisfies(splice_h)
|
||||
assert not concrete["splice-h"].satisfies(splice_h)
|
||||
|
||||
# splice-z is reused, so the hash should stay the same
|
||||
assert concrete["splice-z"].dag_hash() == splice_z.dag_hash()
|
||||
|
||||
|
||||
# The next two tests are mirrors of one another
|
||||
def test_virtual_multi_splices_in(splicing_setup):
|
||||
cache = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
]
|
||||
goal_specs = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
for gs in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(gs)
|
||||
_enable_splicing()
|
||||
for gs in goal_specs:
|
||||
assert spack.concretize.concretize_one(gs).satisfies(gs)
|
||||
@pytest.mark.parametrize(
|
||||
"original_spec,goal_spec",
|
||||
[
|
||||
# `virtual-abi-1` can be spliced for `virtual-abi-multi abi=one` and vice-versa
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
),
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
),
|
||||
# `virtual-abi-2` can be spliced for `virtual-abi-multi abi=two` and vice-versa
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
),
|
||||
(
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_virtual_multi_splices_in(original_spec, goal_spec, install_specs, mutable_config):
|
||||
"""Tests that we can splice a virtual dependency with a different, but compatible, provider."""
|
||||
original = install_specs(original_spec)[0]
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
assert spliced.dag_hash() != original.dag_hash()
|
||||
assert spliced.build_spec.dag_hash() == original.dag_hash()
|
||||
assert spliced["virtual-with-abi"].name != spliced.build_spec["virtual-with-abi"].name
|
||||
|
||||
|
||||
def test_virtual_multi_can_be_spliced(splicing_setup):
|
||||
cache = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=one",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-multi abi=two",
|
||||
]
|
||||
goal_specs = [
|
||||
"depends-on-virtual-with-abi ^virtual-abi-1",
|
||||
"depends-on-virtual-with-abi ^virtual-abi-2",
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["depends-on-virtual-with-abi"]))
|
||||
for gs in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(gs)
|
||||
_enable_splicing()
|
||||
for gs in goal_specs:
|
||||
assert spack.concretize.concretize_one(gs).satisfies(gs)
|
||||
|
||||
|
||||
def test_manyvariant_star_matching_variant_splice(splicing_setup):
|
||||
cache = [
|
||||
@pytest.mark.parametrize(
|
||||
"original_spec,goal_spec",
|
||||
[
|
||||
# can_splice("manyvariants@1.0.0", when="@1.0.1", match_variants="*")
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0+a+b c=v1 d=v2",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0~a~b c=v3 d=v3",
|
||||
]
|
||||
goal_specs = [
|
||||
Spec("depends-on-manyvariants ^manyvariants@1.0.1+a+b c=v1 d=v2"),
|
||||
Spec("depends-on-manyvariants ^manyvariants@1.0.1~a~b c=v3 d=v3"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_build_config = {"depends-on-manyvariants": {"buildable": False}}
|
||||
spack.config.set("packages", freeze_build_config)
|
||||
for goal in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(goal)
|
||||
_enable_splicing()
|
||||
for goal in goal_specs:
|
||||
assert spack.concretize.concretize_one(goal).satisfies(goal)
|
||||
|
||||
|
||||
def test_manyvariant_limited_matching(splicing_setup):
|
||||
cache = [
|
||||
(
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0+a+b c=v1 d=v2",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.1+a+b c=v1 d=v2",
|
||||
),
|
||||
(
|
||||
"depends-on-manyvariants ^manyvariants@1.0.0~a~b c=v3 d=v3",
|
||||
"depends-on-manyvariants ^manyvariants@1.0.1~a~b c=v3 d=v3",
|
||||
),
|
||||
# can_splice("manyvariants@2.0.0+a~b", when="@2.0.1~a+b", match_variants=["c", "d"])
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0+a~b c=v3 d=v2",
|
||||
(
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0+a~b c=v3 d=v2",
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.1~a+b c=v3 d=v2",
|
||||
),
|
||||
# can_splice("manyvariants@2.0.0 c=v1 d=v1", when="@2.0.1+a+b")
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0~a~b c=v1 d=v1",
|
||||
]
|
||||
goal_specs = [
|
||||
Spec("depends-on-manyvariants@2.0 ^manyvariants@2.0.1~a+b c=v3 d=v2"),
|
||||
Spec("depends-on-manyvariants@2.0 ^manyvariants@2.0.1+a+b c=v3 d=v3"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
freeze_build_config = {"depends-on-manyvariants": {"buildable": False}}
|
||||
spack.config.set("packages", freeze_build_config)
|
||||
for s in goal_specs:
|
||||
with pytest.raises(Exception):
|
||||
spack.concretize.concretize_one(s)
|
||||
_enable_splicing()
|
||||
for s in goal_specs:
|
||||
assert spack.concretize.concretize_one(s).satisfies(s)
|
||||
(
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.0~a~b c=v1 d=v1",
|
||||
"depends-on-manyvariants@2.0 ^manyvariants@2.0.1+a+b c=v3 d=v3",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_manyvariant_matching_variant_splice(
|
||||
original_spec, goal_spec, install_specs, mutable_config
|
||||
):
|
||||
"""Tests splicing with different kind of matching on variants"""
|
||||
original = install_specs(original_spec)[0]
|
||||
mutable_config.set("packages", {"depends-on-manyvariants": {"buildable": False}})
|
||||
|
||||
with pytest.raises(SolverError):
|
||||
spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one(goal_spec)
|
||||
|
||||
assert spliced.dag_hash() != original.dag_hash()
|
||||
assert spliced.build_spec.dag_hash() == original.dag_hash()
|
||||
|
||||
# The spliced 'manyvariants' is yet to be built
|
||||
assert spliced["manyvariants"].dag_hash() != original["manyvariants"].dag_hash()
|
||||
assert spliced["manyvariants"].build_spec.dag_hash() == spliced["manyvariants"].dag_hash()
|
||||
|
||||
|
||||
def test_external_splice_same_name(splicing_setup):
|
||||
cache = [
|
||||
def test_external_splice_same_name(install_specs, mutable_config):
|
||||
"""Tests that externals can be spliced for non-external specs"""
|
||||
original_splice_h, original_splice_t = install_specs(
|
||||
"splice-h@1.0.0 ^splice-z@1.0.0+compat",
|
||||
"splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.1+compat",
|
||||
]
|
||||
packages_yaml = {
|
||||
"splice-z": {"externals": [{"spec": "splice-z@1.0.2+compat", "prefix": "/usr"}]}
|
||||
}
|
||||
goal_specs = [
|
||||
Spec("splice-h@1.0.0 ^splice-z@1.0.2"),
|
||||
Spec("splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.2"),
|
||||
]
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", packages_yaml)
|
||||
_enable_splicing()
|
||||
for s in goal_specs:
|
||||
assert spack.concretize.concretize_one(s).satisfies(s)
|
||||
)
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-t", "splice-h"]))
|
||||
mutable_config.set(
|
||||
"packages",
|
||||
{
|
||||
"splice-z": {
|
||||
"externals": [{"spec": "splice-z@1.0.2+compat", "prefix": "/usr"}],
|
||||
"buildable": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
_enable_splicing()
|
||||
concrete_splice_h = spack.concretize.concretize_one("splice-h@1.0.0 ^splice-z@1.0.2")
|
||||
concrete_splice_t = spack.concretize.concretize_one(
|
||||
"splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.2"
|
||||
)
|
||||
|
||||
assert concrete_splice_h.dag_hash() != original_splice_h.dag_hash()
|
||||
assert concrete_splice_h.build_spec.dag_hash() == original_splice_h.dag_hash()
|
||||
assert concrete_splice_h["splice-z"].external
|
||||
|
||||
assert concrete_splice_t.dag_hash() != original_splice_t.dag_hash()
|
||||
assert concrete_splice_t.build_spec.dag_hash() == original_splice_t.dag_hash()
|
||||
assert concrete_splice_t["splice-z"].external
|
||||
|
||||
assert concrete_splice_t["splice-z"].dag_hash() == concrete_splice_h["splice-z"].dag_hash()
|
||||
|
||||
|
||||
def test_spliced_build_deps_only_in_build_spec(splicing_setup):
|
||||
cache = ["splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.0"]
|
||||
goal_spec = Spec("splice-t@1.0 ^splice-h@1.0.2 ^splice-z@1.0.0")
|
||||
def test_spliced_build_deps_only_in_build_spec(install_specs):
|
||||
"""Tests that build specs are not reported in the spliced spec"""
|
||||
install_specs("splice-t@1.0 ^splice-h@1.0.1 ^splice-z@1.0.0")
|
||||
|
||||
with CacheManager(cache):
|
||||
_enable_splicing()
|
||||
concr_goal = spack.concretize.concretize_one(goal_spec)
|
||||
build_spec = concr_goal._build_spec
|
||||
# Spec has been spliced
|
||||
assert build_spec is not None
|
||||
# Build spec has spliced build dependencies
|
||||
assert _has_build_dependency(build_spec, "splice-h")
|
||||
assert _has_build_dependency(build_spec, "splice-z")
|
||||
# Spliced build dependencies are removed
|
||||
assert len(concr_goal.dependencies(None, dt.BUILD)) == 0
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one("splice-t@1.0 ^splice-h@1.0.2 ^splice-z@1.0.0")
|
||||
build_spec = spliced.build_spec
|
||||
|
||||
# Spec has been spliced
|
||||
assert build_spec.dag_hash() != spliced.dag_hash()
|
||||
# Build spec has spliced build dependencies
|
||||
assert build_spec.dependencies("splice-h", dt.BUILD)
|
||||
assert build_spec.dependencies("splice-z", dt.BUILD)
|
||||
# Spliced build dependencies are removed
|
||||
assert len(spliced.dependencies(None, dt.BUILD)) == 0
|
||||
|
||||
|
||||
def test_spliced_transitive_dependency(splicing_setup):
|
||||
cache = ["splice-depends-on-t@1.0 ^splice-h@1.0.1"]
|
||||
goal_spec = Spec("splice-depends-on-t^splice-h@1.0.2")
|
||||
def test_spliced_transitive_dependency(install_specs, mutable_config):
|
||||
"""Tests that build specs are not reported, even for spliced transitive dependencies"""
|
||||
install_specs("splice-depends-on-t@1.0 ^splice-h@1.0.1")
|
||||
mutable_config.set("packages", _make_specs_non_buildable(["splice-depends-on-t"]))
|
||||
|
||||
with CacheManager(cache):
|
||||
spack.config.set("packages", _make_specs_non_buildable(["splice-depends-on-t"]))
|
||||
_enable_splicing()
|
||||
concr_goal = spack.concretize.concretize_one(goal_spec)
|
||||
# Spec has been spliced
|
||||
assert concr_goal._build_spec is not None
|
||||
assert concr_goal["splice-t"]._build_spec is not None
|
||||
assert concr_goal.satisfies(goal_spec)
|
||||
# Spliced build dependencies are removed
|
||||
assert len(concr_goal.dependencies(None, dt.BUILD)) == 0
|
||||
_enable_splicing()
|
||||
spliced = spack.concretize.concretize_one("splice-depends-on-t^splice-h@1.0.2")
|
||||
|
||||
# Spec has been spliced
|
||||
assert spliced.build_spec.dag_hash() != spliced.dag_hash()
|
||||
assert spliced["splice-t"].build_spec.dag_hash() != spliced["splice-t"].dag_hash()
|
||||
|
||||
# Spliced build dependencies are removed
|
||||
assert len(spliced.dependencies(None, dt.BUILD)) == 0
|
||||
assert len(spliced["splice-t"].dependencies(None, dt.BUILD)) == 0
|
||||
|
@ -2125,15 +2125,7 @@ def configure_reuse(reuse_mode, combined_env) -> Optional[ev.Environment]:
|
||||
"from_environment_raise",
|
||||
],
|
||||
)
|
||||
def test_env_include_concrete_reuse(monkeypatch, reuse_mode):
|
||||
|
||||
# The mock packages do not use the gcc-runtime
|
||||
def mock_has_runtime_dependencies(*args, **kwargs):
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(
|
||||
spack.solver.asp, "_has_runtime_dependencies", mock_has_runtime_dependencies
|
||||
)
|
||||
def test_env_include_concrete_reuse(do_not_check_runtimes_on_reuse, reuse_mode):
|
||||
# The default mpi version is 3.x provided by mpich in the mock repo.
|
||||
# This test verifies that concretizing with an included concrete
|
||||
# environment with "concretizer:reuse:true" the included
|
||||
|
@ -3122,14 +3122,13 @@ def test_concretization_version_order():
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("mutable_database", "mock_store")
|
||||
@pytest.mark.usefixtures("mutable_database", "mock_store", "do_not_check_runtimes_on_reuse")
|
||||
@pytest.mark.not_on_windows("Expected length is different on Windows")
|
||||
def test_filtering_reused_specs(
|
||||
roots, reuse_yaml, expected, not_expected, expected_length, mutable_config, monkeypatch
|
||||
roots, reuse_yaml, expected, not_expected, expected_length, mutable_config
|
||||
):
|
||||
"""Tests that we can select which specs are to be reused, using constraints as filters"""
|
||||
# Assume all specs have a runtime dependency
|
||||
monkeypatch.setattr(spack.solver.asp, "_has_runtime_dependencies", lambda x: True)
|
||||
mutable_config.set("concretizer:reuse", reuse_yaml)
|
||||
selector = spack.solver.asp.ReusableSpecsSelector(mutable_config)
|
||||
specs = selector.reusable_specs(roots)
|
||||
@ -3149,10 +3148,11 @@ def test_filtering_reused_specs(
|
||||
[({"from": [{"type": "local"}]}, 17), ({"from": [{"type": "buildcache"}]}, 0)],
|
||||
)
|
||||
@pytest.mark.not_on_windows("Expected length is different on Windows")
|
||||
def test_selecting_reused_sources(reuse_yaml, expected_length, mutable_config, monkeypatch):
|
||||
def test_selecting_reused_sources(
|
||||
reuse_yaml, expected_length, mutable_config, do_not_check_runtimes_on_reuse
|
||||
):
|
||||
"""Tests that we can turn on/off sources of reusable specs"""
|
||||
# Assume all specs have a runtime dependency
|
||||
monkeypatch.setattr(spack.solver.asp, "_has_runtime_dependencies", lambda x: True)
|
||||
mutable_config.set("concretizer:reuse", reuse_yaml)
|
||||
selector = spack.solver.asp.ReusableSpecsSelector(mutable_config)
|
||||
specs = selector.reusable_specs(["mpileaks"])
|
||||
|
Loading…
Reference in New Issue
Block a user