diff options
Diffstat (limited to 'lib/spack/spack/test/spec_syntax.py')
-rw-r--r-- | lib/spack/spack/test/spec_syntax.py | 154 |
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() |