spack audit externals: allow selecting platforms and checking extra attributes (#43782)

This commit is contained in:
Massimiliano Culpo 2024-04-26 12:47:17 +02:00 committed by GitHub
parent e3cb4f09f0
commit ac9012da0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 124 additions and 3 deletions

View file

@ -34,7 +34,7 @@ jobs:
run: |
. share/spack/setup-env.sh
coverage run $(which spack) audit packages
coverage run $(which spack) audit externals
coverage run $(which spack) -d audit externals
coverage combine
coverage xml
- name: Package audits (without coverage)

View file

@ -6435,9 +6435,12 @@ the ``paths`` attribute:
echo "Target: x86_64-pc-linux-gnu"
echo "Thread model: posix"
echo "InstalledDir: /usr/bin"
platforms: ["linux", "darwin"]
results:
- spec: 'llvm@3.9.1 +clang~lld~lldb'
If the ``platforms`` attribute is present, tests are run only if the current host
matches one of the listed platforms.
Each test is performed by first creating a temporary directory structure as
specified in the corresponding ``layout`` and by then running
package detection and checking that the outcome matches the expected
@ -6471,6 +6474,10 @@ package detection and checking that the outcome matches the expected
- A spec that is expected from detection
- Any valid spec
- Yes
* - ``results:[0]:extra_attributes``
- Extra attributes expected on the associated Spec
- Nested dictionary with string as keys, and regular expressions as leaf values
- No
"""""""""""""""""""""""""""""""
Reuse tests from other packages

View file

@ -1111,4 +1111,76 @@ def _test_detection_by_executable(pkgs, error_cls):
details = [msg.format(s, idx) for s in sorted(not_expected)]
errors.append(error_cls(summary=summary, details=details))
matched_detection = []
for candidate in expected_specs:
try:
idx = specs.index(candidate)
except (AttributeError, ValueError):
pass
matched_detection.append((candidate, specs[idx]))
def _compare_extra_attribute(_expected, _detected, *, _spec):
result = []
# Check items are of the same type
if not isinstance(_detected, type(_expected)):
_summary = f'{pkg_name}: error when trying to detect "{_expected}"'
_details = [f"{_detected} was detected instead"]
return [error_cls(summary=_summary, details=_details)]
# If they are string expected is a regex
if isinstance(_expected, str):
try:
_regex = re.compile(_expected)
except re.error:
_summary = f'{pkg_name}: illegal regex in "{_spec}" extra attributes'
_details = [f"{_expected} is not a valid regex"]
return [error_cls(summary=_summary, details=_details)]
if not _regex.match(_detected):
_summary = (
f'{pkg_name}: error when trying to match "{_expected}" '
f"in extra attributes"
)
_details = [f"{_detected} does not match the regex"]
return [error_cls(summary=_summary, details=_details)]
if isinstance(_expected, dict):
_not_detected = set(_expected.keys()) - set(_detected.keys())
if _not_detected:
_summary = f"{pkg_name}: cannot detect some attributes for spec {_spec}"
_details = [
f'"{_expected}" was expected',
f'"{_detected}" was detected',
] + [f'attribute "{s}" was not detected' for s in sorted(_not_detected)]
result.append(error_cls(summary=_summary, details=_details))
_common = set(_expected.keys()) & set(_detected.keys())
for _key in _common:
result.extend(
_compare_extra_attribute(_expected[_key], _detected[_key], _spec=_spec)
)
return result
for expected, detected in matched_detection:
# We might not want to test all attributes, so avoid not_expected
not_detected = set(expected.extra_attributes) - set(detected.extra_attributes)
if not_detected:
summary = f"{pkg_name}: cannot detect some attributes for spec {expected}"
details = [
f'"{s}" was not detected [test_id={idx}]' for s in sorted(not_detected)
]
errors.append(error_cls(summary=summary, details=details))
common = set(expected.extra_attributes) & set(detected.extra_attributes)
for key in common:
errors.extend(
_compare_extra_attribute(
expected.extra_attributes[key],
detected.extra_attributes[key],
_spec=expected,
)
)
return errors

View file

@ -11,6 +11,7 @@
from llnl.util import filesystem
import spack.platforms
import spack.repo
import spack.spec
from spack.util import spack_yaml
@ -32,6 +33,8 @@ class ExpectedTestResult(NamedTuple):
#: Spec to be detected
spec: str
#: Attributes expected in the external spec
extra_attributes: Dict[str, str]
class DetectionTest(NamedTuple):
@ -100,7 +103,10 @@ def _create_executable_scripts(self, mock_executables: MockExecutables) -> List[
@property
def expected_specs(self) -> List[spack.spec.Spec]:
return [spack.spec.Spec(r.spec) for r in self.test.results]
return [
spack.spec.Spec.from_detection(item.spec, extra_attributes=item.extra_attributes)
for item in self.test.results
]
def detection_tests(pkg_name: str, repository: spack.repo.RepoPath) -> List[Runner]:
@ -117,9 +123,13 @@ def detection_tests(pkg_name: str, repository: spack.repo.RepoPath) -> List[Runn
"""
result = []
detection_tests_content = read_detection_tests(pkg_name, repository)
current_platform = str(spack.platforms.host())
tests_by_path = detection_tests_content.get("paths", [])
for single_test_data in tests_by_path:
if current_platform not in single_test_data.get("platforms", [current_platform]):
continue
mock_executables = []
for layout in single_test_data["layout"]:
mock_executables.append(
@ -127,7 +137,11 @@ def detection_tests(pkg_name: str, repository: spack.repo.RepoPath) -> List[Runn
)
expected_results = []
for assertion in single_test_data["results"]:
expected_results.append(ExpectedTestResult(spec=assertion["spec"]))
expected_results.append(
ExpectedTestResult(
spec=assertion["spec"], extra_attributes=assertion.get("extra_attributes", {})
)
)
current_test = DetectionTest(
pkg_name=pkg_name, layout=mock_executables, results=expected_results

View file

@ -9,6 +9,7 @@ paths:
echo "Target: x86_64-apple-darwin19.5.0"
echo "Thread model: posix"
echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin"
platforms: ["darwin"]
results:
- spec: 'apple-clang@11.0.0'
# Apple Clang on Apple M1 (Ventura)
@ -21,6 +22,7 @@ paths:
echo "Target: arm64-apple-darwin22.6.0"
echo "Thread model: posix"
echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin"
platforms: ["darwin"]
results:
- spec: 'apple-clang@15.0.0'
# Test that missing a compiler prevents the package from being detected
@ -32,4 +34,5 @@ paths:
echo "Target: x86_64-apple-darwin19.5.0"
echo "Thread model: posix"
echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin"
platforms: ["darwin"]
results: [ ]

View file

@ -20,8 +20,13 @@ paths:
echo "mock executable got an unexpected flag: $1"
exit 1
fi
platforms: ["darwin", "linux"]
results:
- spec: "gcc@9.4.0 languages=c,c++"
extra_attributes:
compilers:
c: ".*/bin/gcc"
cxx: ".*/bin/g++"
# Mock a version < 7 of GCC that requires -dumpversion and
# errors with -dumpfullversion
- layout:
@ -37,8 +42,14 @@ paths:
echo "compilation terminated."
exit 1
fi
platforms: ["darwin", "linux"]
results:
- spec: "gcc@5.5.0 languages=c,c++,fortran"
extra_attributes:
compilers:
c: ".*/bin/gcc-5$"
cxx: ".*/bin/g[+][+]-5$"
fortran: ".*/bin/gfortran-5$"
# Multiple compilers present at the same time
- layout:
- executables:
@ -50,7 +61,14 @@ paths:
script: "echo 10.1.0"
results:
- spec: "gcc@6.5.0 languages=c"
extra_attributes:
compilers:
c: ".*/bin/x86_64-linux-gnu-gcc-6$"
- spec: "gcc@10.1.0 languages=c,c++"
extra_attributes:
compilers:
c: ".*/bin/x86_64-linux-gnu-gcc-10$"
cxx: ".*/bin/x86_64-linux-gnu-g[+][+]-10$"
# Apple clang under disguise as gcc should not be detected
- layout:
- executables:
@ -70,4 +88,5 @@ paths:
echo "mock executable got an unexpected flag: $1"
exit 1
fi
platforms: ["darwin"]
results: []

View file

@ -15,5 +15,6 @@ paths:
script: |
echo "ifort (IFORT) 18.0.5 20180823"
echo "Copyright (C) 1985-2018 Intel Corporation. All rights reserved."
platforms: ["darwin", "linux"]
results:
- spec: 'intel@18.0.5'

View file

@ -14,6 +14,7 @@ paths:
echo "Target: x86_64-pc-linux-gnu"
echo "Thread model: posix"
echo "InstalledDir: /usr/bin"
platforms: ["darwin", "linux"]
results:
- spec: 'llvm@3.9.1 +clang~lld~lldb'
# Multiple LLVM packages in the same prefix
@ -40,6 +41,7 @@ paths:
echo "Target: x86_64-pc-linux-gnu"
echo "Thread model: posix"
echo "InstalledDir: /usr/bin"
platforms: ["darwin", "linux"]
results:
- spec: 'llvm@8.0.0+clang+lld+lldb'
- spec: 'llvm@3.9.1+clang~lld~lldb'
@ -53,4 +55,5 @@ paths:
echo "Target: x86_64-apple-darwin19.5.0"
echo "Thread model: posix"
echo "InstalledDir: /Library/Developer/CommandLineTools/usr/bin"
platforms: ["darwin"]
results: []

View file

@ -13,6 +13,7 @@ paths:
script: |
echo "IBM XL Fortran for Linux, V16.1.1 (5725-C73, 5765-J13)"
echo "Version: 16.01.0001.0006"
platforms: ["linux"]
results:
- spec: "xlc+r@16.1"
- spec: "xlc~r@16.1"

View file

@ -6,6 +6,7 @@ paths:
script: |
echo "IBM XL Fortran for Linux, V16.1.1 (5725-C73, 5765-J13)"
echo "Version: 16.01.0001.0006"
platforms: ["linux"]
results:
- spec: "xlf+r@16.1"
- spec: "xlf~r@16.1"