Skip to content

Commit ca557ec

Browse files
authored
Merge branch 'develop' into feat/config-option-topology-prefix
2 parents 268f9da + 7d4a7cb commit ca557ec

File tree

8 files changed

+69
-27
lines changed

8 files changed

+69
-27
lines changed

docs/config_reference.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ System Partition Configuration
601601
:required: No
602602
:default: ``[]``
603603

604-
A list of job scheduler `resource specification <#custom-job-scheduler-resources>`__ objects.
604+
A list of job scheduler :ref:`resource specification <scheduler-resources>` objects.
605605

606606

607607
.. py:attribute:: systems.partitions.processor
@@ -754,6 +754,8 @@ ReFrame can launch containerized applications, but you need to configure properl
754754
If specified in conjunction with :attr:`~systems.partitions.container_platforms.env_vars`, it will be ignored.
755755

756756

757+
.. _scheduler-resources:
758+
757759
Custom Job Scheduler Resources
758760
==============================
759761

reframe/core/decorators.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
__all__ = ['simple_test']
1111

12-
1312
import inspect
1413
import sys
1514
import traceback
@@ -171,10 +170,10 @@ def _validate_test(cls):
171170

172171
if (cls.is_abstract()):
173172
getlogger().warning(
174-
f'skipping test {cls.__qualname__!r}: '
175-
f'test has one or more undefined parameters'
173+
f'skipping test {cls.__qualname__!r}: ' +
174+
'the following parameters are undefined: ' +
175+
', '.join(cls.param_space.undefined_params())
176176
)
177-
return False
178177

179178
conditions = [VersionValidator(v) for v in cls._rfm_required_version]
180179
if (cls._rfm_required_version and

reframe/core/fixtures.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,6 @@ def uninst_tests(self):
325325
'''Get the uninstantiated tests of this registry'''
326326
return self._registry.keys()
327327

328-
def _filter_valid_partitions(self, candidate_parts):
329-
return [p for p in candidate_parts if p in self._env_by_part]
330-
331-
def _filter_valid_environs(self, part, candidate_environs):
332-
return [e for e in cadidate_environs if e in self._env_by_part[part]]
333-
334328
def _is_registry(self, other):
335329
if not isinstance(other, FixtureRegistry):
336330
raise TypeError('other is not a FixtureRegistry')
@@ -776,7 +770,8 @@ def __init__(self, cls, *, scope='test', action='fork', variants='all',
776770
# Check that the fixture class is not an abstract test.
777771
if cls.is_abstract():
778772
raise ValueError(
779-
f'class {cls.__qualname__!r} has undefined parameters'
773+
f'fixture {cls.__qualname__!r} has undefined parameters: ' +
774+
', '.join(cls.param_space.undefined_params())
780775
)
781776

782777
# Validate the scope

reframe/core/parameters.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def update(self, other):
198198
self.values = tuple(filt_vals) + self.values
199199
except TypeError:
200200
raise ReframeSyntaxError(
201-
f"'filter_param' must return an iterable"
201+
"'filter_param' must return an iterable"
202202
) from None
203203

204204
def is_abstract(self):
@@ -307,7 +307,7 @@ def inject(self, obj, cls=None, params_index=None):
307307
try:
308308
# Get the parameter values for the specified variant
309309
param_values = self.__param_combinations[params_index]
310-
except IndexError as no_params:
310+
except IndexError:
311311
raise RuntimeError(
312312
f'parameter space index out of range for '
313313
f'{obj.__class__.__qualname__}'
@@ -333,6 +333,11 @@ def defines(self, name):
333333
'''
334334
return name in self.params and not self.params[name].is_abstract()
335335

336+
def undefined_params(self):
337+
'''Return a list of all undefined parameters.'''
338+
return [name for name, param in self.params.items()
339+
if param.is_abstract()]
340+
336341
def __iter__(self):
337342
'''Create a generator object to iterate over the parameter space
338343

reframe/core/pipeline.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,18 @@ def pipeline_hooks(cls):
261261
#: of the :attr:`valid_systems` list, in which case an AND operation on
262262
#: these constraints is implied. For example, the test defining the
263263
#: following will be valid for all systems that have define both ``feat1``
264-
#: and ``feat2`` and set ``foo=1``
264+
#: and ``feat2`` and set ``foo=1``:
265265
#:
266266
#: .. code-block:: python
267267
#:
268-
#: valid_systems = ['+feat1 +feat2 %foo=1']
268+
#: valid_systems = [r'+feat1 +feat2 %foo=1']
269+
#:
270+
#: Any partition/environment extra or
271+
#: :ref:`partition resource <scheduler-resources>` can be specified as a
272+
#: feature constraint without having to explicitly state this in the
273+
#: partition's/environment's feature list. For example, if ``key1`` is part
274+
#: of the partition/environment extras list, then ``+key1`` will select
275+
#: that partition or environment.
269276
#:
270277
#: For key/value pairs comparisons, ReFrame will automatically convert the
271278
#: value in the key/value spec to the type of the value of the

reframe/core/runtime.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,13 @@ def _is_valid_part(part, valid_systems):
311311
props[key] = val
312312

313313
have_plus_feats = all(
314-
ft in part.features or ft in part.resources
314+
(ft in part.features or
315+
ft in part.resources or ft in part.extras)
315316
for ft in plus_feats
316317
)
317318
have_minus_feats = any(
318-
ft in part.features or ft in part.resources
319+
(ft in part.features or
320+
ft in part.resources or ft in part.extras)
319321
for ft in minus_feats
320322
)
321323
try:
@@ -357,8 +359,9 @@ def _is_valid_env(env, valid_prog_environs):
357359
key, val = subspec[1:].split('=')
358360
props[key] = val
359361

360-
have_plus_feats = all(ft in env.features for ft in plus_feats)
361-
have_minus_feats = any(ft in env.features
362+
have_plus_feats = all(ft in env.features or ft in env.extras
363+
for ft in plus_feats)
364+
have_minus_feats = any(ft in env.features or ft in env.extras
362365
for ft in minus_feats)
363366
try:
364367
have_props = True

unittests/test_parameters.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import reframe as rfm
1212
from reframe.core.exceptions import ReframeSyntaxError
13+
import reframe.core.decorators as decorators
1314

1415

1516
class NoParams(rfm.RunOnlyRegressionTest):
@@ -48,10 +49,13 @@ class MyTest(TwoParams):
4849

4950
def test_abstract_param():
5051
class MyTest(Abstract):
51-
pass
52+
# Add another abstract parameter
53+
P2 = parameter()
5254

5355
assert MyTest.param_space['P0'] == ()
5456
assert MyTest.param_space['P1'] == ('b',)
57+
assert MyTest.param_space['P2'] == ()
58+
assert MyTest.param_space.undefined_params() == ['P0', 'P2']
5559

5660

5761
def test_param_override():

unittests/test_pipeline.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ def _assert_supported(valid_systems, valid_prog_environs,
556556

557557
# Check AND in features and extras
558558
_assert_supported(
559-
valid_systems=['+cuda +mpi %gpu_arch=v100'],
559+
valid_systems=[r'+cuda +mpi %gpu_arch=v100'],
560560
valid_prog_environs=['*'],
561561
expected={}
562562
)
@@ -566,9 +566,18 @@ def _assert_supported(valid_systems, valid_prog_environs,
566566
expected={}
567567
)
568568

569-
# Check OR in features ad extras
569+
# Check OR in features and extras
570570
_assert_supported(
571-
valid_systems=['+cuda +mpi', '%gpu_arch=v100'],
571+
valid_systems=['+cuda +mpi', r'%gpu_arch=v100'],
572+
valid_prog_environs=['*'],
573+
expected={
574+
'testsys:gpu': ['PrgEnv-gnu', 'builtin']
575+
}
576+
)
577+
578+
# Check that extra keys can used as features
579+
_assert_supported(
580+
valid_systems=['+cuda +mpi', '+gpu_arch'],
572581
valid_prog_environs=['*'],
573582
expected={
574583
'testsys:gpu': ['PrgEnv-gnu', 'builtin']
@@ -640,23 +649,23 @@ def _assert_supported(valid_systems, valid_prog_environs,
640649
)
641650
_assert_supported(
642651
valid_systems=['*'],
643-
valid_prog_environs=['%bar=x'],
652+
valid_prog_environs=[r'%bar=x'],
644653
expected={
645654
'testsys:gpu': [],
646655
'testsys:login': ['PrgEnv-gnu']
647656
}
648657
)
649658
_assert_supported(
650659
valid_systems=['*'],
651-
valid_prog_environs=['%foo=2'],
660+
valid_prog_environs=[r'%foo=2'],
652661
expected={
653662
'testsys:gpu': ['PrgEnv-gnu'],
654663
'testsys:login': []
655664
}
656665
)
657666
_assert_supported(
658667
valid_systems=['*'],
659-
valid_prog_environs=['%foo=bar'],
668+
valid_prog_environs=[r'%foo=bar'],
660669
expected={
661670
'testsys:gpu': [],
662671
'testsys:login': []
@@ -671,6 +680,24 @@ def _assert_supported(valid_systems, valid_prog_environs,
671680
}
672681
)
673682

683+
# Check that extra keys can used as features
684+
_assert_supported(
685+
valid_systems=['*'],
686+
valid_prog_environs=['+foo +bar'],
687+
expected={
688+
'testsys:gpu': ['PrgEnv-gnu'],
689+
'testsys:login': ['PrgEnv-gnu']
690+
}
691+
)
692+
_assert_supported(
693+
valid_systems=['*'],
694+
valid_prog_environs=['+foo -bar'],
695+
expected={
696+
'testsys:gpu': [],
697+
'testsys:login': []
698+
}
699+
)
700+
674701
# Check valid_systems / valid_prog_environs combinations
675702
_assert_supported(
676703
valid_systems=['testsys:login'],

0 commit comments

Comments
 (0)