From 22c649dcaa8129bc240d49b24f2e363832e70d9a Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Sat, 7 Dec 2024 23:14:00 +0300 Subject: [PATCH 1/4] test_local.py and test_exec_command_failure__expect_error are added test_local.py contains set of test for LocalOperations - test_exec_command_success - test_exec_command_failure - test_exec_command_failure__expect_error Changes in TestRemoteOperations: - test_exec_command_failure exptects an exception - new test test_exec_command_failure__expect_error was added TestRemoteOperations::test_exec_command_failure__expect_error will fail because RemoteOperations::exec_command does not handle the 'expect_error' parameter correctly. --- tests/test_local.py | 46 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_remote.py | 23 ++++++++++++++++++---- 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/test_local.py diff --git a/tests/test_local.py b/tests/test_local.py new file mode 100644 index 00000000..1caba74b --- /dev/null +++ b/tests/test_local.py @@ -0,0 +1,46 @@ +import pytest + +from testgres import ExecUtilException +from testgres import LocalOperations + + +class TestLocalOperations: + + @pytest.fixture(scope="function", autouse=True) + def setup(self): + self.operations = LocalOperations() + + def test_exec_command_success(self): + """ + Test exec_command for successful command execution. + """ + cmd = "python3 --version" + response = self.operations.exec_command(cmd, wait_exit=True, shell=True) + + assert b'Python 3.' in response + + def test_exec_command_failure(self): + """ + Test exec_command for command execution failure. + """ + cmd = "nonexistent_command" + while True: + try: + self.operations.exec_command(cmd, wait_exit=True, shell=True) + except ExecUtilException as e: + error = e.message + break + raise Exception("We wait an exception!") + assert error == "Utility exited with non-zero code. Error `b'/bin/sh: 1: nonexistent_command: not found\\n'`" + + def test_exec_command_failure__expect_error(self): + """ + Test exec_command for command execution failure. + """ + cmd = "nonexistent_command" + + exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True, shell=True, expect_error=True) + + assert error == b'/bin/sh: 1: nonexistent_command: not found\n' + assert exit_status == 127 + assert result == b'' diff --git a/tests/test_remote.py b/tests/test_remote.py index e0e4a555..565163f7 100755 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -30,12 +30,27 @@ def test_exec_command_failure(self): Test exec_command for command execution failure. """ cmd = "nonexistent_command" - try: - exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True) - except ExecUtilException as e: - error = e.message + while True: + try: + self.operations.exec_command(cmd, verbose=True, wait_exit=True) + except ExecUtilException as e: + error = e.message + break + raise Exception("We wait an exception!") assert error == b'Utility exited with non-zero code. Error: bash: line 1: nonexistent_command: command not found\n' + def test_exec_command_failure__expect_error(self): + """ + Test exec_command for command execution failure. + """ + cmd = "nonexistent_command" + + exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True, shell=True, expect_error=True) + + assert error == b'bash: line 1: nonexistent_command: command not found\n' + assert exit_status == 127 + assert result == b'' + def test_is_executable_true(self): """ Test is_executable for an existing executable. From 45cfbf738e1f5d7f46f8ab053f4a6a481abf53e7 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Sat, 7 Dec 2024 23:26:04 +0300 Subject: [PATCH 2/4] RemoteOperations::exec_command must not raise an exception when 'expect_error' is True (#159) This commit fixes an issue #159. --- testgres/operations/remote_ops.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testgres/operations/remote_ops.py b/testgres/operations/remote_ops.py index 20095051..88394eb7 100644 --- a/testgres/operations/remote_ops.py +++ b/testgres/operations/remote_ops.py @@ -83,26 +83,26 @@ def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False, exit_status = process.returncode - if encoding: - result = result.decode(encoding) - error = error.decode(encoding) - - if expect_error: - raise Exception(result, error) + assert type(result) == bytes # noqa: E721 + assert type(error) == bytes # noqa: E721 if not error: - error_found = 0 + error_found = False else: - error = normalize_error(error) error_found = exit_status != 0 or any( - marker in error for marker in ['error', 'Permission denied', 'fatal', 'No such file or directory'] + marker in error for marker in [b'error', b'Permission denied', b'fatal', b'No such file or directory'] ) - if not ignore_errors and error_found: - if isinstance(error, bytes): - message = b"Utility exited with non-zero code. Error: " + error - else: - message = f"Utility exited with non-zero code. Error: {error}" + assert type(error_found) == bool # noqa: E721 + + if encoding: + result = result.decode(encoding) + error = error.decode(encoding) + + if not ignore_errors and error_found and not expect_error: + error = normalize_error(error) + assert type(error) == str # noqa: E721 + message = "Utility exited with non-zero code. Error: " + error raise ExecUtilException(message=message, command=cmd, exit_code=exit_status, out=result) if verbose: From 1c64337682288201f4c163ad4f12afdca82e33cb Mon Sep 17 00:00:00 2001 From: Dmitry Kovalenko Date: Sun, 8 Dec 2024 00:12:41 +0300 Subject: [PATCH 3/4] TestLocalOperations tests skip Windows --- tests/test_local.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test_local.py b/tests/test_local.py index 1caba74b..3493810f 100644 --- a/tests/test_local.py +++ b/tests/test_local.py @@ -1,4 +1,5 @@ import pytest +import platform from testgres import ExecUtilException from testgres import LocalOperations @@ -10,10 +11,16 @@ class TestLocalOperations: def setup(self): self.operations = LocalOperations() + def skip_if_windows(): + if platform.system().lower() == "windows": + pytest.skip("This test does not support Windows.") + def test_exec_command_success(self): """ Test exec_command for successful command execution. """ + __class__.skip_if_windows() + cmd = "python3 --version" response = self.operations.exec_command(cmd, wait_exit=True, shell=True) @@ -23,6 +30,8 @@ def test_exec_command_failure(self): """ Test exec_command for command execution failure. """ + __class__.skip_if_windows() + cmd = "nonexistent_command" while True: try: @@ -37,6 +46,8 @@ def test_exec_command_failure__expect_error(self): """ Test exec_command for command execution failure. """ + __class__.skip_if_windows() + cmd = "nonexistent_command" exit_status, result, error = self.operations.exec_command(cmd, verbose=True, wait_exit=True, shell=True, expect_error=True) From cb87d0a7b1c87a10c85787591c3d9ba4e6687e76 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Sun, 8 Dec 2024 15:26:58 +0300 Subject: [PATCH 4/4] tests.helpers.RunConditions is added RunConditions contains the code to check the execution condition of tests. It is used in TestLocalOperations. --- tests/__init__.py | 0 tests/helpers/__init__.py | 0 tests/helpers/run_conditions.py | 11 +++++++++++ tests/test_local.py | 13 +++++-------- 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/helpers/__init__.py create mode 100644 tests/helpers/run_conditions.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/helpers/run_conditions.py b/tests/helpers/run_conditions.py new file mode 100644 index 00000000..8d57f753 --- /dev/null +++ b/tests/helpers/run_conditions.py @@ -0,0 +1,11 @@ +import pytest +import platform + + +class RunConditions: + # It is not a test kit! + __test__ = False + + def skip_if_windows(): + if platform.system().lower() == "windows": + pytest.skip("This test does not support Windows.") diff --git a/tests/test_local.py b/tests/test_local.py index 3493810f..da26468b 100644 --- a/tests/test_local.py +++ b/tests/test_local.py @@ -1,9 +1,10 @@ import pytest -import platform from testgres import ExecUtilException from testgres import LocalOperations +from .helpers.run_conditions import RunConditions + class TestLocalOperations: @@ -11,15 +12,11 @@ class TestLocalOperations: def setup(self): self.operations = LocalOperations() - def skip_if_windows(): - if platform.system().lower() == "windows": - pytest.skip("This test does not support Windows.") - def test_exec_command_success(self): """ Test exec_command for successful command execution. """ - __class__.skip_if_windows() + RunConditions.skip_if_windows() cmd = "python3 --version" response = self.operations.exec_command(cmd, wait_exit=True, shell=True) @@ -30,7 +27,7 @@ def test_exec_command_failure(self): """ Test exec_command for command execution failure. """ - __class__.skip_if_windows() + RunConditions.skip_if_windows() cmd = "nonexistent_command" while True: @@ -46,7 +43,7 @@ def test_exec_command_failure__expect_error(self): """ Test exec_command for command execution failure. """ - __class__.skip_if_windows() + RunConditions.skip_if_windows() cmd = "nonexistent_command"