diff --git a/osbuild/testutil/__init__.py b/osbuild/testutil/__init__.py index 3d9e2bc0..00531972 100644 --- a/osbuild/testutil/__init__.py +++ b/osbuild/testutil/__init__.py @@ -1,10 +1,12 @@ """ Test related utilities """ +import contextlib import os import pathlib import re import shutil +import tempfile def has_executable(executable: str) -> bool: @@ -57,3 +59,21 @@ def assert_jsonschema_error_contains(res, expected_err, expected_num_errs=None): def finder(s): return expected_err in s # pylint: disable=C0321 assert any(finder(err_msg) for err_msg in err_msgs), f"{expected_err} not found in {err_msgs}" + + +@contextlib.contextmanager +def mock_command(cmd_name: str, script: str): + """ + mock_command creates a mocked binary with the given :cmd_name: and :script: + content. This is useful to e.g. mock errors from binaries. + """ + original_path = os.environ["PATH"] + with tempfile.TemporaryDirectory() as tmpdir: + cmd_path = pathlib.Path(tmpdir) / cmd_name + cmd_path.write_text(script, encoding="utf8") + cmd_path.chmod(0o755) + os.environ["PATH"] = f"{tmpdir}:{original_path}" + try: + yield + finally: + os.environ["PATH"] = original_path diff --git a/test/mod/test_testutil_mock_command.py b/test/mod/test_testutil_mock_command.py new file mode 100644 index 00000000..5e332512 --- /dev/null +++ b/test/mod/test_testutil_mock_command.py @@ -0,0 +1,29 @@ +# +# Tests for the 'osbuild.util.testutil.mock_command' module. +# +import os +import subprocess +import textwrap + +from osbuild.testutil import mock_command + + +def test_mock_command_integration(): + output = subprocess.check_output(["echo", "hello"]) + assert output == b"hello\n" + fake_echo = textwrap.dedent("""\ + #!/bin/sh + echo i-am-not-echo + """) + with mock_command("echo", fake_echo): + output = subprocess.check_output(["echo", "hello"]) + assert output == b"i-am-not-echo\n" + output = subprocess.check_output(["echo", "hello"]) + assert output == b"hello\n" + + +def test_mock_command_environ_is_modified_and_restored(): + orig_path = os.environ["PATH"] + with mock_command("something", "#!/bin/sh\ntrue\n"): + assert os.environ["PATH"] != orig_path + assert os.environ["PATH"] == orig_path