def test_run_external_command_process_error_should_fail(): """Check external command execution CalledProcessError handling.""" def run(*args, **kwargs): # TODO need to be checked on Exception without output and stderr params raise CalledProcessError(1, 'command', 'out', 'err') with mock.patch('subprocess.run', side_effect=run): with pytest.raises(ExternalCommandError): utils.run_external_command('')
def test_run_external_command_timeout(tmp_path): """ A process times-out if it runs longer than expected. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_slow) with pytest.raises(ExternalCommandError) as e: run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script)), 2) # no way to access returncode, stdout, and stderr assert 'timed out' in str(e)
def test_run_external_command_error(tmp_path): """ A PowerShell script fails if text is written to error stream. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_error) with pytest.raises(ExternalCommandError) as e: run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script))) # no way to access returncode, stdout, and stderr assert 'WriteErrorException' in str(e)
def test_run_external_command_failure(tmp_path): """ An exception is raised on a non-zero exit. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_failure) with pytest.raises(ExternalCommandError) as e: run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script))) # no way to access returncode, stdout, and stderr assert 'Exit code[4]' in str(e)
def _exec_external_commands(self, *cmd_cl_defs): """Execute a chain of external commands. :param cmd_cl_defs: tuple(str), set of command line definitions """ msg_src = self.__class__.__name__ for cmd_cl_def in cmd_cl_defs: try: cm_utl.run_external_command(cmd_cl_def) LOG.debug(f'{msg_src}: External command: {cmd_cl_def}: OK') except cm_exc.ExternalCommandError as e: raise extm_exc.InstExtrasManagerError( f'{type(e).__name__}: {e}') from e
def _run_external_command(self, svcm_op_name, cl_elements): """Run an external command within the scope of a service manager's operation of a higher level. :param svcm_op_name: str, name of a service manager operation which this external command is a part of :param cl_elements: list[str], a sequence of individual elements of command line, beginning with executable name """ assert isinstance( cl_elements, list), (f'{self.msg_src}: Argument: cl_elements:' f' Got {type(cl_elements).__name__} instead of list') cmd_line = ' '.join(cl_elements) try: ext_cmd_run = cm_utl.run_external_command(cmd_line) LOG.debug(f'{self.msg_src}: {svcm_op_name.capitalize()}:' f' {cmd_line}: OK') except cm_exc.ExternalCommandError as e: LOG.debug(f'{self.msg_src}: {svcm_op_name.capitalize()}:' f' {cmd_line}: {type(e).__name__}: {e}') raise svcm_exc.ServiceManagerCommandError( f'{svcm_op_name.capitalize()}: {e}') from e return ext_cmd_run
def test_run_external_command_verbose(tmp_path): """ Processes can generate large output. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_verbose) p = run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script))) assert p.returncode == 0 assert len(p.stdout.strip()) == 99999
def test_run_external_command_slow(tmp_path): """ All output is returned, even if slow. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_slow) p = run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script))) assert p.returncode == 0 assert p.stdout.strip() == 'line 1\nline 2' assert p.stderr.strip() == ''
def test_run_external_command_success(tmp_path): """ Output can be captured from a successful process. """ script = tmp_path / 'script.ps1' script.write_text(_cmd_success) p = run_external_command(('powershell', '-executionpolicy', 'Bypass', '-File', str(script))) assert p.returncode == 0 assert p.stdout.strip() == 'output' assert p.stderr.strip() == ''
def test_successful_run_external_command_should_provide_output( mock_subprocess): """Check do we have external command execution output in function result and subprocess params.""" assert utils.run_external_command('some command') == 'output' mock_subprocess.assert_called_once_with('some command', check=True, stderr=-1, stdout=-1, timeout=30, universal_newlines=True)
def _exec_external_commands(self, *cmd_cl_defs): """Execute a chain of external commands. :param cmd_cl_defs: tuple(str), set of command line definitions """ for cmd_id, cmd_cl_def in enumerate(cmd_cl_defs, start=1): try: cmd_run_result = cm_utl.run_external_command(cmd_cl_def, timeout=90) LOG.debug( f'{self.msg_src}: Run external command (cmd_id={cmd_id}):' f' {cmd_cl_def}: OK') self._save_extcmd_output(str(cmd_id), cmd_run_result) except cm_exc.ExternalCommandError as e: LOG.debug( f'{self.msg_src}: Run external command (cmd_id={cmd_id}):' f' {cmd_cl_def}: {type(e).__name__}: {e}') self._save_extcmd_output(str(cmd_id), e) raise extm_exc.InstExtrasManagerError( f'{type(e).__name__}: {e}') from e
def _run_external_command( self, svcm_op_name: str, cl_elements: List) -> subprocess.CompletedProcess: """Run an external command within the scope of a service manager's operation of a higher level. :param svcm_op_name: str, name of a service manager operation which this external command is a part of :param cl_elements: list[str], a sequence of individual elements of command line, beginning with executable name """ cmd_line = ' '.join(cl_elements) try: ext_cmd_run = cm_utl.run_external_command(cmd_line, timeout=90) LOG.debug(f'{self.msg_src}: {svcm_op_name.capitalize()}:' f' {cmd_line}: OK') except cm_exc.ExternalCommandError as e: LOG.debug(f'{self.msg_src}: {svcm_op_name.capitalize()}:' f' {cmd_line}: {type(e).__name__}: {e}') raise svcm_exc.ServiceManagerCommandError( f'{svcm_op_name.capitalize()}: {e}') from e return ext_cmd_run
def test_run_external_command_os_error_should_fail(*args): """Check external command execution OSError handling.""" with pytest.raises(ExternalCommandError): utils.run_external_command('')