From 00b9b20c4c3fb794eaad303b96e6b6dc277f75e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 11 Jan 2023 16:41:53 +0000 Subject: [PATCH] Migrate openscap unit tests to pytest --- tests/pytests/unit/modules/test_openscap.py | 421 ++++++++++++++++++ tests/unit/modules/test_openscap.py | 447 -------------------- 2 files changed, 421 insertions(+), 447 deletions(-) create mode 100644 tests/pytests/unit/modules/test_openscap.py delete mode 100644 tests/unit/modules/test_openscap.py diff --git a/tests/pytests/unit/modules/test_openscap.py b/tests/pytests/unit/modules/test_openscap.py new file mode 100644 index 00000000000..35e200bb9bc --- /dev/null +++ b/tests/pytests/unit/modules/test_openscap.py @@ -0,0 +1,421 @@ +import subprocess + +import pytest + +import salt.modules.openscap as openscap +from tests.support.mock import MagicMock, Mock, patch + +random_temp_dir = "/tmp/unique-name" +policy_file = "/usr/share/openscap/policy-file-xccdf.xml" + + +class OpenscapTestMock: + def __init__(self): + import salt.modules.openscap + + salt.modules.openscap.__salt__ = MagicMock() + self.patchers = [ + patch("salt.modules.openscap.__salt__", MagicMock()), + patch("salt.modules.openscap.shutil.rmtree", Mock()), + patch( + "salt.modules.openscap.tempfile.mkdtemp", + Mock(return_value=random_temp_dir), + ), + patch("salt.modules.openscap.os.path.exists", Mock(return_value=True)), + ] + for patcher in self.patchers: + self.apply_patch(patcher) + + def apply_patch(self, patcher): + patcher.start() + + def close(self): + for patcher in self.patchers: + patcher.stop() + + +@pytest.fixture +def openscap_mocks(): + mocks = OpenscapTestMock() + yield mocks + mocks.close() + + +@pytest.fixture +def configure_loader_modules(openscap_mocks): + return {openscap: {"__salt__": {"cp.push_dir": MagicMock()}}} + + +def test_openscap_xccdf_eval_success(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock(**{"returncode": 0, "communicate.return_value": ("", "")}) + ), + ): + response = openscap.xccdf("eval --profile Default {}".format(policy_file)) + + assert openscap.tempfile.mkdtemp.call_count == 1 + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + policy_file, + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + openscap.__salt__["cp.push_dir"].assert_called_once_with(random_temp_dir) + assert openscap.shutil.rmtree.call_count == 1 + assert response == { + "upload_dir": random_temp_dir, + "error": "", + "success": True, + "returncode": 0, + } + + +def test_openscap_xccdf_eval_success_with_failing_rules(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{"returncode": 2, "communicate.return_value": ("", "some error")} + ) + ), + ): + response = openscap.xccdf("eval --profile Default {}".format(policy_file)) + + assert openscap.tempfile.mkdtemp.call_count == 1 + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + policy_file, + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + openscap.__salt__["cp.push_dir"].assert_called_once_with(random_temp_dir) + assert openscap.shutil.rmtree.call_count == 1 + assert response == { + "upload_dir": random_temp_dir, + "error": "some error", + "success": True, + "returncode": 2, + } + + +def test_openscap_xccdf_eval_fail_no_profile(): + response = openscap.xccdf("eval --param Default /unknown/param") + error = "the following arguments are required: --profile" + assert response == { + "error": error, + "upload_dir": None, + "success": False, + "returncode": None, + } + + +def test_openscap_xccdf_eval_success_ignore_unknown_params(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{"returncode": 2, "communicate.return_value": ("", "some error")} + ) + ), + ): + response = openscap.xccdf("eval --profile Default --param Default /policy/file") + assert response == { + "upload_dir": random_temp_dir, + "error": "some error", + "success": True, + "returncode": 2, + } + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + "/policy/file", + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + + +def test_openscap_xccdf_eval_evaluation_error(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{ + "returncode": 1, + "communicate.return_value": ("", "evaluation error"), + } + ) + ), + ): + response = openscap.xccdf("eval --profile Default {}".format(policy_file)) + + assert response == { + "upload_dir": None, + "error": "evaluation error", + "success": False, + "returncode": 1, + } + + +def test_openscap_xccdf_eval_fail_not_implemented_action(): + response = openscap.xccdf("info {}".format(policy_file)) + mock_err = "argument action: invalid choice: 'info' (choose from 'eval')" + + assert response == { + "upload_dir": None, + "error": mock_err, + "success": False, + "returncode": None, + } + + +def test_new_openscap_xccdf_eval_success(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock(**{"returncode": 0, "communicate.return_value": ("", "")}) + ), + ): + response = openscap.xccdf_eval( + policy_file, + profile="Default", + oval_results=True, + results="results.xml", + report="report.html", + ) + + assert openscap.tempfile.mkdtemp.call_count == 1 + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + policy_file, + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + openscap.__salt__["cp.push_dir"].assert_called_once_with(random_temp_dir) + assert openscap.shutil.rmtree.call_count == 1 + assert response == { + "upload_dir": random_temp_dir, + "error": "", + "success": True, + "returncode": 0, + } + + +def test_new_openscap_xccdf_eval_success_with_extra_ovalfiles(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock(**{"returncode": 0, "communicate.return_value": ("", "")}) + ), + ): + response = openscap.xccdf_eval( + policy_file, + ["/usr/share/xml/another-oval.xml", "/usr/share/xml/oval.xml"], + profile="Default", + oval_results=True, + results="results.xml", + report="report.html", + ) + + assert openscap.tempfile.mkdtemp.call_count == 1 + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + policy_file, + "/usr/share/xml/another-oval.xml", + "/usr/share/xml/oval.xml", + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + openscap.__salt__["cp.push_dir"].assert_called_once_with(random_temp_dir) + assert openscap.shutil.rmtree.call_count == 1 + assert response == { + "upload_dir": random_temp_dir, + "error": "", + "success": True, + "returncode": 0, + } + + +def test_new_openscap_xccdf_eval_success_with_failing_rules(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{"returncode": 2, "communicate.return_value": ("", "some error")} + ) + ), + ): + response = openscap.xccdf_eval( + policy_file, + profile="Default", + oval_results=True, + results="results.xml", + report="report.html", + ) + + assert openscap.tempfile.mkdtemp.call_count == 1 + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + policy_file, + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + openscap.__salt__["cp.push_dir"].assert_called_once_with(random_temp_dir) + assert openscap.shutil.rmtree.call_count == 1 + assert response == { + "upload_dir": random_temp_dir, + "error": "some error", + "success": True, + "returncode": 2, + } + + +def test_new_openscap_xccdf_eval_success_ignore_unknown_params(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{"returncode": 2, "communicate.return_value": ("", "some error")} + ) + ), + ): + response = openscap.xccdf_eval( + "/policy/file", + param="Default", + profile="Default", + oval_results=True, + results="results.xml", + report="report.html", + ) + + assert response == { + "upload_dir": random_temp_dir, + "error": "some error", + "success": True, + "returncode": 2, + } + expected_cmd = [ + "oscap", + "xccdf", + "eval", + "--oval-results", + "--results", + "results.xml", + "--report", + "report.html", + "--profile", + "Default", + "/policy/file", + ] + openscap.Popen.assert_called_once_with( + expected_cmd, + cwd=openscap.tempfile.mkdtemp.return_value, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + + +def test_new_openscap_xccdf_eval_evaluation_error(): + with patch( + "salt.modules.openscap.Popen", + MagicMock( + return_value=Mock( + **{ + "returncode": 1, + "communicate.return_value": ("", "evaluation error"), + } + ) + ), + ): + response = openscap.xccdf_eval( + policy_file, + profile="Default", + oval_results=True, + results="results.xml", + report="report.html", + ) + + assert response == { + "upload_dir": None, + "error": "evaluation error", + "success": False, + "returncode": 1, + } diff --git a/tests/unit/modules/test_openscap.py b/tests/unit/modules/test_openscap.py deleted file mode 100644 index 301c1869ecf..00000000000 --- a/tests/unit/modules/test_openscap.py +++ /dev/null @@ -1,447 +0,0 @@ -import subprocess - -import salt.modules.openscap as openscap -from tests.support.mock import MagicMock, Mock, patch -from tests.support.unit import TestCase - - -class OpenscapTestCase(TestCase): - - random_temp_dir = "/tmp/unique-name" - policy_file = "/usr/share/openscap/policy-file-xccdf.xml" - - def setUp(self): - import salt.modules.openscap - - salt.modules.openscap.__salt__ = MagicMock() - patchers = [ - patch("salt.modules.openscap.__salt__", MagicMock()), - patch("salt.modules.openscap.shutil.rmtree", Mock()), - patch( - "salt.modules.openscap.tempfile.mkdtemp", - Mock(return_value=self.random_temp_dir), - ), - patch("salt.modules.openscap.os.path.exists", Mock(return_value=True)), - ] - for patcher in patchers: - self.apply_patch(patcher) - - def apply_patch(self, patcher): - patcher.start() - self.addCleanup(patcher.stop) - - def test_openscap_xccdf_eval_success(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 0, "communicate.return_value": ("", "")} - ) - ), - ): - response = openscap.xccdf( - "eval --profile Default {}".format(self.policy_file) - ) - - self.assertEqual(openscap.tempfile.mkdtemp.call_count, 1) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - self.policy_file, - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - openscap.__salt__["cp.push_dir"].assert_called_once_with( - self.random_temp_dir - ) - self.assertEqual(openscap.shutil.rmtree.call_count, 1) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "", - "success": True, - "returncode": 0, - }, - ) - - def test_openscap_xccdf_eval_success_with_failing_rules(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 2, "communicate.return_value": ("", "some error")} - ) - ), - ): - response = openscap.xccdf( - "eval --profile Default {}".format(self.policy_file) - ) - - self.assertEqual(openscap.tempfile.mkdtemp.call_count, 1) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - self.policy_file, - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - openscap.__salt__["cp.push_dir"].assert_called_once_with( - self.random_temp_dir - ) - self.assertEqual(openscap.shutil.rmtree.call_count, 1) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "some error", - "success": True, - "returncode": 2, - }, - ) - - def test_openscap_xccdf_eval_fail_no_profile(self): - response = openscap.xccdf("eval --param Default /unknown/param") - error = "the following arguments are required: --profile" - self.assertEqual( - response, - {"error": error, "upload_dir": None, "success": False, "returncode": None}, - ) - - def test_openscap_xccdf_eval_success_ignore_unknown_params(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 2, "communicate.return_value": ("", "some error")} - ) - ), - ): - response = openscap.xccdf( - "eval --profile Default --param Default /policy/file" - ) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "some error", - "success": True, - "returncode": 2, - }, - ) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - "/policy/file", - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - - def test_openscap_xccdf_eval_evaluation_error(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{ - "returncode": 1, - "communicate.return_value": ("", "evaluation error"), - } - ) - ), - ): - response = openscap.xccdf( - "eval --profile Default {}".format(self.policy_file) - ) - - self.assertEqual( - response, - { - "upload_dir": None, - "error": "evaluation error", - "success": False, - "returncode": 1, - }, - ) - - def test_openscap_xccdf_eval_fail_not_implemented_action(self): - response = openscap.xccdf("info {}".format(self.policy_file)) - mock_err = "argument action: invalid choice: 'info' (choose from 'eval')" - - self.assertEqual( - response, - { - "upload_dir": None, - "error": mock_err, - "success": False, - "returncode": None, - }, - ) - - def test_new_openscap_xccdf_eval_success(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 0, "communicate.return_value": ("", "")} - ) - ), - ): - response = openscap.xccdf_eval( - self.policy_file, - profile="Default", - oval_results=True, - results="results.xml", - report="report.html", - ) - - self.assertEqual(openscap.tempfile.mkdtemp.call_count, 1) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - self.policy_file, - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - openscap.__salt__["cp.push_dir"].assert_called_once_with( - self.random_temp_dir - ) - self.assertEqual(openscap.shutil.rmtree.call_count, 1) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "", - "success": True, - "returncode": 0, - }, - ) - - def test_new_openscap_xccdf_eval_success_with_extra_ovalfiles(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 0, "communicate.return_value": ("", "")} - ) - ), - ): - response = openscap.xccdf_eval( - self.policy_file, - ["/usr/share/xml/another-oval.xml", "/usr/share/xml/oval.xml"], - profile="Default", - oval_results=True, - results="results.xml", - report="report.html", - ) - - self.assertEqual(openscap.tempfile.mkdtemp.call_count, 1) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - self.policy_file, - "/usr/share/xml/another-oval.xml", - "/usr/share/xml/oval.xml", - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - openscap.__salt__["cp.push_dir"].assert_called_once_with( - self.random_temp_dir - ) - self.assertEqual(openscap.shutil.rmtree.call_count, 1) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "", - "success": True, - "returncode": 0, - }, - ) - - def test_new_openscap_xccdf_eval_success_with_failing_rules(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 2, "communicate.return_value": ("", "some error")} - ) - ), - ): - response = openscap.xccdf_eval( - self.policy_file, - profile="Default", - oval_results=True, - results="results.xml", - report="report.html", - ) - - self.assertEqual(openscap.tempfile.mkdtemp.call_count, 1) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - self.policy_file, - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - openscap.__salt__["cp.push_dir"].assert_called_once_with( - self.random_temp_dir - ) - self.assertEqual(openscap.shutil.rmtree.call_count, 1) - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "some error", - "success": True, - "returncode": 2, - }, - ) - - def test_new_openscap_xccdf_eval_success_ignore_unknown_params(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{"returncode": 2, "communicate.return_value": ("", "some error")} - ) - ), - ): - response = openscap.xccdf_eval( - "/policy/file", - param="Default", - profile="Default", - oval_results=True, - results="results.xml", - report="report.html", - ) - - self.assertEqual( - response, - { - "upload_dir": self.random_temp_dir, - "error": "some error", - "success": True, - "returncode": 2, - }, - ) - expected_cmd = [ - "oscap", - "xccdf", - "eval", - "--oval-results", - "--results", - "results.xml", - "--report", - "report.html", - "--profile", - "Default", - "/policy/file", - ] - openscap.Popen.assert_called_once_with( - expected_cmd, - cwd=openscap.tempfile.mkdtemp.return_value, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - - def test_new_openscap_xccdf_eval_evaluation_error(self): - with patch( - "salt.modules.openscap.Popen", - MagicMock( - return_value=Mock( - **{ - "returncode": 1, - "communicate.return_value": ("", "evaluation error"), - } - ) - ), - ): - response = openscap.xccdf_eval( - self.policy_file, - profile="Default", - oval_results=True, - results="results.xml", - report="report.html", - ) - - self.assertEqual( - response, - { - "upload_dir": None, - "error": "evaluation error", - "success": False, - "returncode": 1, - }, - )