Remove CombinatorialSpecSet in favor of environments + stacks

This commit is contained in:
Scott Wittenburg 2019-05-30 17:46:51 -06:00 committed by Todd Gamblin
parent 0b67f30e21
commit 5323a5cff9
10 changed files with 83 additions and 721 deletions

View file

@ -1,16 +0,0 @@
# -------------------------------------------------------------------------
# This is the default spack release spec set.
# -------------------------------------------------------------------------
spec-set:
include: []
exclude: []
matrix:
- packages:
xsdk:
versions: [0.4.0]
- compilers:
gcc:
versions: [5.5.0]
clang:
versions: [6.0.0, '6.0.0-1ubuntu2']
cdash: ["https://spack.io/cdash/submit.php?project=spack"]

View file

@ -1,21 +0,0 @@
spec-set:
include: [ ape, atompaw, transset]
exclude: [binutils,tk]
packages:
ape:
versions: [2.2.1]
atompaw:
versions: [3.1.0.3, 4.0.0.13]
binutils:
versions: [2.20.1, 2.25, 2.23.2, 2.24, 2.27, 2.26]
tk:
versions: [8.6.5, 8.6.3]
transset:
versions: [1.0.1]
compilers:
gcc:
versions: [4.9, 4.8, 4.7]
clang:
versions: [3.5, 3.6]
dashboard: ["https://spack.io/cdash/submit.php?project=spack"]

View file

@ -20,11 +20,8 @@
import spack.config
import spack.repo
import spack.store
from spack.error import SpecError
from spack.paths import etc_path
from spack.spec import Spec, save_dependency_spec_yamls
from spack.spec_set import CombinatorialSpecSet
from spack.cmd import display_specs
@ -417,10 +414,9 @@ def check_binaries(args):
if args.spec or args.spec_yaml:
specs = [get_concrete_spec(args)]
else:
release_specs_path = os.path.join(
etc_path, 'spack', 'defaults', 'release.yaml')
spec_set = CombinatorialSpecSet.from_file(release_specs_path)
specs = [spec for spec in spec_set]
env = ev.get_env(args, 'buildcache', required=True)
env.concretize()
specs = env.all_specs()
if not specs:
tty.msg('No specs provided, exiting.')

View file

@ -4,17 +4,18 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import json
import sys
from jsonschema import validate, ValidationError
from six import iteritems
from six.moves.urllib.request import build_opener, HTTPHandler, Request
from six.moves.urllib.error import HTTPError, URLError
from six.moves.urllib.parse import urlencode
from six.moves.urllib.request import build_opener, HTTPHandler, Request
import llnl.util.tty as tty
import spack.environment as ev
from spack.dependency import all_deptypes
from spack.error import SpackError
from spack.spec import Spec
from spack.schema.specs_deps import schema as specs_deps_schema
import spack.util.spack_yaml as syaml
@ -42,7 +43,7 @@ def setup_parser(subparser):
help="Print summary of staged jobs to standard output")
subparser.add_argument(
'-c', '--cdash-credentials', default=None,
'--cdash-credentials', default=None,
help="Path to file containing CDash authentication token")
@ -59,9 +60,9 @@ def _create_buildgroup(opener, headers, url, project, group_name, group_type):
response_code = response.getcode()
if response_code != 200 and response_code != 201:
print('Creating buildgroup failed (response code = {0}'.format(
response_code))
return None
msg = 'Creating buildgroup failed (response code = {0}'.format(
response_code)
raise SpackError(msg)
response_text = response.read()
response_json = json.loads(response_text)
@ -71,7 +72,7 @@ def _create_buildgroup(opener, headers, url, project, group_name, group_type):
def populate_buildgroup(job_names, group_name, project, site,
credentials, cdash_url, exit_on_fail=False):
credentials, cdash_url):
url = "{0}/api/v1/buildgroup.php".format(cdash_url)
headers = {
@ -88,8 +89,9 @@ def populate_buildgroup(job_names, group_name, project, site,
'Latest')
if not parent_group_id or not group_id:
print('Unable to create or retrieve the build groups')
sys.exit(1)
msg = 'Failed to create or retrieve buildgroups for {0}'.format(
group_name)
raise SpackError(msg)
data = {
'project': project,
@ -107,10 +109,10 @@ def populate_buildgroup(job_names, group_name, project, site,
response = opener.open(request)
response_code = response.getcode()
if response_code != 200 and exit_on_fail:
print('Unexpected response ({0}) when populating buildgroup'.format(
response_code))
sys.exit(1)
if response_code != 200:
msg = 'Error response code ({0}) in populate_buildgroup'.format(
response_code)
raise SpackError(msg)
def get_job_name(spec, osarch, build_group):
@ -173,24 +175,12 @@ def get_spec_dependencies(specs, deps, spec_labels):
def stage_spec_jobs(specs):
"""Take a set of release specs along with a dictionary describing the
available docker containers and what compilers they have, and generate
a list of "stages", where the jobs in any stage are dependent only on
jobs in previous stages. This allows us to maximize build parallelism
within the gitlab-ci framework.
"""Take a set of release specs and generate a list of "stages", where the
jobs in any stage are dependent only on jobs in previous stages. This
allows us to maximize build parallelism within the gitlab-ci framework.
Arguments:
spec_set (CombinatorialSpecSet): Iterable containing all the specs
to build.
containers (dict): Describes the docker containers available to use
for concretizing specs (and also for the gitlab runners to use
for building packages). The schema can be found at
"lib/spack/spack/schema/os_container_mapping.py"
current_system (string): If provided, this indicates not to use the
containers for concretizing the release specs, but rather just
assume the current system is in the "containers" dictionary. A
SpackError will be raised if the current system is not in that
dictionary.
specs (Iterable): Specs to build
Returns: A tuple of information objects describing the specs, dependencies
and stages:
@ -391,6 +381,8 @@ def release_jobs(parser, args):
env = ev.get_env(args, 'release-jobs', required=True)
env.concretize(force=args.force)
# FIXME: What's the difference between one that opens with 'spack'
# and one that opens with 'env'? This will only handle the former.
yaml_root = env.yaml['spack']
if 'gitlab-ci' not in yaml_root:
@ -514,8 +506,11 @@ def release_jobs(parser, args):
# Use "all_job_names" to populate the build group for this set
if cdash_auth_token:
try:
populate_buildgroup(all_job_names, build_group, cdash_project,
cdash_site, cdash_auth_token, cdash_url)
except (SpackError, HTTPError, URLError) as err:
tty.warn('Problem populating buildgroup: {0}'.format(err))
else:
tty.warn('Unable to populate buildgroup without CDash credentials')

View file

@ -14,7 +14,6 @@
properties = {
'cdash': {
'type': 'object',
'default': {},
'additionalProperties': False,
'required': ['build-group', 'url', 'project', 'site'],
'patternProperties': {

View file

@ -14,7 +14,6 @@
properties = {
'gitlab-ci': {
'type': 'object',
'default': {},
'additionalProperties': False,
'required': ['mappings'],
'patternProperties': {
@ -25,7 +24,6 @@
'patternProperties': {
r'[\w\d\-_\.]+': {
'type': 'object',
'default': {},
'additionalProperties': False,
'required': ['match', 'runner-attributes'],
'properties': {
@ -38,7 +36,6 @@
},
'runner-attributes': {
'type': 'object',
'default': {},
'additionalProperties': True,
'required': ['tags'],
'properties': {

View file

@ -1,111 +0,0 @@
# Copyright 2013-2018 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)
"""Schema for Spack spec-set configuration file.
.. literalinclude:: _spack_root/lib/spack/spack/schema/spec_set.py
:lines: 32-
"""
schema = {
'$schema': 'http://json-schema.org/schema#',
'title': 'Spack test configuration file schema',
'definitions': {
# used for include/exclude
'list_of_specs': {
'type': 'array',
'items': {'type': 'string'}
},
# used for compilers and for packages
'objects_with_version_list': {
'type': 'object',
'additionalProperties': False,
'patternProperties': {
r'\w[\w-]*': {
'type': 'object',
'additionalProperties': False,
'required': ['versions'],
'properties': {
'versions': {
'type': 'array',
'items': {
'oneOf': [
{'type': 'string'},
{'type': 'number'},
],
},
},
},
},
},
},
'packages': {
'type': 'object',
'additionalProperties': False,
'properties': {
'packages': {
'$ref': '#/definitions/objects_with_version_list'
},
}
},
'compilers': {
'type': 'object',
'additionalProperties': False,
'properties': {
'compilers': {
'$ref': '#/definitions/objects_with_version_list'
},
}
},
'specs': {
'type': 'object',
'additionalProperties': False,
'properties': {
'specs': {'$ref': '#/definitions/list_of_specs'},
}
},
},
# this is the actual top level object
'type': 'object',
'additionalProperties': False,
'properties': {
'spec-set': {
'type': 'object',
'additionalProperties': False,
'required': ['matrix'],
'properties': {
# top-level settings are keys and need to be unique
'include': {'$ref': '#/definitions/list_of_specs'},
'exclude': {'$ref': '#/definitions/list_of_specs'},
'cdash': {
'oneOf': [
{'type': 'string'},
{
'type': 'array',
'items': {'type': 'string'}
},
],
},
'project': {
'type': 'string',
},
# things under matrix (packages, compilers, etc.) are a
# list so that we can potentiall have multiple of them.
'matrix': {
'type': 'array',
'items': {
'type': 'object',
'oneOf': [
{'$ref': '#/definitions/specs'},
{'$ref': '#/definitions/packages'},
{'$ref': '#/definitions/compilers'},
],
},
},
},
},
},
}

View file

@ -1,188 +0,0 @@
# Copyright 2013-2018 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
from jsonschema import validate
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
import spack
import spack.compilers
import spack.architecture as sarch
import spack.schema.spec_set as spec_set_schema
import spack.util.spack_yaml as syaml
from spack.error import SpackError
from spack.spec import Spec, ArchSpec
class CombinatorialSpecSet:
"""Set of combinatorial Specs constructed from YAML file."""
def __init__(self, yaml_like, ignore_invalid=True):
"""Construct a combinatorial Spec set.
Args:
yaml_like: either raw YAML data as a dict, a file-like object
to read the YAML from, or a string containing YAML. In the
first case, we assume already-parsed YAML data. In the second
two cases, we just run yaml.load() on the data.
ignore_invalid (bool): whether to ignore invalid specs when
expanding the values of this spec set.
"""
self.ignore_invalid = ignore_invalid
if isinstance(yaml_like, dict):
# if it's raw data, just assign it to self.data
self.data = yaml_like
else:
# otherwise try to load it.
self.data = syaml.load(yaml_like)
# validate against the spec set schema
validate(self.data, spec_set_schema.schema)
# chop off the initial spec-set label after valiation.
self.data = self.data['spec-set']
# initialize these from data.
self.cdash = self.data.get('cdash', None)
if isinstance(self.cdash, str):
self.cdash = [self.cdash]
self.project = self.data.get('project', None)
# _spec_lists is a list of lists of specs, to be combined as a
# cartesian product when we iterate over all specs in the set.
# it's initialized lazily.
self._spec_lists = None
self._include = []
self._exclude = []
@staticmethod
def from_file(path):
try:
with open(path, 'r') as fin:
specs_yaml = syaml.load(fin.read())
# For now, turn off ignoring invalid specs, as it prevents
# iteration if the specified compilers can't be found.
return CombinatorialSpecSet(specs_yaml, ignore_invalid=False)
except Exception as e:
emsg = e.message
if not emsg:
emsg = e.problem
msg = ('Unable to create CombinatorialSpecSet from file ({0})'
' due to {1}'.format(path, emsg))
raise SpackError(msg)
def all_package_versions(self):
"""Get package/version combinations for all spack packages."""
for name in spack.repo.all_package_names():
pkg = spack.repo.get(name)
for v in pkg.versions:
yield Spec('{0}@{1}'.format(name, v))
def _specs(self, data):
"""Read a list of specs from YAML data"""
return [Spec(s) for s in data]
def _compiler_specs(self, data):
"""Read compiler specs from YAML data.
Example YAML:
gcc:
versions: [4.4.8, 4.9.3]
clang:
versions: [3.6.1, 3.7.2, 3.8]
Optionally, data can be 'all', in which case all compilers for
the current platform are returned.
"""
# get usable compilers for current platform.
arch = ArchSpec(str(sarch.platform()), 'default_os', 'default_target')
available_compilers = [
c.spec for c in spack.compilers.compilers_for_arch(arch)]
# return compilers for this platform if asked for everything.
if data == 'all':
return [cspec.copy() for cspec in available_compilers]
# otherwise create specs from the YAML file.
cspecs = set([
Spec('%{0}@{1}'.format(compiler, version))
for compiler in data for version in data[compiler]['versions']])
# filter out invalid specs if caller said to ignore them.
if self.ignore_invalid:
missing = [c for c in cspecs if not any(
c.compiler.satisfies(comp) for comp in available_compilers)]
tty.warn("The following compilers were unavailable:")
colify(sorted(m.compiler for m in missing))
cspecs -= set(missing)
return cspecs
def _package_specs(self, data):
"""Read package/version specs from YAML data.
Example YAML:
gmake:
versions: [4.0, 4.1, 4.2]
qt:
versions: [4.8.6, 5.2.1, 5.7.1]
Optionally, data can be 'all', in which case all packages and
versions from the package repository are returned.
"""
if data == 'all':
return set(self.all_package_versions())
return set([
Spec('{0}@{1}'.format(name, version))
for name in data for version in data[name]['versions']])
def _get_specs(self, matrix_dict):
"""Parse specs out of an element in the build matrix."""
readers = {
'packages': self._package_specs,
'compilers': self._compiler_specs,
'specs': self._specs
}
key = next(iter(matrix_dict), None)
assert key in readers
return readers[key](matrix_dict[key])
def __iter__(self):
# read in data from YAML file lazily.
if self._spec_lists is None:
self._spec_lists = [self._get_specs(spec_list)
for spec_list in self.data['matrix']]
if 'include' in self.data:
self._include = [Spec(s) for s in self.data['include']]
if 'exclude' in self.data:
self._exclude = [Spec(s) for s in self.data['exclude']]
for spec_list in itertools.product(*self._spec_lists):
# if there is an empty array in spec_lists, we'll get this.
if not spec_list:
yield spec_list
continue
# merge all the constraints in spec_list with each other
spec = spec_list[0].copy()
for s in spec_list[1:]:
spec.constrain(s)
# test each spec for include/exclude
if (self._include and
not any(spec.satisfies(s) for s in self._include)):
continue
if any(spec.satisfies(s) for s in self._exclude):
continue
# we now know we can include this spec in the set
yield spec

View file

@ -3,37 +3,27 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import json
from jsonschema import validate
import os
import pytest
import spack
import spack.environment as ev
from spack import repo
from spack.architecture import sys_type
from spack.cmd.release_jobs import stage_spec_jobs, spec_deps_key_label
from spack.main import SpackCommand
from spack.schema.specs_deps import schema as specs_deps_schema
from spack.spec import Spec
from spack.test.conftest import MockPackage, MockPackageMultiRepo
env = SpackCommand('env')
release_jobs = SpackCommand('release-jobs')
def test_specs_deps(tmpdir, config):
"""If we ask for the specs dependencies to be written to disk, then make
sure we get a file of the correct format."""
output_path = str(tmpdir.mkdir('json').join('spec_deps.json'))
release_jobs('--specs-deps-output', output_path, 'readline')
deps_object = None
with open(output_path, 'r') as fd:
deps_object = json.loads(fd.read())
assert (deps_object is not None)
validate(deps_object, specs_deps_schema)
@pytest.fixture()
def env_deactivate():
yield
spack.environment._active_environment = None
os.environ.pop('SPACK_ENV', None)
def test_specs_staging(config):
@ -52,25 +42,6 @@ def test_specs_staging(config):
and then 'd', 'b', and 'a' to be put in the next three stages, respectively.
"""
current_system = sys_type()
config_compilers = config.get_config('compilers')
first_compiler = config_compilers[0]
compiler_spec = first_compiler['compiler']['spec']
# Whatever that first compiler in the configuration was, let's make sure
# we mock up an entry like we'd find in os-container-mapping.yaml which
# has that compiler.
mock_containers = {}
mock_containers[current_system] = {
"image": "dontcare",
"compilers": [
{
"name": compiler_spec,
}
],
}
default = ('build', 'link')
g = MockPackage('g', [], [])
@ -84,9 +55,7 @@ def test_specs_staging(config):
mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g])
with repo.swap(mock_repo):
# Now we'll ask for the root package to be compiled with whatever that
# first compiler in the configuration was.
spec_a = Spec('a%{0}'.format(compiler_spec))
spec_a = Spec('a')
spec_a.concretize()
spec_a_label = spec_deps_key_label(spec_a)[1]
@ -97,8 +66,7 @@ def test_specs_staging(config):
spec_f_label = spec_deps_key_label(spec_a['f'])[1]
spec_g_label = spec_deps_key_label(spec_a['g'])[1]
spec_labels, dependencies, stages = stage_spec_jobs(
[spec_a], mock_containers, current_system)
spec_labels, dependencies, stages = stage_spec_jobs([spec_a])
assert (len(stages) == 4)
@ -116,3 +84,45 @@ def test_specs_staging(config):
assert (len(stages[3]) == 1)
assert (spec_a_label in stages[3])
def test_release_jobs_with_env(tmpdir, mutable_mock_env_path, env_deactivate,
install_mockery, mock_packages):
"""Make sure we can get a .gitlab-ci.yml from an environment file
which has the gitlab-ci, cdash, and mirrors sections."""
filename = str(tmpdir.join('spack.yaml'))
with open(filename, 'w') as f:
f.write("""\
spack:
definitions:
- packages: [archive-files]
specs:
- $packages
mirrors:
some-mirror: https://my.fake.mirror
gitlab-ci:
mappings:
- some-runner-mapping:
match:
- archive-files
runner-attributes:
tags:
- donotcare
image: donotcare
cdash:
build-group: Not important
url: https://my.fake.cdash
project: Not used
site: Nothing
""")
with tmpdir.as_cwd():
env('create', 'test', './spack.yaml')
outputfile = str(tmpdir.join('.gitlab-ci.yml'))
with ev.read('test'):
release_jobs('--output-file', outputfile)
with open(outputfile) as f:
contents = f.read()
assert('archive-files' in contents)
assert('stages: [stage-0' in contents)

View file

@ -1,299 +0,0 @@
# Copyright 2013-2018 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 pytest
from spack.spec import Spec
from jsonschema import ValidationError
from spack.spec_set import CombinatorialSpecSet
pytestmark = pytest.mark.usefixtures('config')
basic_yaml_file = {
'spec-set': {
'cdash': 'http://example.com/cdash',
'project': 'testproj',
'include': ['gmake'],
'matrix': [
{'packages': {
'gmake': {
'versions': ['4.0']
}
}},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
def test_spec_set_basic():
"""The "include" isn't required, but if it is present, we should only
see specs mentioned there. Also, if we include cdash and project
properties, those should be captured and stored on the resulting
CombinatorialSpecSet as attributes."""
spec_set = CombinatorialSpecSet(basic_yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 4
assert spec_set.cdash == ['http://example.com/cdash']
assert spec_set.project == 'testproj'
def test_spec_set_no_include():
"""Make sure that without any exclude or include, we get the full cross-
product of specs/versions."""
yaml_file = {
'spec-set': {
'matrix': [
{'packages': {
'gmake': {
'versions': ['4.0']
}
}},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 4
def test_spec_set_include_exclude_conflict():
"""Exclude should override include"""
yaml_file = {
'spec-set': {
'include': ['gmake'],
'exclude': ['gmake'],
'matrix': [
{'packages': {
'gmake': {
'versions': ['4.0']
}
}},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 0
def test_spec_set_exclude():
"""The exclude property isn't required, but if it appears, any specs
mentioned there should not appear in the output specs"""
yaml_file = {
'spec-set': {
'exclude': ['gmake'],
'matrix': [
{'packages': {
'gmake': {
'versions': ['4.0']
},
'appres': {
'versions': ['1.0.4']
},
'allinea-reports': {
'versions': ['6.0.4']
}
}},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 8
def test_spec_set_include_limited_packages():
"""If we see the include key, it is a filter and only the specs mentioned
there should actually be included."""
yaml_file = {
'spec-set': {
'include': ['gmake'],
'matrix': [
{'packages': {
'gmake': {
'versions': ['4.0']
},
'appres': {
'versions': ['1.0.4']
},
'allinea-reports': {
'versions': ['6.0.4']
}
}},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 4
def test_spec_set_simple_spec_list():
"""Make sure we can handle the slightly more concise syntax where we
include the package name/version together and skip the extra keys in
the dictionary."""
yaml_file = {
'spec-set': {
'matrix': [
{'specs': [
'gmake@4.0',
'appres@1.0.4',
'allinea-reports@6.0.4'
]},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 3
def test_spec_set_with_specs():
"""Make sure we only see the specs mentioned in the include"""
yaml_file = {
'spec-set': {
'include': ['gmake', 'appres'],
'matrix': [
{'specs': [
'gmake@4.0',
'appres@1.0.4',
'allinea-reports@6.0.4'
]},
{'compilers': {
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file, False)
specs = list(spec for spec in spec_set)
assert len(specs) == 8
def test_spec_set_packages_no_matrix():
"""The matrix property is required, make sure we error out if it is
missing"""
yaml_file = {
'spec-set': {
'include': ['gmake'],
'packages': {
'gmake': {
'versions': ['4.0']
},
'appres': {
'versions': ['1.0.4']
},
'allinea-reports': {
'versions': ['6.0.4']
}
},
}
}
with pytest.raises(ValidationError):
CombinatorialSpecSet(yaml_file)
def test_spec_set_get_cdash_array():
"""Make sure we can handle multiple cdash sites in a list"""
yaml_file = {
'spec-set': {
'cdash': ['http://example.com/cdash', 'http://example.com/cdash2'],
'project': 'testproj',
'matrix': [
{'packages': {
'gmake': {'versions': ['4.0']},
}},
{'compilers': {
'gcc': {'versions': ['4.2.1', '6.3.0']},
'clang': {'versions': ['8.0', '3.8']},
}},
]
}
}
spec_set = CombinatorialSpecSet(yaml_file)
assert spec_set.cdash == [
'http://example.com/cdash', 'http://example.com/cdash2']
assert spec_set.project == 'testproj'
def test_compiler_specs():
spec_set = CombinatorialSpecSet(basic_yaml_file, False)
compilers = spec_set._compiler_specs({
'gcc': {
'versions': ['4.2.1', '6.3.0']
}, 'clang': {
'versions': ['8.0', '3.8']
}})
assert len(list(compilers)) == 4
assert Spec('%gcc@4.2.1') in compilers
assert Spec('%gcc@6.3.0') in compilers
assert Spec('%clang@8.0') in compilers
assert Spec('%clang@3.8') in compilers
def test_package_specs():
spec_set = CombinatorialSpecSet(basic_yaml_file, False)
packages = spec_set._package_specs({
'gmake': {
'versions': ['4.0', '5.0']
},
'appres': {
'versions': ['1.0.4']
},
'allinea-reports': {
'versions': ['6.0.1', '6.0.3', '6.0.4']
}
})
assert Spec('gmake@4.0') in packages
assert Spec('gmake@5.0') in packages
assert Spec('appres@1.0.4') in packages
assert Spec('allinea-reports@6.0.1') in packages
assert Spec('allinea-reports@6.0.3') in packages
assert Spec('allinea-reports@6.0.4') in packages