From 24f821ffc504858bf33f13f09ea985fc3a5f3ca4 Mon Sep 17 00:00:00 2001 From: Jan Richter Date: Thu, 11 Apr 2024 10:54:39 +0200 Subject: [PATCH] exec-test clear testing environment This commit adds more control over the environment variables in exec-tests for users. It brings a way how to clear the test environment during the test runtime so it won't affect the test script. Only thing which user needs to do is to set the runner.exectest.clear_env to `system` or `all` in tests config. Reference: #5889 Signed-off-by: Jan Richter --- avocado/core/__init__.py | 14 +++++++ avocado/plugins/runners/exec_test.py | 14 +++++-- docs/source/guides/writer/chapters/basics.rst | 9 +++++ selftests/check.py | 2 +- selftests/functional/basic.py | 40 ++++++++++++------- 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/avocado/core/__init__.py b/avocado/core/__init__.py index 3120a35dbe..8a529a79b1 100644 --- a/avocado/core/__init__.py +++ b/avocado/core/__init__.py @@ -178,6 +178,20 @@ def register_core_options(): help_msg=help_msg, ) + help_msg = ( + "If and how to clear test environment. Two possible options, " + "`system` and `all`. " + "`system` = no variables set, besides avocados default and kwargs. " + "`all` = only kwargs are set." + ) + stgs.register_option( + section="runner.exectest", + key="clear_env", + key_type=str, + default=None, + help_msg=help_msg, + ) + help_msg = ( "By default Avocado runners will use the {uri} of a test as " "its identifier. Use a custom f-string identifier in order to " diff --git a/avocado/plugins/runners/exec_test.py b/avocado/plugins/runners/exec_test.py index 0194cf17be..c4aa925d71 100644 --- a/avocado/plugins/runners/exec_test.py +++ b/avocado/plugins/runners/exec_test.py @@ -33,7 +33,11 @@ class ExecTestRunner(BaseRunner): name = "exec-test" description = "Runner for standalone executables treated as tests" - CONFIGURATION_USED = ["run.keep_tmp", "runner.exectest.exitcodes.skip"] + CONFIGURATION_USED = [ + "run.keep_tmp", + "runner.exectest.exitcodes.skip", + "runner.exectest.clear_env", + ] def _process_final_status( self, process, runnable, stdout=None, stderr=None @@ -119,7 +123,11 @@ def _is_uri_a_file_on_cwd(uri): return False def _get_env(self, runnable): - env = dict(os.environ) + clear_env = runnable.config.get("runner.exectest.clear_env", None) + if clear_env in ["all", "system"]: + env = {} + else: + env = dict(os.environ) if runnable.kwargs: env.update(runnable.kwargs) for key, value in runnable.kwargs.items(): @@ -127,7 +135,7 @@ def _get_env(self, runnable): del env[key] # set default Avocado environment variables if running on a valid Task - if runnable.uri is not None: + if runnable.uri is not None and clear_env != "all": avocado_test_env_variables = self._get_env_variables(runnable) # save environment variables for further cleanup runnable.kwargs.update(avocado_test_env_variables) diff --git a/docs/source/guides/writer/chapters/basics.rst b/docs/source/guides/writer/chapters/basics.rst index 765958db2c..ea08705226 100644 --- a/docs/source/guides/writer/chapters/basics.rst +++ b/docs/source/guides/writer/chapters/basics.rst @@ -99,3 +99,12 @@ disable those variables during the test runtime. To disable a test variable, you need to set it in test ``kwargs`` to ``None`` like this:: Runnable("exec-test", "examples/tests/sleeptest.sh", SLEEP_LENGTH=None) + +If you need to clear the whole environment before your test, then you can set +``runner.exectest.clear_env`` config variable. This variable has two options. +``system`` and ``all``. If you use ``system`` option the testing environment +will have only Avocado default variables and variables from test ``kwargs``. +If you use ``all`` option, the testing environment will have only variables +from test ``kwargs``:: + + Runnable("exec-test", "examples/tests/sleeptest.sh", config={'runner.exectest.clear_env': system}, SLEEP_LENGTH=1) diff --git a/selftests/check.py b/selftests/check.py index 3924ff8d9c..90f62ebf21 100755 --- a/selftests/check.py +++ b/selftests/check.py @@ -29,7 +29,7 @@ "nrunner-requirement": 24, "unit": 669, "jobs": 11, - "functional-parallel": 303, + "functional-parallel": 305, "functional-serial": 6, "optional-plugins": 0, "optional-plugins-golang": 2, diff --git a/selftests/functional/basic.py b/selftests/functional/basic.py index 7cb96c890b..f6edda1130 100644 --- a/selftests/functional/basic.py +++ b/selftests/functional/basic.py @@ -99,9 +99,12 @@ def test(self): """ EXEC_ENV_VARIABLE_TEST = """#!/bin/bash -if [[ -n "${TEST_ENV}" ]]; then +if [[ -n "${TEST_ENV}" ]]; then exit 1 fi +if [[ -z "${AVOCADO_VERSION}" ]]; then + exit 2 +fi """ @@ -1002,6 +1005,20 @@ def setUp(self): ) self.fail_script.save() + def _test_env(self, configuration, expected_rc): + with script.TemporaryScript("exec_env_var.sh", EXEC_ENV_VARIABLE_TEST) as tst: + res = process.run( + f"env TEST_ENV=test avocado-runner-exec-test runnable-run -k exec-test -u {tst}", + ) + result = res.stdout_text.split("\n")[-2] + self.assertIn("'returncode': 1", result, "The test might be corrupted.") + + res = process.run( + f"env TEST_ENV=test avocado-runner-exec-test runnable-run -k exec-test -u {tst} {configuration}" + ) + result = res.stdout_text.split("\n")[-2] + self.assertIn(f"'returncode': {expected_rc}", result) + def test_exec_test_pass(self): cmd_line = ( f"{AVOCADO} run --job-results-dir {self.tmpdir.name} " @@ -1101,20 +1118,15 @@ def test_non_absolute_path(self): @skipUnlessPathExists("/bin/bash") def test_env_var_disable(self): - with script.TemporaryScript("exec_env_var.sh", EXEC_ENV_VARIABLE_TEST) as tst: - res = process.run( - f"env TEST_ENV=test avocado-runner-exec-test runnable-run -k exec-test -u {tst}", - ) - result = res.stdout_text.split("\n")[-2] - self.assertIn("'returncode': 1", result, "The test might be corrupted.") + self._test_env("TEST_ENV=json:null", 0) - res = process.run( - f"env TEST_ENV=test avocado-runner-exec-test runnable-run -k exec-test -u {tst} TEST_ENV=json:null", - ) - result = res.stdout_text.split("\n")[-2] - self.assertIn( - "'returncode': 0", result, "The env variable was not disabled." - ) + @skipUnlessPathExists("/bin/sh") + def test_env_clear_system(self): + self._test_env('-c \'{"runner.exectest.clear_env": "system"}\'', 0) + + @skipUnlessPathExists("/bin/sh") + def test_env_clear_all(self): + self._test_env('-c \'{"runner.exectest.clear_env": "all"}\'', 2) def tearDown(self): self.pass_script.remove()