summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2018-07-22 16:15:37 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2018-07-25 23:10:10 -0700
commit020c34e13665c508d5afe13da52042d791d22367 (patch)
tree041246e7575f7cc6dfbb0652842e7d00541bda6a /lib
parent6f7eaecfa0ee0a6bbe5652c9c1d5cc6c367b799a (diff)
downloadspack-020c34e13665c508d5afe13da52042d791d22367.tar.gz
spack-020c34e13665c508d5afe13da52042d791d22367.tar.bz2
spack-020c34e13665c508d5afe13da52042d791d22367.tar.xz
spack-020c34e13665c508d5afe13da52042d791d22367.zip
tests: add checks and tests for consistent version() arguments
- Previously, Spack didn't check the arguments you put in version() directives. - So, you could do something like this, where there are arguments for a URL fetcher AND for a git fetcher: version('1.0', md5='abc123', git='https://foo.bar', commit='feda2343') - Now, we check the arguments before constructing a fetcher, to ensure that each package has *only* arguments for a single type of fetcher. - Also added `test_package_version_consistency()` to the `package_sanity` test, so that all builtin packages are required to have valid `version()` directives.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/fetch_strategy.py24
-rw-r--r--lib/spack/spack/test/package_sanity.py10
-rw-r--r--lib/spack/spack/test/packages.py28
3 files changed, 60 insertions, 2 deletions
diff --git a/lib/spack/spack/fetch_strategy.py b/lib/spack/spack/fetch_strategy.py
index 3245f56482..38b837b659 100644
--- a/lib/spack/spack/fetch_strategy.py
+++ b/lib/spack/spack/fetch_strategy.py
@@ -993,6 +993,27 @@ def check_pkg_attributes(pkg):
% (pkg.name, comma_and(quote(conflicts))))
+def _check_version_attributes(fetcher, pkg, version):
+ """Ensure that the fetcher for a version is not ambiguous.
+
+ This assumes that we have already determined the fetcher for the
+ specific version using ``for_package_version()``
+ """
+ all_optionals = set(a for s in all_strategies for a in s.optional_attrs)
+
+ args = pkg.versions[version]
+ extra = set(args) - set(fetcher.optional_attrs) - set([fetcher.url_attr])
+ extra.intersection_update(all_optionals)
+
+ if extra:
+ legal_attrs = [fetcher.url_attr] + list(fetcher.optional_attrs)
+ raise FetcherConflict(
+ "%s version '%s' has extra arguments: %s"
+ % (pkg.name, version, comma_and(quote(extra))),
+ "Valid arguments for a %s fetcher are: \n %s"
+ % (fetcher.url_attr, comma_and(quote(legal_attrs))))
+
+
def _extrapolate(pkg, version):
"""Create a fetcher from an extrapolated URL for this version."""
try:
@@ -1033,6 +1054,7 @@ def for_package_version(pkg, version):
# If the version specifies a `url_attr` directly, use that.
for fetcher in all_strategies:
if fetcher.url_attr in args:
+ _check_version_attributes(fetcher, pkg, version)
return fetcher(**args)
# if a version's optional attributes imply a particular fetch
@@ -1041,6 +1063,7 @@ def for_package_version(pkg, version):
if hasattr(pkg, fetcher.url_attr) or fetcher.url_attr == 'url':
optionals = fetcher.optional_attrs
if optionals and any(a in args for a in optionals):
+ _check_version_attributes(fetcher, pkg, version)
return _from_merged_attrs(fetcher, pkg, version)
# if the optional attributes tell us nothing, then use any `url_attr`
@@ -1048,6 +1071,7 @@ def for_package_version(pkg, version):
# defined first in this file.
for fetcher in all_strategies:
if hasattr(pkg, fetcher.url_attr):
+ _check_version_attributes(fetcher, pkg, version)
return _from_merged_attrs(fetcher, pkg, version)
raise InvalidArgsError(pkg, version, **args)
diff --git a/lib/spack/spack/test/package_sanity.py b/lib/spack/spack/test/package_sanity.py
index 0c26fd7d95..74890664a6 100644
--- a/lib/spack/spack/test/package_sanity.py
+++ b/lib/spack/spack/test/package_sanity.py
@@ -29,6 +29,7 @@ import pytest
import spack.paths
import spack.repo
+import spack.fetch_strategy
def check_repo():
@@ -68,3 +69,12 @@ def test_all_virtual_packages_have_default_providers():
for provider in providers:
assert provider in default_providers
+
+
+def test_package_version_consistency():
+ """Make sure all versions on builtin packages can produce a fetcher."""
+ for name in spack.repo.all_package_names():
+ pkg = spack.repo.get(name)
+ spack.fetch_strategy.check_pkg_attributes(pkg)
+ for version in pkg.versions:
+ assert spack.fetch_strategy.for_package_version(pkg, version)
diff --git a/lib/spack/spack/test/packages.py b/lib/spack/spack/test/packages.py
index d50de07a57..464e37a8d2 100644
--- a/lib/spack/spack/test/packages.py
+++ b/lib/spack/spack/test/packages.py
@@ -275,8 +275,8 @@ def test_two_vcs_fetchers_top_level(mock_packages, config):
spack.fetch_strategy.for_package_version(pkg, '1.0')
-def test_git_url_top_level(mock_packages, config):
- """Test fetch strategy inference when url is specified with a VCS."""
+def test_git_url_top_level_url_versions(mock_packages, config):
+ """Test URL fetch strategy inference when url is specified with git."""
pkg = spack.repo.get('git-url-top-level')
@@ -300,6 +300,12 @@ def test_git_url_top_level(mock_packages, config):
assert fetcher.url == 'https://www.example.com/foo2.3.tar.gz'
assert fetcher.digest == 'abc23'
+
+def test_git_url_top_level_git_versions(mock_packages, config):
+ """Test git fetch strategy inference when url is specified with git."""
+
+ pkg = spack.repo.get('git-url-top-level')
+
fetcher = spack.fetch_strategy.for_package_version(pkg, '3.0')
assert isinstance(fetcher, spack.fetch_strategy.GitFetchStrategy)
assert fetcher.url == 'https://example.com/some/git/repo'
@@ -341,3 +347,21 @@ def test_git_url_top_level(mock_packages, config):
assert fetcher.tag is None
assert fetcher.commit is None
assert fetcher.branch == 'develop'
+
+
+def test_git_url_top_level_conflicts(mock_packages, config):
+ """Test git fetch strategy inference when url is specified with git."""
+
+ pkg = spack.repo.get('git-url-top-level')
+
+ with pytest.raises(spack.fetch_strategy.FetcherConflict):
+ spack.fetch_strategy.for_package_version(pkg, '1.0')
+
+ with pytest.raises(spack.fetch_strategy.FetcherConflict):
+ spack.fetch_strategy.for_package_version(pkg, '1.1')
+
+ with pytest.raises(spack.fetch_strategy.FetcherConflict):
+ spack.fetch_strategy.for_package_version(pkg, '1.2')
+
+ with pytest.raises(spack.fetch_strategy.FetcherConflict):
+ spack.fetch_strategy.for_package_version(pkg, '1.3')