Source code for spack.test.spec_list

# Copyright 2013-2022 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)
import itertools

import pytest

from spack.spec import Spec
from spack.spec_list import SpecList


[docs]class TestSpecList(object): default_input = ['mpileaks', '$mpis', {'matrix': [['hypre'], ['$gccs', '$clangs']]}, 'libelf'] default_reference = {'gccs': SpecList('gccs', ['%gcc@4.5.0']), 'clangs': SpecList('clangs', ['%clang@3.3']), 'mpis': SpecList('mpis', ['zmpi@1.0', 'mpich@3.0'])} default_expansion = ['mpileaks', 'zmpi@1.0', 'mpich@3.0', {'matrix': [ ['hypre'], ['%gcc@4.5.0', '%clang@3.3'], ]}, 'libelf'] default_constraints = [[Spec('mpileaks')], [Spec('zmpi@1.0')], [Spec('mpich@3.0')], [Spec('hypre'), Spec('%gcc@4.5.0')], [Spec('hypre'), Spec('%clang@3.3')], [Spec('libelf')]] default_specs = [Spec('mpileaks'), Spec('zmpi@1.0'), Spec('mpich@3.0'), Spec('hypre%gcc@4.5.0'), Spec('hypre%clang@3.3'), Spec('libelf')]
[docs] def test_spec_list_expansions(self): speclist = SpecList('specs', self.default_input, self.default_reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs
[docs] @pytest.mark.regression('28749') @pytest.mark.parametrize('specs,expected', [ # Constraints are ordered randomly ([{'matrix': [ ['^zmpi'], ['%gcc@4.5.0'], ['hypre', 'libelf'], ['~shared'], ['cflags=-O3', 'cflags="-g -O0"'], ['^foo'] ]}], [ 'hypre cflags=-O3 ~shared %gcc@4.5.0 ^foo ^zmpi', 'hypre cflags="-g -O0" ~shared %gcc@4.5.0 ^foo ^zmpi', 'libelf cflags=-O3 ~shared %gcc@4.5.0 ^foo ^zmpi', 'libelf cflags="-g -O0" ~shared %gcc@4.5.0 ^foo ^zmpi', ]), # A constraint affects both the root and a dependency ([{'matrix': [ ['gromacs'], ['%gcc'], ['+plumed ^plumed%gcc'] ]}], [ 'gromacs+plumed%gcc ^plumed%gcc' ]) ]) def test_spec_list_constraint_ordering(self, specs, expected): speclist = SpecList('specs', specs) expected_specs = [Spec(x) for x in expected] assert speclist.specs == expected_specs
[docs] def test_spec_list_add(self): speclist = SpecList('specs', self.default_input, self.default_reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs speclist.add('libdwarf') assert speclist.specs_as_yaml_list == self.default_expansion + [ 'libdwarf'] assert speclist.specs_as_constraints == self.default_constraints + [ [Spec('libdwarf')]] assert speclist.specs == self.default_specs + [Spec('libdwarf')]
[docs] def test_spec_list_remove(self): speclist = SpecList('specs', self.default_input, self.default_reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs speclist.remove('libelf') assert speclist.specs_as_yaml_list + [ 'libelf' ] == self.default_expansion assert speclist.specs_as_constraints + [ [Spec('libelf')] ] == self.default_constraints assert speclist.specs + [Spec('libelf')] == self.default_specs
[docs] def test_spec_list_update_reference(self): speclist = SpecList('specs', self.default_input, self.default_reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs new_mpis = SpecList('mpis', self.default_reference['mpis'].yaml_list) new_mpis.add('mpich@3.3') new_reference = self.default_reference.copy() new_reference['mpis'] = new_mpis speclist.update_reference(new_reference) expansion = list(self.default_expansion) expansion.insert(3, 'mpich@3.3') constraints = list(self.default_constraints) constraints.insert(3, [Spec('mpich@3.3')]) specs = list(self.default_specs) specs.insert(3, Spec('mpich@3.3')) assert speclist.specs_as_yaml_list == expansion assert speclist.specs_as_constraints == constraints assert speclist.specs == specs
[docs] def test_spec_list_extension(self): speclist = SpecList('specs', self.default_input, self.default_reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs new_ref = self.default_reference.copy() otherlist = SpecList('specs', ['zlib', {'matrix': [['callpath'], ['%intel@18']]}], new_ref) speclist.extend(otherlist) assert speclist.specs_as_yaml_list == (self.default_expansion + otherlist.specs_as_yaml_list) assert speclist.specs == self.default_specs + otherlist.specs assert speclist._reference is new_ref
[docs] def test_spec_list_nested_matrices(self): inner_matrix = [{'matrix': [['zlib', 'libelf'], ['%gcc', '%intel']]}] outer_addition = ['+shared', '~shared'] outer_matrix = [{'matrix': [inner_matrix, outer_addition]}] speclist = SpecList('specs', outer_matrix) expected_components = itertools.product(['zlib', 'libelf'], ['%gcc', '%intel'], ['+shared', '~shared']) expected = [Spec(' '.join(combo)) for combo in expected_components] assert set(speclist.specs) == set(expected)
[docs] @pytest.mark.regression('16897') def test_spec_list_recursion_specs_as_constraints(self): input = ['mpileaks', '$mpis', {'matrix': [['hypre'], ['$%gccs', '$%clangs']]}, 'libelf'] reference = {'gccs': SpecList('gccs', ['gcc@4.5.0']), 'clangs': SpecList('clangs', ['clang@3.3']), 'mpis': SpecList('mpis', ['zmpi@1.0', 'mpich@3.0'])} speclist = SpecList('specs', input, reference) assert speclist.specs_as_yaml_list == self.default_expansion assert speclist.specs_as_constraints == self.default_constraints assert speclist.specs == self.default_specs
[docs] def test_spec_list_matrix_exclude(self, mock_packages): # Test on non-boolean variants for regression for #16841 matrix = [{'matrix': [['multivalue-variant'], ['foo=bar', 'foo=baz']], 'exclude': ['foo=bar']}] speclist = SpecList('specs', matrix) assert len(speclist.specs) == 1