def test_write(self): p = Popen(["dd", "of=/dev/null", "bs=%d" % self.BUFSIZE], stdin=subprocess.PIPE, stdout=None, stderr=subprocess.PIPE) start = monotonic_time() total = self.COUNT * self.BUFSIZE sent = 0 with io.open("/dev/zero", "rb") as f: while sent < total: n = min(total - sent, self.BUFSIZE) data = f.read(n) if not data: raise RuntimeError("/dev/zero closed?!") p.stdin.write(data) sent += len(data) p.stdin.flush() p.stdin.close() for _, data in cmdutils.receive(p, 10): pass elapsed = monotonic_time() - start sent_gb = sent / float(1024**3) print("%.2fg in %.2f seconds (%.2fg/s)" % (sent_gb, elapsed, sent_gb / elapsed), end=" ") self.assertEqual(p.returncode, 0)
def test_kill(self): p = subprocess.Popen(["sleep", "1"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.kill() list(cmdutils.receive(p)) self.assertEqual(p.returncode, -signal.SIGKILL)
def test_stderr(self): p = subprocess.Popen(["sh", "-c", "echo error >/dev/stderr"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) received = list(cmdutils.receive(p)) self.assertEqual(received, [(cmdutils.ERR, b"error\n")]) self.assertEqual(p.returncode, 0)
def test_stdout(self): p = subprocess.Popen(["echo", "output"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) received = list(cmdutils.receive(p)) self.assertEqual(received, [(cmdutils.OUT, b"output\n")]) self.assertEqual(p.returncode, 0)
def test_no_output_error(self): p = subprocess.Popen(["false"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) received = list(cmdutils.receive(p)) self.assertEqual(received, []) self.assertEqual(p.returncode, 1)
def test_both_stdout_stderr(self): p = subprocess.Popen( ["sh", "-c", "echo output; echo error >/dev/stderr;"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) received = list(cmdutils.receive(p)) self.assertEqual(sorted(received), sorted([ (cmdutils.OUT, b"output\n"), (cmdutils.ERR, b"error\n") ])) self.assertEqual(p.returncode, 0)
def test_fds_closed(self): cmd = ["python", "-c", "import os, time; os.close(1); os.close(2); time.sleep(1)"] p = subprocess.Popen(cmd, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: with self.assertRaises(cmdutils.TimeoutExpired): for _ in cmdutils.receive(p, 0.5): pass finally: p.kill() p.wait()
def test_no_fds(self): p = subprocess.Popen(["sleep", "1"], stdin=None, stdout=None, stderr=None) try: with self.assertRaises(cmdutils.TimeoutExpired): for _ in cmdutils.receive(p, 0.5): pass finally: p.kill() p.wait()
def test_timeout_with_data(self): p = subprocess.Popen(["yes"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: with self.assertRaises(cmdutils.TimeoutExpired): for _ in cmdutils.receive(p, 0.5): pass finally: p.kill() p.wait()
def test_read(self): p = Popen(["dd", "if=/dev/zero", "bs=%d" % self.BUFSIZE, "count=%d" % self.COUNT], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) start = monotonic_time() received = 0 for src, data in cmdutils.receive(p, bufsize=self.BUFSIZE): if src == cmdutils.OUT: received += len(data) elapsed = monotonic_time() - start received_gb = received / float(1024**3) print("%.2fg in %.2f seconds (%.2fg/s)" % (received_gb, elapsed, received_gb / elapsed), end=" ") self.assertEqual(received, self.COUNT * self.BUFSIZE) self.assertEqual(p.returncode, 0)
def test_terminate(self, signo): # Start bash process printing its pid and sleeping. p = subprocess.Popen( ['./py-watch', '10', 'bash', '-c', 'echo $$; sleep 10'], stdout=subprocess.PIPE) # Wait until the underlying bash process prints its pid. for src, data in cmdutils.receive(p): if src == cmdutils.OUT: child_pid = int(data) break # Terminate py-watch, and check its exit code. p.send_signal(signo) assert p.wait() == 128 + signo # Check that the child process was terminated. with pytest.raises(OSError) as e: assert os.kill(child_pid, 0) assert e.value.errno == errno.ESRCH
def watch(self): """ Run a command, iterating on data received from underlying command stdout. Data read from stderr is collected and will be included in the cmdutils.Error raised if the underlying command failed. Raises: `RuntimeError` if invoked more then once `exception.ActionStopped` if the command was aborted `cmdutils.Error` if the command failed """ self._start_process() err = bytearray() for src, data in cmdutils.receive(self._proc): if src == cmdutils.OUT: yield data else: err += data self._finalize(b"", err)
def test_terminate(self, signo): # Start bash process printing its pid and sleeping. The short sleep # before printing the pid avoids a race when we got the pid before # py-watch started to wait for the child. p = subprocess.Popen([ sys.executable, 'py-watch', '10', 'bash', '-c', 'sleep 0.5; echo $$; sleep 10' ], stdout=subprocess.PIPE) # Wait until the underlying bash process prints its pid. for src, data in cmdutils.receive(p): if src == cmdutils.OUT: child_pid = int(data) break # Terminate py-watch, and check its exit code. p.send_signal(signo) assert p.wait() == 128 + signo # Check that the child process was terminated. with pytest.raises(OSError) as e: assert os.kill(child_pid, 0) assert e.value.errno == errno.ESRCH