From 30b0655c3960410d8164b9ceb96291daa6cd7fc0 Mon Sep 17 00:00:00 2001 From: Tyson Smith Date: Mon, 21 Nov 2022 12:46:55 -0800 Subject: [PATCH] Use --timeout 0 to disable timeout --- grizzly/args.py | 4 ++-- grizzly/common/test_utils.py | 26 ++++++++++++++++++++++++++ grizzly/common/utils.py | 34 +++++++++++++++++++++++++++++++--- grizzly/main.py | 9 ++------- grizzly/replay/replay.py | 14 +++++++++----- grizzly/test_args.py | 2 +- 6 files changed, 71 insertions(+), 18 deletions(-) diff --git a/grizzly/args.py b/grizzly/args.py index 3d1e7482..ea59e4e1 100644 --- a/grizzly/args.py +++ b/grizzly/args.py @@ -301,8 +301,8 @@ def sanity_check(self, args): if args.time_limit is not None and args.time_limit < 1: self.parser.error("--time-limit must be >= 1") - if args.timeout is not None and args.timeout < 1: - self.parser.error("--timeout must be >= 1") + if args.timeout is not None and args.timeout < 0: + self.parser.error("--timeout must be >= 0") if args.time_limit and args.timeout and args.timeout < args.time_limit: self.parser.error("--timeout must be >= --time-limit") diff --git a/grizzly/common/test_utils.py b/grizzly/common/test_utils.py index afe43a1b..112542e7 100644 --- a/grizzly/common/test_utils.py +++ b/grizzly/common/test_utils.py @@ -10,6 +10,7 @@ DEFAULT_TIME_LIMIT, TIMEOUT_DELAY, configure_logging, + display_time_limits, grz_tmp, time_limits, ) @@ -76,9 +77,34 @@ def test_configure_logging_01(mocker, env, log_level): (None, 10, [0], (10, 10)), # specify time limit and timeout (50, 100, [0], (50, 100)), + # timeout disabled - use default time limit + (None, 0, [None], (DEFAULT_TIME_LIMIT, 0)), + # timeout disabled - with time limit + (15, 0, [None], (15, 0)), ], ) def test_time_limits_01(mocker, time_limit, timeout, test_durations, expected): """test time_limits()""" tests = [mocker.Mock(spec_set=TestCase, duration=d) for d in test_durations] assert time_limits(time_limit, timeout, tests=tests) == expected + + +@mark.parametrize( + "time_limit, timeout, no_harness, msg", + [ + # typical - harness + (1, 2, False, "Using time limit: 1s, timeout: 2s"), + # typical - without harness + (1, 2, True, "Using timeout: 2s, harness: DISABLED"), + # warn time limit and timeout match - harness + (1, 1, False, "To avoid unnecessary relaunches set timeout > time limit"), + # disabled timeout - harness + (1, 0, False, "Using time limit: 1s, timeout: DISABLED"), + # disable timeout - without harness + (1, 0, True, "Using timeout: DISABLED, harness: DISABLED"), + ], +) +def test_display_time_limits_01(caplog, time_limit, timeout, no_harness, msg): + """test display_time_limits()""" + display_time_limits(time_limit, timeout, no_harness) + assert msg in caplog.text diff --git a/grizzly/common/utils.py b/grizzly/common/utils.py index 6e5f18c1..09b187a8 100644 --- a/grizzly/common/utils.py +++ b/grizzly/common/utils.py @@ -11,6 +11,7 @@ __all__ = ( "ConfigError", "configure_logging", + "display_time_limits", "DEFAULT_TIME_LIMIT", "Exit", "grz_tmp", @@ -73,6 +74,32 @@ def configure_logging(log_level): basicConfig(format=log_fmt, datefmt=date_fmt, level=log_level) +def display_time_limits(time_limit, timeout, no_harness): + """Output configuration of time limits and harness. + + Args: + time_limit (int): Time in seconds before harness attempts to close current test. + timeout (int): Time in seconds before iteration is considered a timeout. + no_harness (bool): Indicate whether harness will is disabled. + + Returns: + None + """ + if timeout > 0: + if no_harness: + LOG.info("Using timeout: %ds, harness: DISABLED", timeout) + else: + LOG.info("Using time limit: %ds, timeout: %ds", time_limit, timeout) + if time_limit == timeout: + LOG.info("To avoid unnecessary relaunches set timeout > time limit") + else: + if no_harness: + LOG.info("Using timeout: DISABLED, harness: DISABLED") + else: + LOG.info("Using time limit: %ds, timeout: DISABLED,", time_limit) + LOG.warning("TIMEOUT DISABLED, not recommended for automation") + + def grz_tmp(*subdir): path = Path(GRZ_TMP, *subdir) path.mkdir(parents=True, exist_ok=True) @@ -114,9 +141,10 @@ def time_limits( calc_timeout = timeout is None if calc_timeout: timeout = time_limit + timeout_delay - elif calc_limit and time_limit > timeout: + elif calc_limit and time_limit > timeout > 0: LOG.debug("calculated time limit > given timeout, using timeout") time_limit = timeout - assert timeout > 0 - assert timeout >= time_limit + assert timeout >= 0 + # timeout should always be >= time limit unless timeout is disabled + assert timeout >= time_limit or timeout == 0 return time_limit, timeout diff --git a/grizzly/main.py b/grizzly/main.py index 5b98d69f..88447f95 100644 --- a/grizzly/main.py +++ b/grizzly/main.py @@ -13,7 +13,7 @@ FilesystemReporter, FuzzManagerReporter, ) -from .common.utils import Exit, configure_logging, time_limits +from .common.utils import Exit, configure_logging, display_time_limits, time_limits from .session import Session from .target import Target, TargetLaunchError, TargetLaunchTimeout @@ -52,12 +52,7 @@ def main(args): time_limit, timeout = time_limits( args.time_limit, args.timeout, default_limit=adapter.TIME_LIMIT ) - if args.no_harness: - LOG.info("Using timeout: %ds (no harness)", timeout) - else: - LOG.info("Using time limit: %ds, timeout: %ds", time_limit, timeout) - if time_limit == timeout: - LOG.warning("To avoid unnecessary relaunches set timeout > time limit") + display_time_limits(time_limit, timeout, args.no_harness) if adapter.RELAUNCH > 0: LOG.info("Relaunch (%d) set in Adapter", adapter.RELAUNCH) diff --git a/grizzly/replay/replay.py b/grizzly/replay/replay.py index 04ac2d25..f64d879c 100644 --- a/grizzly/replay/replay.py +++ b/grizzly/replay/replay.py @@ -20,7 +20,14 @@ from ..common.runner import Runner from ..common.status import SimpleStatus from ..common.storage import TestCase, TestCaseLoadFailure -from ..common.utils import ConfigError, Exit, configure_logging, grz_tmp, time_limits +from ..common.utils import ( + ConfigError, + Exit, + configure_logging, + display_time_limits, + grz_tmp, + time_limits, +) from ..target import Result, Target, TargetLaunchError, TargetLaunchTimeout __author__ = "Tyson Smith" @@ -593,10 +600,7 @@ def main(cls, args): time_limit, timeout = time_limits( args.time_limit, args.timeout, tests=testcases ) - if args.no_harness: - LOG.info("Using timeout: %ds (no harness)", timeout) - else: - LOG.info("Using time limit: %ds, timeout: %ds", time_limit, timeout) + display_time_limits(time_limit, timeout, args.no_harness) # calculate repeat and relaunch repeat = max(args.min_crashes, args.repeat) relaunch = min(args.relaunch, repeat) diff --git a/grizzly/test_args.py b/grizzly/test_args.py index 3bd0afe8..b601236a 100644 --- a/grizzly/test_args.py +++ b/grizzly/test_args.py @@ -86,7 +86,7 @@ def test_common_args_02(capsys, mocker, args, msg, idx): # test invalid timeout ( ["--platform", "targ1", "--timeout", "-1"], - "error: --timeout must be >= 1", + "error: --timeout must be >= 0", ["targ1"], ), # test timeout < time-limit