summaryrefslogtreecommitdiff
path: root/lib/spack/spack/test/spec_syntax.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/test/spec_syntax.py')
-rw-r--r--lib/spack/spack/test/spec_syntax.py154
1 files changed, 92 insertions, 62 deletions
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index c421494ce8..22942862eb 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -2,7 +2,6 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-import inspect
import itertools
import os
import re
@@ -10,10 +9,12 @@ import sys
import pytest
+import spack.binary_distribution
import spack.cmd
+import spack.parser
import spack.platforms.test
+import spack.repo
import spack.spec
-import spack.variant
from spack.parser import (
UNIX_FILENAME,
WINDOWS_FILENAME,
@@ -523,6 +524,23 @@ def specfile_for(default_mock_concretization):
],
"^[virtuals=mpi] openmpi",
),
+ # Allow merging attributes, if deptypes match
+ (
+ "^[virtuals=mpi] openmpi+foo ^[virtuals=lapack] openmpi+bar",
+ [
+ Token(TokenType.START_EDGE_PROPERTIES, value="^["),
+ Token(TokenType.KEY_VALUE_PAIR, value="virtuals=mpi"),
+ Token(TokenType.END_EDGE_PROPERTIES, value="]"),
+ Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="openmpi"),
+ Token(TokenType.BOOL_VARIANT, value="+foo"),
+ Token(TokenType.START_EDGE_PROPERTIES, value="^["),
+ Token(TokenType.KEY_VALUE_PAIR, value="virtuals=lapack"),
+ Token(TokenType.END_EDGE_PROPERTIES, value="]"),
+ Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="openmpi"),
+ Token(TokenType.BOOL_VARIANT, value="+bar"),
+ ],
+ "^[virtuals=lapack,mpi] openmpi+bar+foo",
+ ),
(
"^[deptypes=link,build] zlib",
[
@@ -534,12 +552,26 @@ def specfile_for(default_mock_concretization):
"^[deptypes=build,link] zlib",
),
(
- "zlib@git.foo/bar",
+ "^[deptypes=link] zlib ^[deptypes=build] zlib",
[
- Token(TokenType.UNQUALIFIED_PACKAGE_NAME, "zlib"),
+ Token(TokenType.START_EDGE_PROPERTIES, value="^["),
+ Token(TokenType.KEY_VALUE_PAIR, value="deptypes=link"),
+ Token(TokenType.END_EDGE_PROPERTIES, value="]"),
+ Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="zlib"),
+ Token(TokenType.START_EDGE_PROPERTIES, value="^["),
+ Token(TokenType.KEY_VALUE_PAIR, value="deptypes=build"),
+ Token(TokenType.END_EDGE_PROPERTIES, value="]"),
+ Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="zlib"),
+ ],
+ "^[deptypes=link] zlib ^[deptypes=build] zlib",
+ ),
+ (
+ "git-test@git.foo/bar",
+ [
+ Token(TokenType.UNQUALIFIED_PACKAGE_NAME, "git-test"),
Token(TokenType.GIT_VERSION, "@git.foo/bar"),
],
- "zlib@git.foo/bar",
+ "git-test@git.foo/bar",
),
# Variant propagation
(
@@ -568,7 +600,7 @@ def specfile_for(default_mock_concretization):
),
],
)
-def test_parse_single_spec(spec_str, tokens, expected_roundtrip):
+def test_parse_single_spec(spec_str, tokens, expected_roundtrip, mock_git_test_package):
parser = SpecParser(spec_str)
assert tokens == parser.tokens()
assert expected_roundtrip == str(parser.next_spec())
@@ -683,7 +715,7 @@ def test_parse_multiple_specs(text, tokens, expected_specs):
],
)
def test_cli_spec_roundtrip(args, expected):
- if inspect.isclass(expected) and issubclass(expected, BaseException):
+ if isinstance(expected, type) and issubclass(expected, BaseException):
with pytest.raises(expected):
spack.cmd.parse_specs(args)
return
@@ -742,7 +774,7 @@ def test_spec_by_hash_tokens(text, tokens):
@pytest.mark.db
def test_spec_by_hash(database, monkeypatch, config):
mpileaks = database.query_one("mpileaks ^zmpi")
- b = spack.spec.Spec("b").concretized()
+ b = spack.spec.Spec("pkg-b").concretized()
monkeypatch.setattr(spack.binary_distribution, "update_cache_and_get_specs", lambda: [b])
hash_str = f"/{mpileaks.dag_hash()}"
@@ -834,12 +866,12 @@ def test_multiple_specs_with_hash(database, config):
@pytest.mark.db
-def test_ambiguous_hash(mutable_database, default_mock_concretization, config):
+def test_ambiguous_hash(mutable_database):
"""Test that abstract hash ambiguity is delayed until concretization.
In the past this ambiguity error would happen during parse time."""
# This is a very sketchy as manually setting hashes easily breaks invariants
- x1 = default_mock_concretization("a")
+ x1 = spack.spec.Spec("pkg-a").concretized()
x2 = x1.copy()
x1._hash = "xyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
x1._process_hash = "xyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
@@ -848,8 +880,8 @@ def test_ambiguous_hash(mutable_database, default_mock_concretization, config):
assert x1 != x2 # doesn't hold when only the dag hash is modified.
- mutable_database.add(x1, directory_layout=None)
- mutable_database.add(x2, directory_layout=None)
+ mutable_database.add(x1)
+ mutable_database.add(x2)
# ambiguity in first hash character
s1 = SpecParser("/x").next_spec()
@@ -857,7 +889,7 @@ def test_ambiguous_hash(mutable_database, default_mock_concretization, config):
s1.lookup_hash()
# ambiguity in first hash character AND spec name
- s2 = SpecParser("a/x").next_spec()
+ s2 = SpecParser("pkg-a/x").next_spec()
with pytest.raises(spack.spec.AmbiguousHashError):
s2.lookup_hash()
@@ -935,64 +967,62 @@ def test_disambiguate_hash_by_spec(spec1, spec2, constraint, mock_packages, monk
@pytest.mark.parametrize(
- "text,exc_cls",
+ "text,match_string",
[
# Duplicate variants
- ("x@1.2+debug+debug", spack.variant.DuplicateVariantError),
- ("x ^y@1.2+debug debug=true", spack.variant.DuplicateVariantError),
- ("x ^y@1.2 debug=false debug=true", spack.variant.DuplicateVariantError),
- ("x ^y@1.2 debug=false ~debug", spack.variant.DuplicateVariantError),
+ ("x@1.2+debug+debug", "variant"),
+ ("x ^y@1.2+debug debug=true", "variant"),
+ ("x ^y@1.2 debug=false debug=true", "variant"),
+ ("x ^y@1.2 debug=false ~debug", "variant"),
# Multiple versions
- ("x@1.2@2.3", spack.spec.MultipleVersionError),
- ("x@1.2:2.3@1.4", spack.spec.MultipleVersionError),
- ("x@1.2@2.3:2.4", spack.spec.MultipleVersionError),
- ("x@1.2@2.3,2.4", spack.spec.MultipleVersionError),
- ("x@1.2 +foo~bar @2.3", spack.spec.MultipleVersionError),
- ("x@1.2%y@1.2@2.3:2.4", spack.spec.MultipleVersionError),
+ ("x@1.2@2.3", "version"),
+ ("x@1.2:2.3@1.4", "version"),
+ ("x@1.2@2.3:2.4", "version"),
+ ("x@1.2@2.3,2.4", "version"),
+ ("x@1.2 +foo~bar @2.3", "version"),
+ ("x@1.2%y@1.2@2.3:2.4", "version"),
# Duplicate dependency
- ("x ^y@1 ^y@2", spack.spec.DuplicateDependencyError),
+ ("x ^y@1 ^y@2", "Cannot depend on incompatible specs"),
# Duplicate compiler
- ("x%intel%intel", spack.spec.DuplicateCompilerSpecError),
- ("x%intel%gcc", spack.spec.DuplicateCompilerSpecError),
- ("x%gcc%intel", spack.spec.DuplicateCompilerSpecError),
- ("x ^y%intel%intel", spack.spec.DuplicateCompilerSpecError),
- ("x ^y%intel%gcc", spack.spec.DuplicateCompilerSpecError),
- ("x ^y%gcc%intel", spack.spec.DuplicateCompilerSpecError),
+ ("x%intel%intel", "compiler"),
+ ("x%intel%gcc", "compiler"),
+ ("x%gcc%intel", "compiler"),
+ ("x ^y%intel%intel", "compiler"),
+ ("x ^y%intel%gcc", "compiler"),
+ ("x ^y%gcc%intel", "compiler"),
# Duplicate Architectures
- (
- "x arch=linux-rhel7-x86_64 arch=linux-rhel7-x86_64",
- spack.spec.DuplicateArchitectureError,
- ),
- (
- "x arch=linux-rhel7-x86_64 arch=linux-rhel7-ppc64le",
- spack.spec.DuplicateArchitectureError,
- ),
- (
- "x arch=linux-rhel7-ppc64le arch=linux-rhel7-x86_64",
- spack.spec.DuplicateArchitectureError,
- ),
- (
- "y ^x arch=linux-rhel7-x86_64 arch=linux-rhel7-x86_64",
- spack.spec.DuplicateArchitectureError,
- ),
- (
- "y ^x arch=linux-rhel7-x86_64 arch=linux-rhel7-ppc64le",
- spack.spec.DuplicateArchitectureError,
- ),
- ("x os=fe os=fe", spack.spec.DuplicateArchitectureError),
- ("x os=fe os=be", spack.spec.DuplicateArchitectureError),
- ("x target=fe target=fe", spack.spec.DuplicateArchitectureError),
- ("x target=fe target=be", spack.spec.DuplicateArchitectureError),
- ("x platform=test platform=test", spack.spec.DuplicateArchitectureError),
- ("x os=fe platform=test target=fe os=fe", spack.spec.DuplicateArchitectureError),
- ("x target=be platform=test os=be os=fe", spack.spec.DuplicateArchitectureError),
- ("^[@foo] zlib", spack.parser.SpecParsingError),
+ ("x arch=linux-rhel7-x86_64 arch=linux-rhel7-x86_64", "two architectures"),
+ ("x arch=linux-rhel7-x86_64 arch=linux-rhel7-ppc64le", "two architectures"),
+ ("x arch=linux-rhel7-ppc64le arch=linux-rhel7-x86_64", "two architectures"),
+ ("y ^x arch=linux-rhel7-x86_64 arch=linux-rhel7-x86_64", "two architectures"),
+ ("y ^x arch=linux-rhel7-x86_64 arch=linux-rhel7-ppc64le", "two architectures"),
+ ("x os=fe os=fe", "'os'"),
+ ("x os=fe os=be", "'os'"),
+ ("x target=fe target=fe", "'target'"),
+ ("x target=fe target=be", "'target'"),
+ ("x platform=test platform=test", "'platform'"),
+ # TODO: these two seem wrong: need to change how arch is initialized (should fail on os)
+ ("x os=fe platform=test target=fe os=fe", "'platform'"),
+ ("x target=be platform=test os=be os=fe", "'platform'"),
+ # Dependencies
+ ("^[@foo] zlib", "edge attributes"),
+ ("x ^[deptypes=link]foo ^[deptypes=run]foo", "conflicting dependency types"),
+ ("x ^[deptypes=build,link]foo ^[deptypes=link]foo", "conflicting dependency types"),
# TODO: Remove this as soon as use variants are added and we can parse custom attributes
- ("^[foo=bar] zlib", spack.parser.SpecParsingError),
+ ("^[foo=bar] zlib", "edge attributes"),
+ # Propagating reserved names generates a parse error
+ ("x namespace==foo.bar.baz", "Propagation"),
+ ("x arch==linux-rhel9-x86_64", "Propagation"),
+ ("x architecture==linux-rhel9-x86_64", "Propagation"),
+ ("x os==rhel9", "Propagation"),
+ ("x operating_system==rhel9", "Propagation"),
+ ("x target==x86_64", "Propagation"),
+ ("x dev_path==/foo/bar/baz", "Propagation"),
+ ("x patches==abcde12345,12345abcde", "Propagation"),
],
)
-def test_error_conditions(text, exc_cls):
- with pytest.raises(exc_cls):
+def test_error_conditions(text, match_string):
+ with pytest.raises(spack.parser.SpecParsingError, match=match_string):
SpecParser(text).next_spec()