Skip to content

Commit

Permalink
exec-test clear testing environment
Browse files Browse the repository at this point in the history
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: avocado-framework#5889
Signed-off-by: Jan Richter <[email protected]>
  • Loading branch information
richtja committed Apr 26, 2024
1 parent e27f4c5 commit 112dd07
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 21 deletions.
14 changes: 14 additions & 0 deletions avocado/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down
18 changes: 15 additions & 3 deletions avocado/plugins/runners/exec_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -119,15 +123,23 @@ 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 not in ["all", "system", None]:
raise ValueError(
f"The `runner.exectest.clear_env` value {clear_env} is not supported."
)
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():
if value is None:
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)
Expand Down
9 changes: 9 additions & 0 deletions docs/source/guides/writer/chapters/basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion selftests/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"nrunner-requirement": 24,
"unit": 669,
"jobs": 11,
"functional-parallel": 304,
"functional-parallel": 306,
"functional-serial": 6,
"optional-plugins": 0,
"optional-plugins-golang": 2,
Expand Down
55 changes: 38 additions & 17 deletions selftests/functional/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def test(self):
fi
"""

EXEC_DEFAULT_ENV_VARIABLE_TEST = """#!/bin/bash
if [[ -n "${AVOCADO_VERSION}" ]]; then
exit 1
fi
"""


def probe_binary(binary):
try:
Expand Down Expand Up @@ -1002,6 +1008,24 @@ def setUp(self):
)
self.fail_script.save()

def _test_env(self, configuration, expected_rc, test_file):
with script.TemporaryScript("exec_env_var.sh", test_file) 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,
"Script unexpectedly passed with environment variable set.",
)

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} "
Expand Down Expand Up @@ -1101,24 +1125,21 @@ 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,
"Script unexpectedly passed with environment variable set",
)
self._test_env("TEST_ENV=json:null", 0, EXEC_ENV_VARIABLE_TEST)

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, EXEC_ENV_VARIABLE_TEST
)

@skipUnlessPathExists("/bin/sh")
def test_env_clear_all(self):
self._test_env(
'-c \'{"runner.exectest.clear_env": "all"}\'',
0,
EXEC_DEFAULT_ENV_VARIABLE_TEST,
)

def tearDown(self):
self.pass_script.remove()
Expand Down

0 comments on commit 112dd07

Please sign in to comment.