def test_timeout_expired__repr__(self): self.assertEqual( repr(psutil.TimeoutExpired(5)), "psutil.TimeoutExpired(seconds=5, msg='timeout after 5 seconds')") self.assertEqual( repr(psutil.TimeoutExpired(5, pid=321, name="name")), "psutil.TimeoutExpired(pid=321, name='name', seconds=5, " "msg='timeout after 5 seconds')")
def test_timeout_expired__repr__(self, func=repr): self.assertEqual(repr(psutil.TimeoutExpired(321)), "psutil.TimeoutExpired timeout after 321 seconds") self.assertEqual( repr(psutil.TimeoutExpired(321, pid=111)), "psutil.TimeoutExpired timeout after 321 seconds (pid=111)") self.assertEqual( repr(psutil.TimeoutExpired(321, pid=111, name='foo')), "psutil.TimeoutExpired timeout after 321 seconds " "(pid=111, name='foo')")
def test_stop(self, mock_is_running): # Postmaster is not running mock_callback = Mock() mock_is_running.return_value = None self.assertTrue(self.p.stop(on_safepoint=mock_callback)) mock_callback.assert_called() # Is running, stopped successfully mock_is_running.return_value = mock_postmaster = MockPostmaster() mock_callback.reset_mock() self.assertTrue(self.p.stop(on_safepoint=mock_callback)) mock_callback.assert_called() mock_postmaster.signal_stop.assert_called() # Timed out waiting for fast shutdown triggers immediate shutdown mock_postmaster.wait.side_effect = [ psutil.TimeoutExpired(30), psutil.TimeoutExpired(30), Mock() ] mock_callback.reset_mock() self.assertTrue( self.p.stop(on_safepoint=mock_callback, stop_timeout=30)) mock_callback.assert_called() mock_postmaster.signal_stop.assert_called() # Immediate shutdown succeeded mock_postmaster.wait.side_effect = [psutil.TimeoutExpired(30), Mock()] self.assertTrue( self.p.stop(on_safepoint=mock_callback, stop_timeout=30)) # Stop signal failed mock_postmaster.signal_stop.return_value = False self.assertFalse(self.p.stop()) # Stop signal failed to find process mock_postmaster.signal_stop.return_value = True mock_callback.reset_mock() self.assertTrue(self.p.stop(on_safepoint=mock_callback)) mock_callback.assert_called() # Fast shutdown is timed out but when immediate postmaster is already gone mock_postmaster.wait.side_effect = [psutil.TimeoutExpired(30), Mock()] mock_postmaster.signal_stop.side_effect = [None, True] self.assertTrue( self.p.stop(on_safepoint=mock_callback, stop_timeout=30))
def wait(self, timeout): print("running", self.running) print("timed out", timeout, self.terminate_time) if not self.running or self.terminate_time < timeout: return raise psutil.TimeoutExpired( "time to terminate {} exceeds timeout {}".format( self.terminate, timeout))
def make_mock_process( pid, # type: int open_files=None, # type: Optional[List] name="", # type: str cmdline="", # type: str create_time=0.0, # type: float as_dict_throw=False, # type: bool signal_throw=False, # type: bool wait_throw=False, # type: bool cmdline_throw=False, # type: bool timeout=False, # type: bool ): # type: (...) -> psutil.Process """ Creates a mock psutil.Process object suitable for these unit tests. If `throw` is True, it sets the side_effect of `as_dict` to throw a NoSuchProcess exception. """ if open_files is None: open_files = [] cmd = str(cmdline).split() if len(cmd) > 1 and name == "": name = cmd[0] mock_process = create_autospec(psutil.Process) mock_process.pid = pid mock_process.create_time.return_value = create_time mock_process.name.return_value = name mock_process.as_dict.__name__ = "as_dict" if as_dict_throw: mock_process.as_dict.side_effect = psutil.NoSuchProcess(pid) # This is hacky, but it works to simulate a TimeoutExpired actually being # raised by as_dict. elif timeout: mock_process.as_dict.side_effect = TimeoutExpired() else: mock_process.as_dict.return_value = { "pid": pid, "open_files": [MockPopenFile(f) for f in open_files], } if signal_throw: mock_process.send_signal.side_effect = psutil.NoSuchProcess(pid) else: mock_process.send_signal.return_value = None if wait_throw: mock_process.wait.side_effect = psutil.TimeoutExpired(5) else: mock_process.wait.return_value = None if cmdline_throw: mock_process.cmdline.side_effect = psutil.NoSuchProcess(pid) else: mock_process.cmdline.return_value = cmd return mock_process
def wait(self, timeout=None): # pylint: disable=unused-argument """Wait for the process completion. Mocks the process waiting for completion before it continues execution. No time is actually spent waiting, however, since the lifetime of the program is completely defined by the initialization params. Args: timeout: int|None. Time to wait before raising an exception, or None to wait indefinitely. """ if not self.alive: return if not self.unresponsive: self._exit() elif timeout is not None: raise psutil.TimeoutExpired(timeout) else: raise RuntimeError('PopenStub has entered an infinite loop')
def make_mock_process( pid, open_files, name='', as_dict_throw=False, signal_throw=False, wait_throw=False, timeout=False, ): # type: (int, List[str], str, bool, bool, bool) -> psutil.Process """ Creates a mock psutil.Process object suitable for these unit tests. If `throw` is True, it sets the side_effect of `as_dict` to throw a NoSuchProcess exception. """ mock_process = create_autospec(psutil.Process) mock_process.pid = pid mock_process.name.return_value = name mock_process.as_dict.__name__ = 'as_dict' if as_dict_throw: mock_process.as_dict.side_effect = psutil.NoSuchProcess(pid) # This is hacky, but it works to simulate a TimeoutExpired actually being # raised by as_dict. elif timeout: mock_process.as_dict.side_effect = TimeoutExpired() else: mock_process.as_dict.return_value = { 'pid': pid, 'open_files': [MockPopenFile(f) for f in open_files], } if signal_throw: mock_process.send_signal.side_effect = psutil.NoSuchProcess(pid) else: mock_process.send_signal.return_value = None if wait_throw: mock_process.wait.side_effect = psutil.TimeoutExpired(5) else: mock_process.wait.return_value = None return mock_process
def wait(self, timeout=None): raise psutil.TimeoutExpired(timeout)
def run_command(cmd, stdout=None, stderr=None, shell=False, timeout=None, cwd=None, env=None, universal_newlines=False): """Runs a command in a subprocess. This function is very similar to subprocess.check_output. The main difference is that it returns the return code and std error output as well as supporting a timeout parameter. Args: cmd: string or list of strings, the command to run. See subprocess.Popen() documentation. stdout: file handle, the file handle to write std out to. If None is given, then subprocess.PIPE is used. See subprocess.Popen() documentation. stderr: file handle, the file handle to write std err to. If None is given, then subprocess.PIPE is used. See subprocess.Popen() documentation. shell: bool, True to run this command through the system shell, False to invoke it directly. See subprocess.Popen() docs. timeout: float, the number of seconds to wait before timing out. If not specified, no timeout takes effect. cwd: string, the path to change the child's current directory to before it is executed. Note that this directory is not considered when searching the executable, so you can't specify the program's path relative to cwd. env: dict, a mapping that defines the environment variables for the new process. Default behavior is inheriting the current process' environment. universal_newlines: bool, True to open file objects in text mode, False in binary mode. Returns: A 3-tuple of the consisting of the return code, the std output, and the std error. Raises: psutil.TimeoutExpired: The command timed out. """ # Only import psutil when actually needed. # psutil may cause import error in certain env. This way the utils module # doesn't crash upon import. import psutil if stdout is None: stdout = subprocess.PIPE if stderr is None: stderr = subprocess.PIPE process = psutil.Popen(cmd, stdout=stdout, stderr=stderr, shell=shell, cwd=cwd, env=env, universal_newlines=universal_newlines) timer = None timer_triggered = threading.Event() if timeout and timeout > 0: # The wait method on process will hang when used with PIPEs with large # outputs, so use a timer thread instead. def timeout_expired(): timer_triggered.set() process.terminate() timer = threading.Timer(timeout, timeout_expired) timer.start() # If the command takes longer than the timeout, then the timer thread # will kill the subprocess, which will make it terminate. (out, err) = process.communicate() if timer is not None: timer.cancel() if timer_triggered.is_set(): raise psutil.TimeoutExpired(timeout, pid=process.pid) return (process.returncode, out, err)
def test_timeout_expired__str__(self): self.assertEqual(str(psutil.TimeoutExpired(5)), "timeout after 5 seconds") self.assertEqual(str(psutil.TimeoutExpired(5, pid=321, name="name")), "timeout after 5 seconds (pid=321, name='name')")
def run_command(cmd, stdout=None, stderr=None, shell=False, timeout=None, env=None): """Runs a command in a subprocess. This function is very similar to subprocess.check_output. The main difference is that it returns the return code and std error output as well as supporting a timeout parameter. Args: cmd: string or list of strings, the command to run. See subprocess.Popen() documentation. stdout: file handle, the file handle to write std out to. If None is given, then subprocess.PIPE is used. See subprocess.Popen() documentation. stdee: file handle, the file handle to write std err to. If None is given, then subprocess.PIPE is used. See subprocess.Popen() documentation. shell: bool, True to run this command through the system shell, False to invoke it directly. See subprocess.Popen() docs. timeout: float, the number of seconds to wait before timing out. If not specified, no timeout takes effect. Returns: A 3-tuple of the consisting of the return code, the std output, and the std error. Raises: psutil.TimeoutExpired: The command timed out. """ # Only import psutil when actually needed. # psutil may cause import error in certain env. This way the utils module # doesn't crash upon import. import psutil if stdout is None: stdout = subprocess.PIPE if stderr is None: stderr = subprocess.PIPE process = psutil.Popen(cmd, stdout=stdout, stderr=stderr, shell=shell, env=env) timer = None timer_triggered = threading.Event() if timeout and timeout > 0: # The wait method on process will hang when used with PIPEs with large # outputs, so use a timer thread instead. def timeout_expired(): timer_triggered.set() process.terminate() timer = threading.Timer(timeout, timeout_expired) timer.start() # If the command takes longer than the timeout, then the timer thread # will kill the subprocess, which will make it terminate. (out, err) = process.communicate() if timer is not None: timer.cancel() if timer_triggered.is_set(): raise psutil.TimeoutExpired(timeout, pid=process.pid) return (process.returncode, out, err)
def wait_for_process(pid, timeout=None): start_time = time.time() while True == is_process_active(pid): if timeout is not None and (time.time() - start_time) >= timeout: raise psutil.TimeoutExpired("Process is still alive") time.sleep(0.1)