1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# Copyright 2013-2023 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)
"""Test for multi_method dispatch."""
import pytest
import spack.platforms
import spack.repo
import spack.spec
from spack.multimethod import NoSuchMethodError
pytestmark = [
pytest.mark.usefixtures("mock_packages", "config"),
pytest.mark.only_clingo("The original concretizer cannot concretize most of the specs"),
pytest.mark.not_on_windows("Not running on windows"),
]
@pytest.fixture(scope="module", params=["multimethod", "multimethod-inheritor"])
def pkg_name(request):
"""Make tests run on both multimethod and multimethod-inheritor.
This means we test all of our @when methods on a class that uses them
directly, AND on a class that inherits them.
"""
return request.param
def test_no_version_match(pkg_name):
spec = spack.spec.Spec(pkg_name + "@2.0").concretized()
with pytest.raises(NoSuchMethodError):
spec.package.no_version_2()
@pytest.mark.parametrize(
"constraint_str,method_name,expected_result",
[
# Only one version match these constraints
("@1.0", "no_version_2", 1),
("@3.0", "no_version_2", 3),
("@4.0", "no_version_2", 4),
# These constraints overlap, in which case the first match wins
("@2.0", "version_overlap", 1),
("@5.0", "version_overlap", 2),
# These constraints are on the version of a virtual dependency
("^mpich@3.0.4", "mpi_version", 3),
("^mpich2@1.2", "mpi_version", 2),
("^mpich@1.0", "mpi_version", 1),
# Undefined mpi versions
("^mpich@=0.4", "mpi_version", 1),
("^mpich@=1.4", "mpi_version", 1),
# Constraints on compilers with a default
("%gcc", "has_a_default", "gcc"),
("%clang", "has_a_default", "clang"),
("%apple-clang os=elcapitan", "has_a_default", "default"),
# Constraints on dependencies
("^zmpi", "different_by_dep", "zmpi"),
("^mpich", "different_by_dep", "mpich"),
# Constraints on virtual dependencies
("^mpich2", "different_by_virtual_dep", 2),
("^mpich@1.0", "different_by_virtual_dep", 1),
# Multimethod with base classes
("@1", "base_method", "base_method"),
# Boolean
("", "boolean_true_first", "True"),
("", "boolean_false_first", "True"),
],
)
def test_multimethod_calls(pkg_name, constraint_str, method_name, expected_result):
s = spack.spec.Spec(pkg_name + constraint_str).concretized()
msg = "Method {0} from {1} is giving a wrong result".format(method_name, s)
assert getattr(s.package, method_name)() == expected_result, msg
def test_target_match(pkg_name):
platform = spack.platforms.host()
targets = list(platform.targets.values())
for target in targets[:-1]:
s = spack.spec.Spec(pkg_name + " target=" + target.name).concretized()
assert s.package.different_by_target() == target.name
s = spack.spec.Spec(pkg_name + " target=" + targets[-1].name).concretized()
if len(targets) == 1:
assert s.package.different_by_target() == targets[-1].name
else:
with pytest.raises(NoSuchMethodError):
s.package.different_by_target()
@pytest.mark.parametrize(
"spec_str,method_name,expected_result",
[
# This is overridden in the second case
("multimethod@3", "base_method", "multimethod"),
("multimethod-inheritor@3", "base_method", "multimethod-inheritor"),
# Here we have a mix of inherited and overridden methods
("multimethod-inheritor@1.0", "inherited_and_overridden", "inheritor@1.0"),
("multimethod-inheritor@2.0", "inherited_and_overridden", "base@2.0"),
("multimethod@1.0", "inherited_and_overridden", "base@1.0"),
("multimethod@2.0", "inherited_and_overridden", "base@2.0"),
# Diamond-like inheritance (even though the MRO linearize everything)
("multimethod-diamond@1.0", "diamond_inheritance", "base_package"),
("multimethod-base@=1.0", "diamond_inheritance", "base_package"),
("multimethod-diamond@2.0", "diamond_inheritance", "first_parent"),
("multimethod-inheritor@2.0", "diamond_inheritance", "first_parent"),
("multimethod-diamond@=3.0", "diamond_inheritance", "second_parent"),
("multimethod-diamond-parent@=3.0", "diamond_inheritance", "second_parent"),
("multimethod-diamond@4.0", "diamond_inheritance", "subclass"),
],
)
def test_multimethod_calls_and_inheritance(spec_str, method_name, expected_result):
s = spack.spec.Spec(spec_str).concretized()
assert getattr(s.package, method_name)() == expected_result
|