Files
spack/lib/spack/spack/test/cmd/spec.py
Massimiliano Culpo 826e0c0405 Improve hit-rate on buildcaches (#43272)
* Relax compiler and target mismatches

The mismatch occurs on an edge. Previously it was assigned
the parent priority, now it is assigned the child priority.

This should make reuse from buildcaches or store more likely,
since most mismatches will be counted with "reused" priority.

* Optimize version badness for runtimes at very low priority

We don't want to e.g. switch other attributes because we
cannot reuse an old installed runtime.

* Optimize runtime attributes at very low priority

This is such that the version of the runtime would
not influence whether we should reuse a spec.

Compiler mismatches are considered for runtimes,
to avoid situations where compiling foo%gcc@9
brings in gcc-runtime%gcc@13 if gcc@13 is among
the available compilers

* Exclude specs without runtimes from reuse

This should ensure that we do not reuse specs that
could be broken, as they expect the compiler to be
installed in a specific place.
2024-04-05 20:10:28 +02:00

184 lines
5.5 KiB
Python

# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import re
import pytest
import spack.environment as ev
import spack.error
import spack.parser
import spack.spec
import spack.store
from spack.main import SpackCommand, SpackCommandError
pytestmark = pytest.mark.usefixtures("config", "mutable_mock_repo")
spec = SpackCommand("spec")
def test_spec():
output = spec("mpileaks")
assert "mpileaks@2.3" in output
assert "callpath@1.0" in output
assert "dyninst@8.2" in output
assert "libdwarf@20130729" in output
assert "libelf@0.8.1" in output
assert "mpich@3.0.4" in output
@pytest.mark.only_clingo("Known failure of the original concretizer")
def test_spec_concretizer_args(mutable_config, mutable_database, do_not_check_runtimes_on_reuse):
"""End-to-end test of CLI concretizer prefs.
It's here to make sure that everything works from CLI
options to `solver.py`, and that config options are not
lost along the way.
"""
# remove two non-preferred mpileaks installations
# so that reuse will pick up the zmpi one
uninstall = SpackCommand("uninstall")
uninstall("-y", "mpileaks^mpich")
uninstall("-y", "mpileaks^mpich2")
# get the hash of mpileaks^zmpi
mpileaks_zmpi = spack.store.STORE.db.query_one("mpileaks^zmpi")
h = mpileaks_zmpi.dag_hash()[:7]
output = spec("--fresh", "-l", "mpileaks")
assert h not in output
output = spec("--reuse", "-l", "mpileaks")
assert h in output
def test_spec_parse_dependency_variant_value():
"""Verify that we can provide multiple key=value variants to multiple separate
packages within a spec string."""
output = spec("multivalue-variant fee=barbaz ^ a foobar=baz")
assert "fee=barbaz" in output
assert "foobar=baz" in output
def test_spec_parse_cflags_quoting():
"""Verify that compiler flags can be provided to a spec from the command line."""
output = spec("--yaml", 'gcc cflags="-Os -pipe" cxxflags="-flto -Os"')
gh_flagged = spack.spec.Spec.from_yaml(output)
assert ["-Os", "-pipe"] == gh_flagged.compiler_flags["cflags"]
assert ["-flto", "-Os"] == gh_flagged.compiler_flags["cxxflags"]
def test_spec_yaml():
output = spec("--yaml", "mpileaks")
mpileaks = spack.spec.Spec.from_yaml(output)
assert "mpileaks" in mpileaks
assert "callpath" in mpileaks
assert "dyninst" in mpileaks
assert "libdwarf" in mpileaks
assert "libelf" in mpileaks
assert "mpich" in mpileaks
def test_spec_json():
output = spec("--json", "mpileaks")
mpileaks = spack.spec.Spec.from_json(output)
assert "mpileaks" in mpileaks
assert "callpath" in mpileaks
assert "dyninst" in mpileaks
assert "libdwarf" in mpileaks
assert "libelf" in mpileaks
assert "mpich" in mpileaks
def test_spec_format(database, config):
output = spec("--format", "{name}-{^mpi.name}", "mpileaks^mpich")
assert output.rstrip("\n") == "mpileaks-mpich"
def _parse_types(string):
"""Parse deptypes for specs from `spack spec -t` output."""
lines = string.strip().split("\n")
result = {}
for line in lines:
match = re.match(r"\[([^]]*)\]\s*\^?([^@]*)@", line)
if match:
types, name = match.groups()
result.setdefault(name, []).append(types)
result[name] = sorted(result[name])
return result
def test_spec_deptypes_nodes():
output = spec("--types", "--cover", "nodes", "--no-install-status", "dt-diamond")
types = _parse_types(output)
assert types["dt-diamond"] == [" "]
assert types["dt-diamond-left"] == ["bl "]
assert types["dt-diamond-right"] == ["bl "]
assert types["dt-diamond-bottom"] == ["blr "]
def test_spec_deptypes_edges():
output = spec("--types", "--cover", "edges", "--no-install-status", "dt-diamond")
types = _parse_types(output)
assert types["dt-diamond"] == [" "]
assert types["dt-diamond-left"] == ["bl "]
assert types["dt-diamond-right"] == ["bl "]
assert types["dt-diamond-bottom"] == ["b ", "blr "]
def test_spec_returncode():
with pytest.raises(SpackCommandError):
spec()
assert spec.returncode == 1
def test_spec_parse_error():
with pytest.raises(spack.parser.SpecSyntaxError) as e:
spec("1.15:")
# make sure the error is formatted properly
error_msg = "unexpected tokens in the spec string\n1.15:\n ^"
assert error_msg in str(e.value)
def test_env_aware_spec(mutable_mock_env_path):
env = ev.create("test")
env.add("mpileaks")
with env:
output = spec()
assert "mpileaks@2.3" in output
assert "callpath@1.0" in output
assert "dyninst@8.2" in output
assert "libdwarf@20130729" in output
assert "libelf@0.8.1" in output
assert "mpich@3.0.4" in output
@pytest.mark.parametrize(
"name, version, error",
[
("develop-branch-version", "f3c7206350ac8ee364af687deaae5c574dcfca2c=develop", None),
("develop-branch-version", "git." + "a" * 40 + "=develop", None),
("callpath", "f3c7206350ac8ee364af687deaae5c574dcfca2c=1.0", spack.error.FetchError),
("develop-branch-version", "git.foo=0.2.15", None),
],
)
def test_spec_version_assigned_git_ref_as_version(name, version, error):
if error:
with pytest.raises(error):
output = spec(name + "@" + version)
else:
output = spec(name + "@" + version)
assert version in output