Skip to content

Commit 138e5e0

Browse files
authored
Merge pull request #169 from eth-cscs/enhancement/assert_reference_restriction
Allow upper thresholds >= 1.0 in 'assert_reference'
2 parents 3a8f945 + 0c06675 commit 138e5e0

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

docs/tutorial.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ The first occurrence will be used as the reference value of the ``perf`` perform
824824
In our example, the ``perf`` key will be resolved in the ``daint:gpu`` scope giving us the reference value.
825825

826826
Reference values in ReFrame are specified as a three-tuple comprising the reference value and lower and upper thresholds.
827-
Thresholds are specified as decimal fractions of the reference value. The lower threshold must lie in the [-1,0] interval, whereas the upper threshold must be lie in the [0,1] interval.
827+
Thresholds are specified as decimal fractions of the reference value. For nonnegative reference values, the lower threshold must lie in the [-1,0], whereas the upper threshold may be any positive real number or zero.
828828
In our example, the reference value for this test on ``daint:gpu`` is 50 Gflop/s ±10%. Setting a threshold value to :class:`None` disables the threshold.
829829

830830
Combining It All Together

reframe/utility/sanity.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -471,26 +471,32 @@ def assert_reference(val, ref, lower_thres=None, upper_thres=None, msg=None):
471471
:arg val: The value to check.
472472
:arg ref: The reference value.
473473
:arg lower_thres: The lower threshold value expressed as a negative decimal
474-
fraction of the reference value. Must be in [-1, 0]. If ``None``, no
475-
lower thresholds is applied.
474+
fraction of the reference value. Must be in [-1, 0] for ref >= 0.0 and
475+
in [-inf, 0] for ref < 0.0.
476+
If ``None``, no lower thresholds is applied.
476477
:arg upper_thres: The upper threshold value expressed as a decimal fraction
477-
of the reference value. Must be in [0, 1]. If ``None``, no upper
478-
thresholds is applied.
478+
of the reference value. Must be in [0, inf] for ref >= 0.0 and
479+
in [0, 1] for ref < 0.0.
480+
If ``None``, no upper thresholds is applied.
479481
:returns: ``True`` on success.
480482
:raises reframe.core.exceptions.SanityError: if assertion fails or if the
481483
lower and upper thresholds do not have appropriate values.
482484
"""
483485
if lower_thres is not None:
486+
lower_thres_limit = -1 if ref >= 0 else None
484487
try:
485-
evaluate(assert_bounded(lower_thres, -1, 0))
488+
evaluate(assert_bounded(lower_thres, lower_thres_limit, 0))
486489
except SanityError:
487-
raise SanityError('invalid low threshold value: %s' % lower_thres)
490+
raise SanityError('invalid low threshold value: %s' %
491+
lower_thres) from None
488492

489493
if upper_thres is not None:
494+
upper_thres_limit = None if ref >= 0 else 1
490495
try:
491-
evaluate(assert_bounded(upper_thres, 0, 1))
496+
evaluate(assert_bounded(upper_thres, 0, upper_thres_limit))
492497
except SanityError:
493-
raise SanityError('invalid high threshold value: %s' % upper_thres)
498+
raise SanityError('invalid high threshold value: %s' %
499+
upper_thres) from None
494500

495501
def calc_bound(thres):
496502
if thres is None:

unittests/test_sanity_functions.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ def test_assert_reference(self):
340340
self.assertTrue(sn.assert_reference(-0.9, -1, upper_thres=0.1))
341341
self.assertTrue(sn.assert_reference(-0.9, -1))
342342

343+
# Check upper threshold values greater than 1
344+
self.assertTrue(sn.assert_reference(20.0, 10.0, None, 3.0))
345+
self.assertTrue(sn.assert_reference(-50.0, -20.0, -2.0, 0.5))
346+
343347
self.assertRaisesRegex(
344348
SanityError,
345349
'0\.5 is beyond reference value 1 \(l=0\.8, u=1\.1\)',
@@ -371,16 +375,21 @@ def test_assert_reference(self):
371375
self.assertRaisesRegex(SanityError,
372376
'invalid high threshold value: -0\.1',
373377
evaluate, sn.assert_reference(0.9, 1, -0.2, -0.1))
374-
self.assertRaisesRegex(SanityError,
375-
'invalid high threshold value: 1\.1',
376-
evaluate, sn.assert_reference(0.9, 1, -0.2, 1.1))
377378
self.assertRaisesRegex(SanityError,
378379
'invalid low threshold value: 0\.2',
379380
evaluate, sn.assert_reference(0.9, 1, 0.2, 0.1))
380381
self.assertRaisesRegex(SanityError,
381382
'invalid low threshold value: 1\.2',
382383
evaluate, sn.assert_reference(0.9, 1, 1.2, 0.1))
383384

385+
# check invalid thresholds greater than 1
386+
self.assertRaisesRegex(SanityError,
387+
'invalid low threshold value: -2\.0',
388+
evaluate, sn.assert_reference(0.9, 1, -2.0, 0.1))
389+
self.assertRaisesRegex(SanityError,
390+
'invalid high threshold value: 1\.5',
391+
evaluate, sn.assert_reference(-1.5, -1, -0.5, 1.5))
392+
384393
def _write_tempfile(self):
385394
ret = None
386395
with NamedTemporaryFile('wt', delete=False) as fp:

0 commit comments

Comments
 (0)