From a38ea732bba893821bf6ee3fb4a6d1d684d31e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= Date: Tue, 4 Mar 2025 07:04:54 +0100 Subject: [PATCH 1/5] Allow to ignore duration in tests There are other ways to adjust this value, but sometimes it is just easier to just let test run as long as they need. --- docs/releases.rst | 6 +++ .../execute/ignore-duration/data/.fmf/version | 1 + tests/execute/ignore-duration/data/demo.fmf | 18 +++++++ tests/execute/ignore-duration/main.fmf | 2 + tests/execute/ignore-duration/test.sh | 49 +++++++++++++++++++ tmt/schemas/execute/tmt.yaml | 3 ++ tmt/steps/execute/__init__.py | 7 +++ tmt/steps/execute/internal.py | 16 ++++++ tmt/utils/__init__.py | 18 +++++++ 9 files changed, 120 insertions(+) create mode 100644 tests/execute/ignore-duration/data/.fmf/version create mode 100644 tests/execute/ignore-duration/data/demo.fmf create mode 100644 tests/execute/ignore-duration/main.fmf create mode 100755 tests/execute/ignore-duration/test.sh diff --git a/docs/releases.rst b/docs/releases.rst index 78356dd9d4..3b9ba92773 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -8,6 +8,7 @@ tmt-1.44.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The ``results.yaml`` file is now populated with test results right after the ``discover`` step is finished and the file is continuously updated during test execution to provide the latest @@ -15,6 +16,11 @@ results. This change also adds a new ``pending`` result outcome to the :ref:`/spec/results` specification for tests that were discovered but not yet executed. +Execute tmt option ``--ignore-duration`` makes tmt to execute +the test as long as it needs. This can be enabled via environment +``TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=1`` even when the execute +step is not stated on the commandline. + tmt-1.43.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/execute/ignore-duration/data/.fmf/version b/tests/execute/ignore-duration/data/.fmf/version new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/execute/ignore-duration/data/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/tests/execute/ignore-duration/data/demo.fmf b/tests/execute/ignore-duration/data/demo.fmf new file mode 100644 index 0000000000..1fcda3a80f --- /dev/null +++ b/tests/execute/ignore-duration/data/demo.fmf @@ -0,0 +1,18 @@ +/test: + test: sleep 4 + duration: "1" + +/plan: + discover: + how: fmf + provision: + how: local + execute: + how: tmt + /no-option: + /via-plan-true: + execute+: + ignore-duration: true + /via-plan-false: + execute+: + ignore-duration: false diff --git a/tests/execute/ignore-duration/main.fmf b/tests/execute/ignore-duration/main.fmf new file mode 100644 index 0000000000..5307015166 --- /dev/null +++ b/tests/execute/ignore-duration/main.fmf @@ -0,0 +1,2 @@ +summary: Verify that the ignore-duration is correctly handled +duration: 5m diff --git a/tests/execute/ignore-duration/test.sh b/tests/execute/ignore-duration/test.sh new file mode 100755 index 0000000000..bc7d299c8e --- /dev/null +++ b/tests/execute/ignore-duration/test.sh @@ -0,0 +1,49 @@ +#!/bin/bash +. /usr/share/beakerlib/beakerlib.sh || exit 1 + + +tmt(){ + tmt_DUR $@ +} + +rlJournalStart + rlPhaseStartSetup + rlRun "tmp=\$(mktemp -d)" 0 "Creating tmp directory" + rlRun "export TMT_WORKDIR_ROOT=$tmp" + rlRun "pushd data" + rlPhaseEnd + + rlPhaseStartTest "No envvar used" + rlRun -s "tmt run -vv plan -n /no-option" "2" + rlAssertGrep 'errr /demo/test (timeout)' $rlRun_LOG '-F' + + rlRun "tmt run -vv plan -n /via-plan-true" "0" + + rlRun "tmt run -vv plan -n /via-plan-false" "2" + rlAssertGrep 'errr /demo/test (timeout)' $rlRun_LOG '-F' + rlPhaseEnd + + rlPhaseStartTest "With IGNORE_DURATION=1" + export TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=1 + rlRun "tmt run -vv plan -n /no-option" + rlRun "tmt run -vv plan -n /via-plan-true" + # ENV should win over CLI or file values, but to be consistent with + # reporportal/polarion plugin envar is weaker than plan.fmf + rlRun "tmt run -vv plan -n /via-plan-false" "2" + rlPhaseEnd + + rlPhaseStartTest "With IGNORE_DURATION=0" + export TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=0 + rlRun "tmt run -vv plan -n /no-option" "2" + # ENV should win over CLI or file values, but to be consistent with + # reporportal/polarion plugin envar is weaker than plan.fmf + rlRun "tmt run -vv plan -n /via-plan-true" + rlRun "tmt run -vv plan -n /via-plan-false" "2" + rlPhaseEnd + + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf $tmp" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalEnd diff --git a/tmt/schemas/execute/tmt.yaml b/tmt/schemas/execute/tmt.yaml index f30e54d34c..f14ba0ef9c 100644 --- a/tmt/schemas/execute/tmt.yaml +++ b/tmt/schemas/execute/tmt.yaml @@ -23,6 +23,9 @@ properties: exit-first: type: boolean + ignore-duration: + type: boolean + # name attribute can exist if more methods name: type: string diff --git a/tmt/steps/execute/__init__.py b/tmt/steps/execute/__init__.py index 8c09b25f77..bd337216eb 100644 --- a/tmt/steps/execute/__init__.py +++ b/tmt/steps/execute/__init__.py @@ -261,6 +261,12 @@ class ExecuteStepData(tmt.steps.WhereableStepData, tmt.steps.StepData): option='--duration', help='The maximal time allowed for the test to run.', ) + ignore_duration: bool = field( + default=False, + option=('--ignore-duration'), + is_flag=True, + help='Ignore test duration values and allow tests run forever.', + ) exit_first: bool = field( default=False, option=('-x', '--exit-first'), @@ -709,6 +715,7 @@ def go( logger: tmt.log.Logger, ) -> None: self.go_prolog(logger) + logger.verbose('ignore-duration', self.data.exit_first, 'green', level=2) logger.verbose('exit-first', self.data.exit_first, 'green', level=2) @property diff --git a/tmt/steps/execute/internal.py b/tmt/steps/execute/internal.py index 11d0e7a4d5..0a7bb77d62 100644 --- a/tmt/steps/execute/internal.py +++ b/tmt/steps/execute/internal.py @@ -25,6 +25,7 @@ Path, ShellScript, Stopwatch, + configure_bool_constant, format_duration, format_timestamp, ) @@ -303,6 +304,17 @@ class ExecuteInternalData(tmt.steps.execute.ExecuteStepData): mode is not captured, and ``duration`` has no effect. """, ) + ignore_duration: bool = field( + default=configure_bool_constant(False, 'TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION'), + option=('--ignore-duration'), + is_flag=True, + help=""" + Ignore test duration value and allow test to run forever. + Can be set by ``TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=1`` even + when step is not specified on the commandline. This environment variable + will be replaced by plan.fmf or CLI arguments. + """, + ) no_progress_bar: bool = field( default=False, option='--no-progress-bar', @@ -560,6 +572,10 @@ def _save_process( timeout = None + elif self.data.ignore_duration: + logger.debug("Test duration is not effective due ignore-duration option.") + timeout = None + else: timeout = tmt.utils.duration_to_seconds( test.duration, tmt.base.DEFAULT_TEST_DURATION_L1 diff --git a/tmt/utils/__init__.py b/tmt/utils/__init__.py index 5f989b144e..5769c0bc08 100644 --- a/tmt/utils/__init__.py +++ b/tmt/utils/__init__.py @@ -120,6 +120,24 @@ def configure_constant(default: int, envvar: str) -> int: ) from exc +def configure_bool_constant(default: bool, envvar: str) -> bool: + """ + Deduce the bool value of global constant. + + Value '1' means True, all other values mean False. + + :param default: the default value of the constant. + :param envvar: name of the optional environment variable which would + override the default value. + :returns: value extracted from the environment variable, or the + given default value if the variable did not exist. + """ + value = os.environ.get(envvar) + if value is None: + return default + return value == "1" + + log = fmf.utils.Logging('tmt').logger From d744ea6a52a2c59db8eb1fcd9e284903f75e2f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= Date: Fri, 7 Mar 2025 09:43:11 +0100 Subject: [PATCH 2/5] squash: addressing review --- docs/overview.rst | 5 +++++ docs/releases.rst | 6 +++--- tmt/steps/execute/__init__.py | 15 +++++++++++---- tmt/steps/execute/internal.py | 12 ------------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/overview.rst b/docs/overview.rst index b96de6cc6d..48194c7825 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -629,6 +629,8 @@ TMT_TEST_PIDFILE_ROOT of temporary directory permissions, e.g. ``chmod 1777``, to allow access to users with all privilege levels. +.. _plugin-variables: + Plugin Variables ---------------- @@ -685,6 +687,9 @@ example, an interactive mode would be enabled in this run:: # Here the environment variable will take effect: $ TMT_PLUGIN_DISCOVER_FMF_VERBOSE=2 tmt run -a discover -h fmf ... + Few plugins (:ref:`/plugins/report/reportportal`, :ref:`/plugins/report/polarion`, + :ref:`/plugins/execute/tmt`) allow selected variables to be processed, + even when plugin is not specified on the command line. .. _regular-expressions: diff --git a/docs/releases.rst b/docs/releases.rst index 3b9ba92773..d513cbb457 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -17,9 +17,9 @@ to the :ref:`/spec/results` specification for tests that were discovered but not yet executed. Execute tmt option ``--ignore-duration`` makes tmt to execute -the test as long as it needs. This can be enabled via environment -``TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=1`` even when the execute -step is not stated on the commandline. +the test as long as it needs. Execute plugin doesn't need to be +specified on the commandline for :ref:`plugin-variables` to work +for this option. tmt-1.43.0 diff --git a/tmt/steps/execute/__init__.py b/tmt/steps/execute/__init__.py index bd337216eb..a3a3bf9e9a 100644 --- a/tmt/steps/execute/__init__.py +++ b/tmt/steps/execute/__init__.py @@ -31,6 +31,7 @@ Path, ShellScript, Stopwatch, + configure_bool_constant, format_duration, format_timestamp, ) @@ -262,10 +263,16 @@ class ExecuteStepData(tmt.steps.WhereableStepData, tmt.steps.StepData): help='The maximal time allowed for the test to run.', ) ignore_duration: bool = field( - default=False, - option=('--ignore-duration'), + default=configure_bool_constant(False, 'TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION'), + option='--ignore-duration', is_flag=True, - help='Ignore test duration values and allow tests run forever.', + envvar="TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION", + help=""" + Ignore test duration value and allow test to run forever. + Can be set by envvar even when step is not specified on the + commandline. This environment variable + will be replaced by plan.fmf or CLI arguments. + """, ) exit_first: bool = field( default=False, @@ -715,7 +722,7 @@ def go( logger: tmt.log.Logger, ) -> None: self.go_prolog(logger) - logger.verbose('ignore-duration', self.data.exit_first, 'green', level=2) + logger.verbose('ignore-duration', self.data.ignore_duration, 'green', level=2) logger.verbose('exit-first', self.data.exit_first, 'green', level=2) @property diff --git a/tmt/steps/execute/internal.py b/tmt/steps/execute/internal.py index 0a7bb77d62..6a029dbca9 100644 --- a/tmt/steps/execute/internal.py +++ b/tmt/steps/execute/internal.py @@ -25,7 +25,6 @@ Path, ShellScript, Stopwatch, - configure_bool_constant, format_duration, format_timestamp, ) @@ -304,17 +303,6 @@ class ExecuteInternalData(tmt.steps.execute.ExecuteStepData): mode is not captured, and ``duration`` has no effect. """, ) - ignore_duration: bool = field( - default=configure_bool_constant(False, 'TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION'), - option=('--ignore-duration'), - is_flag=True, - help=""" - Ignore test duration value and allow test to run forever. - Can be set by ``TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION=1`` even - when step is not specified on the commandline. This environment variable - will be replaced by plan.fmf or CLI arguments. - """, - ) no_progress_bar: bool = field( default=False, option='--no-progress-bar', From 73ac5de23821e3a05f568d2b1ee4e0b547b788fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= Date: Fri, 7 Mar 2025 14:01:30 +0100 Subject: [PATCH 3/5] squash: fix man docs --- docs/overview.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/overview.rst b/docs/overview.rst index 48194c7825..40939cb873 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -687,8 +687,8 @@ example, an interactive mode would be enabled in this run:: # Here the environment variable will take effect: $ TMT_PLUGIN_DISCOVER_FMF_VERBOSE=2 tmt run -a discover -h fmf ... - Few plugins (:ref:`/plugins/report/reportportal`, :ref:`/plugins/report/polarion`, - :ref:`/plugins/execute/tmt`) allow selected variables to be processed, + Several plugins (``report -h reportportal``, ``report -h polarion``, + ``execute -h tmt``) allow selected variables to be processed, even when plugin is not specified on the command line. .. _regular-expressions: From 3e26aa1ee402f6dfdfcfbd474e64c247dc89bd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= Date: Fri, 7 Mar 2025 16:35:56 +0100 Subject: [PATCH 4/5] squash: remove alias I used it to run against local pipx install and forgot to remove :/ --- tests/execute/ignore-duration/test.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/execute/ignore-duration/test.sh b/tests/execute/ignore-duration/test.sh index bc7d299c8e..5f99edb104 100755 --- a/tests/execute/ignore-duration/test.sh +++ b/tests/execute/ignore-duration/test.sh @@ -2,10 +2,6 @@ . /usr/share/beakerlib/beakerlib.sh || exit 1 -tmt(){ - tmt_DUR $@ -} - rlJournalStart rlPhaseStartSetup rlRun "tmp=\$(mktemp -d)" 0 "Creating tmp directory" From 8e132e1aa6dc01aab7c307615cf6c0b5b4ae9c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= <1548503+lukaszachy@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:54:54 +0100 Subject: [PATCH 5/5] squash: apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Petr Šplíchal --- tmt/steps/execute/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmt/steps/execute/__init__.py b/tmt/steps/execute/__init__.py index a3a3bf9e9a..207514a8d8 100644 --- a/tmt/steps/execute/__init__.py +++ b/tmt/steps/execute/__init__.py @@ -269,9 +269,9 @@ class ExecuteStepData(tmt.steps.WhereableStepData, tmt.steps.StepData): envvar="TMT_PLUGIN_EXECUTE_TMT_IGNORE_DURATION", help=""" Ignore test duration value and allow test to run forever. - Can be set by envvar even when step is not specified on the - commandline. This environment variable - will be replaced by plan.fmf or CLI arguments. + Can be set by environment variable even when step is not + specified on the commandline. This environment variable + will be replaced by fmf config file or CLI arguments. """, ) exit_first: bool = field(