Compare commits

...

6 Commits

Author SHA1 Message Date
Gregory Becker
5a23819165 style 2023-03-23 12:48:02 -07:00
Gregory Becker
9df3b57f1f update broadcast test to test excludes as well 2023-03-23 11:24:47 -07:00
Gregory Becker
788ad561bd fix excludes with bcast 2023-03-23 11:24:06 -07:00
becker33
c8c025215d [@spackbot] updating style on behalf of becker33 2023-03-13 17:14:28 +00:00
Gregory Becker
1df6a3196a matrix broadcast: more robust test 2023-02-23 15:47:11 -08:00
Gregory Becker
7014eb3236 matrices: broadcast key combinatorially applies to all nodes in matrix 2023-02-23 15:40:34 -08:00
3 changed files with 60 additions and 19 deletions

View File

@ -30,6 +30,10 @@
"type": "array", "type": "array",
"items": {"type": "array", "items": {"type": "string"}}, "items": {"type": "array", "items": {"type": "string"}},
}, },
"broadcast": {
"type": "array",
"items": {"type": "array", "items": {"type": "string"}},
},
"exclude": {"type": "array", "items": {"type": "string"}}, "exclude": {"type": "array", "items": {"type": "string"}},
}, },
}, },

View File

@ -186,41 +186,64 @@ def _expand_matrix_constraints(matrix_config):
new_row.append([r]) new_row.append([r])
expanded_rows.append(new_row) expanded_rows.append(new_row)
# TODO someday: allow matrices inside `broadcast`
broadcast_rows = matrix_config.get("broadcast", [])
excludes = matrix_config.get("exclude", []) # only compute once excludes = matrix_config.get("exclude", []) # only compute once
sigil = matrix_config.get("sigil", "") sigil = matrix_config.get("sigil", "")
broadcast_constraints = list(itertools.product(*broadcast_rows))
results = [] results = []
for combo in itertools.product(*expanded_rows): for combo in itertools.product(*expanded_rows):
# Construct a combined spec to test against excludes # Construct a combined spec to test against excludes
flat_combo = [constraint for constraint_list in combo for constraint in constraint_list] flat_combo = [constraint for constraint_list in combo for constraint in constraint_list]
flat_combo = [Spec(x) for x in flat_combo] flat_combo = [Spec(x) for x in flat_combo]
test_spec = flat_combo[0].copy() # If no broadcast, this is [(,)].
for constraint in flat_combo[1:]: # It will run once, as required, and apply no constraints
test_spec.constrain(constraint) for broadcast_combo in broadcast_constraints:
final_combo = [_apply_broadcast(spec.copy(), broadcast_combo) for spec in flat_combo]
# Abstract variants don't have normal satisfaction semantics # Check whether final spec is excluded
# Convert all variants to concrete types. # requires constructing a spec from constraints
# This method is best effort, so all existing variants will be test_spec = final_combo[0].copy()
# converted before any error is raised. for constraint in final_combo[1:]:
# Catch exceptions because we want to be able to operate on test_spec.constrain(constraint)
# abstract specs without needing package information
try:
spack.variant.substitute_abstract_variants(test_spec)
except spack.variant.UnknownVariantError:
pass
if any(test_spec.satisfies(x) for x in excludes):
continue
if sigil: # Abstract variants don't have normal satisfaction semantics
flat_combo[0] = Spec(sigil + str(flat_combo[0])) # Convert all variants to concrete types.
# This method is best effort, so all existing variants will be
# converted before any error is raised.
# Catch exceptions because we want to be able to operate on
# abstract specs without needing package information
try:
spack.variant.substitute_abstract_variants(test_spec)
except spack.variant.UnknownVariantError:
pass
# Add to list of constraints # actual exclusion check is here
results.append(flat_combo) if any(test_spec.satisfies(e) for e in excludes):
continue
# Apply sigil if applicable
if sigil:
final_combo[0] = Spec(sigil + str(final_combo[0]))
# Add to list of constraints
results.append(final_combo)
return results return results
def _apply_broadcast(spec, constraints):
if constraints:
for node in spec.traverse():
if node.name:
for constraint in constraints:
node.constrain(constraint)
return spec
def _sigilify(item, sigil): def _sigilify(item, sigil):
if isinstance(item, dict): if isinstance(item, dict):
if sigil: if sigil:

View File

@ -214,3 +214,17 @@ def test_spec_list_constraints_with_structure(
speclist = SpecList("specs", [matrix]) speclist = SpecList("specs", [matrix])
assert len(speclist.specs) == 1 assert len(speclist.specs) == 1
assert libdwarf_spec in speclist.specs[0] assert libdwarf_spec in speclist.specs[0]
def test_spec_list_broadcast(self, mock_packages):
matrix = {
"matrix": [["mpileaks"], ["^callpath"]],
"broadcast": [["%gcc", "%clang"], ["+debug", "~debug"]],
"exclude": ["+debug%clang"],
}
speclist = SpecList("specs", [matrix])
assert len(speclist) == 3
for spec in speclist:
for node in spec.traverse():
assert node.compiler.name == spec.compiler.name
assert node.variants["debug"].value == spec.variants["debug"].value