def test_get_environment(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ executor = Executor( WorkRequest({ 'action_instance_id': 1, 'pipeline_instance_id': 2, 'environment': { 'Something': 'More' } }), None) environment = os.environ environment.update({ 'Something': 'More', 'action_instance_id': '1', 'pipeline_instance_id': '2', 'PYTHONUNBUFFERED': 'true' }) test = executor.get_environment() eq_('More', executor.get_environment()['Something']) eq_('1', executor.get_environment()['action_instance_id']) eq_('2', executor.get_environment()['pipeline_instance_id']) eq_('true', executor.get_environment()['PYTHONUNBUFFERED'])
def test_get_results(self): """ rapid-unit: Rapid Client:Can gather test results :return: :rtype: """ executor = Executor(WorkRequest(), None) file_name = '{}/parsers/*.xml'.format( os.path.dirname(os.path.realpath(__file__))) eq_( { 'JUnitXmlReporter.constructor~should default path to an empty string': { 'status': 'FAILED', 'stacktrace': 'Assertion failed', 'time': '0.006' }, 'JUnitXmlReporter.constructor~should default consolidate to true': { 'status': 'SKIPPED', 'time': '0' }, 'JUnitXmlReporter.constructor~should default useDotNotation to true': { 'status': 'SUCCESS', 'time': '0' }, '__summary__': { 'FAILED': 1, 'SKIPPED': 1, 'SUCCESS': 1, Constants.FAILURES_COUNT: False } }, executor._get_results('/', [file_name]))
def test_get_arguments_empty_work_request(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ executor = Executor(WorkRequest({'args': None}), "bogus") eq_([], executor.get_arguments())
def test_get_arguments_from_work_request(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ executor = Executor(WorkRequest({'args': "testing arguments"}), "bogus") eq_(["testing", "arguments"], executor.get_arguments())
def test_get_stats(self): """ rapid-unit: Rapid Client:Remote Execution:Statistics can be recorded per pipeline_instance :return: :rtype: """ executor = Executor(WorkRequest(), None) eq_(['/tmp/testing.txt', '/tmp/*.txt'], executor._get_stats_files("{}/tmp/testing.txt,/tmp/*.txt".format(Constants.STATS)))
def test_get_parameters(self): """ rapid-unit: Rapid Client:Remote Execution:Parameters can be recorded and passed via pipeline_instance :return: :rtype: """ executor = Executor(WorkRequest(), None) eq_(["/tmp/testing.txt", "/tmp/*.txt"], executor._get_parameters_files("{}/tmp/testing.txt,/tmp/*.txt".format(Constants.PARAMETERS)))
def test_get_results_FAILURE(self): """ rapid-unit: Rapid Client:Remote Execution:Return codes greater than 0 will result in failure. :return: :rtype: """ executor = Executor(WorkRequest(), None) eq_("FAILED", executor._get_status(1))
def start_work(self): executor = Executor( WorkRequest(request.get_json()), self.app.rapid_config.master_uri, workspace=self.app.rapid_config.workspace, quarantine=self.app.rapid_config.quarantine_directory, verify_certs=self.app.rapid_config.verify_certs, rapid_config=self.app.rapid_config) executor.verify_work_request() executor.start()
def test_check_for_dynamic_config_file(self, verify_lines): """ rapid-unit: Rapid Client:Can gather test results :return: :rtype: """ executor = Executor(None, None) executor.verify_file_lines(['{}bogus2'.format(Constants.PARAMETERS)], None) verify_lines.assert_called_with( '{}bogus2'.format(Constants.PARAMETERS), None)
def test_get_results_OVERRIDE(self): """ rapid-unit: Rapid Client:Remote Execution:You can override return codes with different statuses. :return: :rtype: """ executor = Executor(WorkRequest(), None) executor.status_overrides = {4: "GIT_ERROR"} eq_("GIT_ERROR", executor._get_status(4))
def test_start(self, threading): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ executor = Executor(Mock(), "bogus") executor.start() threading.Thread.assert_called_with(target=executor._start_child_process)
def test_get_parameters_error(self): """ rapid-unit: Rapid Client:Remote Execution:Parameters can be recorded and passed via pipeline_instance :return: :rtype: """ executor = Executor(WorkRequest(), None) with self.assertRaises(Exception) as cm: executor._get_parameters_files("nothing") self.assertEqual("list index out of range", str(cm.exception))
def test_clean_workspace_valid_dir(self, mock_os, mock_shutil, mock_logger): """ rapid-unit: Rapid Client:Remote Execution:Code will execute in sandboxed workspace :return: :rtype: """ executor = Executor(WorkRequest({'args': "testing arguments"}), "bogus", workspace="boggus", logger=mock_logger) mock_os.sep = '/' executor.clean_workspace() mock_shutil.rmtree.assert_called_with("boggus", ignore_errors=True)
def test_verify_work_request_no_action_instance_id(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ work_request = WorkRequest() executor = Executor(work_request, "http") with self.assertRaises(Exception) as cm: executor.verify_work_request() self.assertEqual("Invalid action_instance_id", str(cm.exception))
def test_verify_work_request_no_executable(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ work_request = WorkRequest() executor = Executor(work_request, "http") work_request.action_instance_id = 1 with self.assertRaises(Exception) as cm: executor.verify_work_request() self.assertEqual("Executable not set, nothing to run.", str(cm.exception))
def test_clean_workspace_invalid_dir(self, mock_os): """ rapid-unit: Rapid Client:Remote Execution:Code will execute in sandboxed workspace :return: :rtype: """ executor = Executor(WorkRequest({'args': "testing arguments"}), "bogus", workspace="boggus") mock_os.path.isdir.return_value = False mock_os.sep = '/' executor.clean_workspace() mock_os.makedirs.assert_called_with("boggus")
def test_verify_work_request_no_pipeline_instance_id(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ work_request = WorkRequest() executor = Executor(work_request, "http") work_request.action_instance_id = 1 work_request.executable = "something" with self.assertRaises(Exception) as cm: executor.verify_work_request() self.assertEqual("No pipline_instance_id set.", str(cm.exception))
def test_clean_workspace_valid_dir_exception(self, mock_os, mock_shutil, mock_logger): """ rapid-unit: Rapid Client:Remote Execution:Code will execute in sandboxed workspace :return: :rtype: """ executor = Executor(WorkRequest({'args': "testing arguments"}), "bogus", workspace="boggus", logger=mock_logger) def throw_exception(*args, **kwargs): raise Exception("Should not see this") mock_os.sep = '/' mock_shutil.rmtree = throw_exception executor.clean_workspace()
def test_get_name_map(self): """ rapid-unit: Rapid Client:Can gather test results :return: :rtype: """ executor = Executor(None, None) results = { 'LegacyDateTest::testGetDateDiffString~testGetDateDiffString with data set #0': "success", 'OfferLettersControllerTest~testSendOfferLetterMissingRequestDataException': "success" } name_map = executor._get_name_map(results) ok_('testGetDateDiffString with data set #0' in name_map) ok_('testSendOfferLetterMissingRequestDataException' in name_map)
def test_get_state(self): """ rapid-unit: Rapid Client:Remote Execution:Can remotely execute code on client :return: :rtype: """ mock = Mock() executor = Executor(mock, "http", logger=Mock()) eq_({'analyze_tests': None, 'results_files': [], 'work_request': mock, 'parameter_files': [], 'master_uri': 'http', 'thread_id': None, 'read_pid': None, 'status_overrides': {}, 'pid': None, 'workspace': os.path.join(tempfile.gettempdir(), 'rapid', 'workspace'), 'failure_threshold': 0, 'stats_files': [], 'quarantine': None, 'verify_certs': True}, executor.__getstate__())
def test_get_command(self): """ rapid-unit: Rapid Client:Remote Execution:Will download remote file when remote: is used. :return: :rtype: """ work_request = WorkRequest({"action_instance_id": 1, "cmd": "/bin/sh", "executable": "{}trial.sh".format(Communication.REMOTE_FILE), "args": "2>&1"}) executor = Executor(work_request, None) communicator = Mock() communicator.get_downloaded_file_name.return_value = "/tmp/rapidci/workspace/trial.sh" eq_(["/bin/sh", "/tmp/rapidci/workspace/trial.sh"], executor.get_command(communicator))
def test_get_read_process_output_with_exception(self): """ rapid-unit: Rapid Client:Logging:Can read the output from external process :return: :rtype: """ mock_logger = Mock() mock_child_process = Mock() def readline(*args, **kwargs): raise Exception("Shouldn't see this.") mock_child_process.stdout.readline = readline executor = Executor(WorkRequest(), "bogus", mock_logger) executor._read_process_output(mock_logger, mock_child_process) mock_logger.info.assert_called_with("__RCI_{}__ - {} - {}".format(None, os.getpid(), "Shouldn't see this."))
def run_action_instance(self, app, action_instance_id): # type: (Flask, int) -> None communicator = ClientCommunicator( self.client_config.master_uri, self.client_config.quarantine_directory, app, self.client_config.verify_certs) self.client_config.is_single_use = True communicator.register(self.client_config) request_json = communicator.get_work_request_by_action_instance_id( action_instance_id) executor = Executor(WorkRequest(request_json), self.client_config.master_uri, workspace=self.client_config.workspace, quarantine=self.client_config.quarantine_directory, verify_certs=self.client_config.verify_certs, rapid_config=self.client_config) executor.verify_work_request() executor.start(False)
def test_get_read_process_output(self): """ rapid-unit: Rapid Client:Logging:Can read the output from external process :return: :rtype: """ mock_logger = Mock() mock_child_process = Mock() results = ["testing", b''] def readline(*args, **kwargs): return results.pop(0) mock_child_process.stdout.readline = readline executor = Executor(WorkRequest(), "bogus", mock_logger) executor._read_process_output(mock_logger, mock_child_process) mock_logger.info.assert_called_with("__RCI_{}__ - {} - {}".format(None, os.getpid(), "Cleaning up thread."))
def test_clean_workspace_invalid_dir_exception(self, mock_os): """ rapid-unit: Rapid Client:Remote Execution:Code will execute in sandboxed workspace :return: :rtype: """ executor = Executor(WorkRequest({'args': "testing arguments"}), "bogus", workspace="boggus") mock_logger = Mock() executor.logger = mock_logger self_exception = Exception("Should not see this") def throw_exception(*args, **kwargs): raise self_exception mock_os.makedirs = throw_exception mock_os.path.isdir.return_value = False mock_os.sep = '/' executor.clean_workspace() mock_logger.exception.assert_called_with(self_exception)
def test_start_non_threaded(self, child_process, threading): # rapid-unit: Rapid Client:Run Action Instance:Can run an action instance from command line. executor = Executor(Mock(), 'bogus') executor.start(False) self.assertEqual(0, threading.Thread.call_count) child_process.assert_called_with()
def test_get_environment_with_unicode_bytes(self): executor = Executor(Mock(environment={b'Testing': u'\u2013 Trial and Error'}), None) self.assertEqual('– Trial and Error', executor.get_environment()['Testing'])
def test_normalize_workspace_for_windows(self, mock_os): mock_os.sep = '\\' executor = Executor(None, None, workspace='D:\\testing/another\\foo/bar') self.assertEqual('D:\\testing\\another\\foo\\bar', executor._normalize_workspace())
def test_normalize_workspace_for_linux(self, mock_os): mock_os.sep = '/' executor = Executor(None, None, workspace='/root\\bar/testing\\foo') self.assertEqual('/root/bar/testing/foo', executor._normalize_workspace())