diff --git a/e2e_tests/__init__.py b/e2e_tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/e2e_tests/e2e_test.md b/e2e_tests/e2e_test.md new file mode 100644 index 000000000..5d98af56c --- /dev/null +++ b/e2e_tests/e2e_test.md @@ -0,0 +1,5 @@ +# End to end tests module + +This module is setup in `pytest.ini` to _not run_. If you want to run the E2E tests, +you will need to run `pytest e2e_tests` rather than `pytest`. + diff --git a/e2e_tests/helpers.py b/e2e_tests/helpers.py new file mode 100644 index 000000000..f3959a322 --- /dev/null +++ b/e2e_tests/helpers.py @@ -0,0 +1,42 @@ +from subprocess import run +from typing import Optional, Tuple + +from darwin.exceptions import DarwinException + + +def run_cli_command(command: str, working_directory: Optional[str] = None) -> Tuple[int, str, str]: + """ + Run a CLI command and return the return code, stdout, and stderr. + + Parameters + ---------- + command : str + The command to run. + working_directory : str, optional + The working directory to run the command in. + + Returns + ------- + Tuple[int, str, str] + The return code, stdout, and stderr. + """ + + # Do ot allow directory traversal + if ".." in command or (working_directory and ".." in working_directory): + raise DarwinException("Cannot pass directory traversal to 'run_cli_command'.") + + if working_directory: + result = run( + command, + cwd=working_directory, + capture_output=True, + shell=True, + ) + else: + result = run( + command, + capture_output=True, + shell=True, + ) + + return result.returncode, result.stdout.decode("utf-8"), result.stderr.decode("utf-8") diff --git a/e2e_tests/test_example.py b/e2e_tests/test_example.py new file mode 100644 index 000000000..fe8bed468 --- /dev/null +++ b/e2e_tests/test_example.py @@ -0,0 +1,9 @@ +import pytest + + +def test_example_test_does_nothing() -> None: + assert True + + +if __name__ == "__main__": + pytest.main() diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..179f2f9ac --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --ignore=e2e_tests \ No newline at end of file diff --git a/tests/e2e_test_internals/__init__.py b/tests/e2e_test_internals/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e_test_internals/test_run_cli_command.py b/tests/e2e_test_internals/test_run_cli_command.py new file mode 100644 index 000000000..f439f962c --- /dev/null +++ b/tests/e2e_test_internals/test_run_cli_command.py @@ -0,0 +1,58 @@ +from collections import namedtuple +from unittest import mock + +import pytest + +from darwin.exceptions import DarwinException +from e2e_tests.helpers import run_cli_command + + +def test_does_not_allow_directory_traversal() -> None: + with pytest.raises(DarwinException) as excinfo: + run_cli_command("darwin --help; ls ..") + + assert excinfo.value == "Cannot pass directory traversal to 'run_cli_command'." + + with pytest.raises(DarwinException) as excinfo: + run_cli_command("darwin --help", working_directory="/usr/bin/../") + assert excinfo.value == "Cannot pass directory traversal to 'run_cli_command'." + + +@mock.patch("e2e_tests.helpers.run") +def test_passes_working_directory_to_run_cli_command(mock_subprocess_run: mock.Mock) -> None: + mock_subprocess_run.reset_mock() + run_cli_command("darwin --help", "/usr/bin") + + mock_subprocess_run.assert_called_once() + assert mock_subprocess_run.call_args[0][0] == "darwin --help" + assert mock_subprocess_run.call_args[1]["cwd"] == "/usr/bin" + + +@mock.patch("e2e_tests.helpers.run") +def test_passes_back_returncode_stdout_and_stderr(mock_subprocess_run: mock.Mock) -> None: + CompletedProcess = namedtuple("CompletedProcess", ["returncode", "stdout", "stderr"]) + mocked_output = CompletedProcess(returncode=137, stdout=b"stdout", stderr=b"stderr") + + mock_subprocess_run.return_value = mocked_output + + return_code, std_out, std_err = run_cli_command("darwin --help", "/usr/bin") + + mock_subprocess_run.assert_called_once() + + assert return_code == 137 + assert std_out == "stdout" + assert std_err == "stderr" + + +@mock.patch("e2e_tests.helpers.run") +def test_does_not_pass_working_directory_to_run_cli_command(mock_subprocess_run: mock.Mock) -> None: + mock_subprocess_run.reset_mock() + run_cli_command("darwin --help") + + mock_subprocess_run.assert_called_once() + assert mock_subprocess_run.call_args[0][0] == "darwin --help" + assert "cwd" not in mock_subprocess_run.call_args[1] + + +if __name__ == "__main__": + pytest.main()