From 20d87db84f20b4fe0ae77f62c2450a3129c95c98 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 21 May 2026 00:18:03 +0200 Subject: [PATCH] New option `--warn-as-error` for treating warnings as errors Signed-off-by: Vasileios Karakasis --- docs/manpage.rst | 21 +++++++++++++++++++++ reframe/core/exceptions.py | 4 ++++ reframe/core/logging.py | 10 ++++++++-- reframe/frontend/cli.py | 7 ++++++- unittests/test_cli.py | 11 +++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/docs/manpage.rst b/docs/manpage.rst index b6859f6f7..cad711854 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -1254,6 +1254,14 @@ Miscellaneous options This option can also be set using the :envvar:`RFM_VERBOSE` environment variable or the :attr:`~config.general.verbose` general configuration parameter. +.. option:: --warn-as-error + + Treat warnings as errors. + + This option can also be set using the :envvar:`RFM_WARN_AS_ERROR` environment variable. + + .. versionadded:: 4.10 + .. _test_naming_scheme: @@ -2633,6 +2641,19 @@ Whenever an environment variable is associated with a configuration option, its ================================== ================== +.. envvar:: RFM_WARN_AS_ERROR + + Treat warnings as errors. + + .. table:: + :align: left + + ================================== ================== + Associated command line option :option:`--warn-as-error` + Associated configuration parameter N/A + ================================== ================== + + .. _manpage-configuration: Configuration diff --git a/reframe/core/exceptions.py b/reframe/core/exceptions.py index 4a6853ca4..3d1043b6a 100644 --- a/reframe/core/exceptions.py +++ b/reframe/core/exceptions.py @@ -365,6 +365,10 @@ class ReferenceParseError(ReframeError): ''' +class WarningAsError(ReframeError): + '''Raised when a warning is treated as an error.''' + + def user_frame(): '''Return the first user frame as a :py:class:`FrameInfo` object. diff --git a/reframe/core/logging.py b/reframe/core/logging.py index adff012f5..4e5cf97bd 100644 --- a/reframe/core/logging.py +++ b/reframe/core/logging.py @@ -22,7 +22,8 @@ import reframe.utility.color as color import reframe.utility.jsonext as jsonext import reframe.utility.osext as osext -from reframe.core.exceptions import ConfigError, LoggingError, what +from reframe.core.exceptions import (ConfigError, LoggingError, + WarningAsError, what) from reframe.core.warnings import suppress_deprecations from reframe.utility import is_trivially_callable from reframe.utility.profile import TimeProfiler @@ -903,6 +904,7 @@ def __init__(self, logger=None, check=None): ) self.check = check self.colorize = False + self.warn_as_error = False def setLevel(self, level): if self.logger: @@ -999,6 +1001,9 @@ def verbose(self, message, *args, **kwargs): self.log(VERBOSE, message, *args, **kwargs) def warning(self, message, *args, cache=False, **kwargs): + if self.warn_as_error: + raise WarningAsError(message) + if cache: if message in _WARN_ONCE: return @@ -1082,7 +1087,7 @@ def __exit__(self, exc_type, exc_value, traceback): _context_logger = self._orig_logger -def configure_logging(site_config): +def configure_logging(site_config, warn_as_error=False): global _logger, _context_logger, _perf_logger if site_config is None: @@ -1095,6 +1100,7 @@ def configure_logging(site_config): _logger = _create_logger(site_config, 'handlers$', 'handlers') _perf_logger = _create_logger(site_config, 'handlers_perflog') _context_logger = LoggerAdapter(_logger) + _context_logger.warn_as_error = warn_as_error def log_files(): diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 2da918a94..2b605a7cc 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -719,6 +719,11 @@ def main(): '-q', '--quiet', action='count', default=0, help='Decrease verbosity level of output', ) + misc_options.add_argument( + '--warn-as-error', action='store_true', + help='Treat warnings as errors', + envvar='RFM_WARN_AS_ERROR' + ) # Options not associated with command-line arguments argparser.add_argument( @@ -1076,7 +1081,7 @@ def restrict_logging(): options = argparser.parse_args(namespace=options.cmd_options) options.update_config(site_config) - logging.configure_logging(site_config) + logging.configure_logging(site_config, options.warn_as_error) except (OSError, errors.ConfigError) as e: printer.error(f'failed to load configuration: {e}') printer.info(logfiles_message()) diff --git a/unittests/test_cli.py b/unittests/test_cli.py index e0224a243..efee36fbc 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -1372,6 +1372,17 @@ def test_testlib_inherit_fixture_in_different_files(run_reframe): assert 'FAILED' not in stdout +def test_warn_as_error(run_reframe): + returncode, stdout, stderr = run_reframe( + checkpath=['/unknown/path'], + more_options=['--warn-as-error'] + ) + assert 'Traceback' not in stdout + assert 'Traceback' not in stderr + assert returncode == 1 + assert 'warning as error' in stdout + + @pytest.fixture(params=['csv', 'plain', 'pretty']) def table_format(request): return request.param