Skip to content

Commit c325772

Browse files
committed
tests: Check and/or suppress stderr of subprocesses, reduce shell=True uses
1 parent 216e7c9 commit c325772

File tree

6 files changed

+54
-67
lines changed

6 files changed

+54
-67
lines changed

.ci/ci_lib.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
from __future__ import print_function
33

44
import atexit
5+
import errno
56
import os
67
import shlex
78
import shutil
8-
import subprocess
99
import sys
1010
import tempfile
1111

12+
import subprocess32 as subprocess
13+
1214
try:
1315
import urlparse
1416
except ImportError:
@@ -30,40 +32,30 @@ def print(*args, **kwargs):
3032
file.flush()
3133

3234

33-
#
34-
# check_output() monkeypatch cutpasted from testlib.py
35-
#
36-
37-
def subprocess__check_output(*popenargs, **kwargs):
38-
# Missing from 2.6.
39-
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
40-
output, _ = process.communicate()
41-
retcode = process.poll()
42-
if retcode:
43-
cmd = kwargs.get("args")
44-
if cmd is None:
45-
cmd = popenargs[0]
46-
raise subprocess.CalledProcessError(retcode, cmd)
47-
return output
48-
49-
if not hasattr(subprocess, 'check_output'):
50-
subprocess.check_output = subprocess__check_output
51-
35+
def _have_cmd(args):
36+
try:
37+
subprocess.run(
38+
args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
39+
)
40+
except OSError as exc:
41+
if exc.errno == errno.ENOENT:
42+
return False
43+
raise
44+
except subprocess.CallProcessError:
45+
return False
46+
return True
5247

53-
# ------------------
5448

5549
def have_apt():
56-
proc = subprocess.Popen('apt --help >/dev/null 2>/dev/null', shell=True)
57-
return proc.wait() == 0
50+
return _have_cmd(['apt', '--help'])
51+
5852

5953
def have_brew():
60-
proc = subprocess.Popen('brew help >/dev/null 2>/dev/null', shell=True)
61-
return proc.wait() == 0
54+
return _have_cmd(['brew', 'help'])
6255

6356

6457
def have_docker():
65-
proc = subprocess.Popen('docker info >/dev/null 2>/dev/null', shell=True)
66-
return proc.wait() == 0
58+
return _have_cmd(['docker', 'info'])
6759

6860

6961
def _argv(s, *args):
@@ -315,7 +307,7 @@ def get_interesting_procs(container_name=None):
315307
args = ['docker', 'exec', container_name] + args
316308

317309
out = []
318-
for line in subprocess__check_output(args).decode().splitlines():
310+
for line in subprocess.check_output(args).decode().splitlines():
319311
ppid, pid, comm, rest = line.split(None, 3)
320312
if (
321313
(

tests/fork_test.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import random
3+
import subprocess
34
import sys
45
import unittest
56

@@ -26,15 +27,28 @@
2627

2728

2829
def _find_ssl_linux():
29-
s = testlib.subprocess__check_output(['ldd', _ssl.__file__])
30-
for line in s.decode().splitlines():
30+
proc = subprocess.Popen(
31+
['ldd', _ssl.__file__],
32+
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
33+
)
34+
b_stdout, b_stderr = proc.communicate()
35+
assert proc.returncode == 0
36+
assert b_stderr.decode() == ''
37+
for line in b_stdout.decode().splitlines():
3138
bits = line.split()
3239
if bits[0].startswith('libssl'):
3340
return bits[2]
3441

42+
3543
def _find_ssl_darwin():
36-
s = testlib.subprocess__check_output(['otool', '-l', _ssl.__file__])
37-
for line in s.decode().splitlines():
44+
proc = subprocess.Popen(
45+
['otool', '-l', _ssl.__file__],
46+
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
47+
)
48+
b_stdout, b_stderr = proc.communicate()
49+
assert proc.returncode == 0
50+
assert b_stderr.decode() == ''
51+
for line in b_stdout.decode().splitlines():
3852
bits = line.split()
3953
if bits[0] == 'name' and 'libssl' in bits[1]:
4054
return bits[1]

tests/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ cffi==1.14.3 # Random pin to try and fix pyparser==2.18 not having effect
88
pycparser==2.18 # Last version supporting 2.6.
99
pytest-catchlog==1.2.2
1010
pytest==3.1.2
11+
subprocess32==3.5.4
1112
timeoutcontext==1.2.0
1213
# Fix InsecurePlatformWarning while creating py26 tox environment
1314
# https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

tests/responder_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ def test_self_contained_program(self):
9393
# Ensure a program composed of a single script can be imported
9494
# successfully.
9595
args = [sys.executable, testlib.data_path('self_contained_program.py')]
96-
output = testlib.subprocess__check_output(args).decode()
97-
self.assertEqual(output, "['__main__', 50]\n")
96+
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
97+
b_stdout, _ = proc.communicate()
98+
self.assertEqual(proc.returncode, 0)
99+
self.assertEqual(b_stdout.decode(), "['__main__', 50]\n")
98100

99101

100102
class BrokenModulesTest(testlib.TestCase):

tests/testlib.py

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
import os
44
import random
55
import re
6-
import signal
76
import socket
8-
import subprocess
97
import sys
108
import threading
119
import time
1210
import traceback
1311
import unittest
1412

1513
import psutil
14+
import subprocess32 as subprocess
1615

1716
import mitogen.core
1817
import mitogen.fork
@@ -71,30 +70,6 @@ def data_path(suffix):
7170
return path
7271

7372

74-
def subprocess__check_output(*popenargs, **kwargs):
75-
# Missing from 2.6.
76-
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
77-
output, _ = process.communicate()
78-
retcode = process.poll()
79-
if retcode:
80-
cmd = kwargs.get("args")
81-
if cmd is None:
82-
cmd = popenargs[0]
83-
raise subprocess.CalledProcessError(retcode, cmd)
84-
return output
85-
86-
87-
def Popen__terminate(proc):
88-
os.kill(proc.pid, signal.SIGTERM)
89-
90-
91-
if hasattr(subprocess, 'check_output'):
92-
subprocess__check_output = subprocess.check_output
93-
94-
if hasattr(subprocess.Popen, 'terminate'):
95-
Popen__terminate = subprocess.Popen.terminate
96-
97-
9873
def threading__thread_is_alive(thread):
9974
"""Return whether the thread is alive (Python version compatibility shim).
10075
@@ -457,7 +432,7 @@ def get_docker_host():
457432

458433
class DockerizedSshDaemon(object):
459434
def _get_container_port(self):
460-
s = subprocess__check_output(['docker', 'port', self.container_name])
435+
s = subprocess.check_output(['docker', 'port', self.container_name])
461436
for line in s.decode().splitlines():
462437
m = self.PORT_RE.match(line)
463438
if not m:
@@ -472,7 +447,7 @@ def _get_container_port(self):
472447

473448
def start_container(self):
474449
try:
475-
subprocess__check_output(['docker', '--version'])
450+
subprocess.check_output(['docker', '--version'])
476451
except Exception:
477452
raise unittest.SkipTest('Docker binary is unavailable')
478453

@@ -486,7 +461,7 @@ def start_container(self):
486461
'--name', self.container_name,
487462
self.image,
488463
]
489-
subprocess__check_output(args)
464+
subprocess.check_output(args)
490465
self._get_container_port()
491466

492467
def __init__(self, mitogen_test_distro=os.environ.get('MITOGEN_TEST_DISTRO', 'debian9')):
@@ -518,7 +493,7 @@ def wait_for_sshd(self):
518493
def check_processes(self):
519494
args = ['docker', 'exec', self.container_name, 'ps', '-o', 'comm=']
520495
counts = {}
521-
for comm in subprocess__check_output(args).decode().splitlines():
496+
for comm in subprocess.check_output(args).decode().splitlines():
522497
comm = comm.strip()
523498
counts[comm] = counts.get(comm, 0) + 1
524499

@@ -533,7 +508,7 @@ def check_processes(self):
533508

534509
def close(self):
535510
args = ['docker', 'rm', '-f', self.container_name]
536-
subprocess__check_output(args)
511+
subprocess.check_output(args)
537512

538513

539514
class BrokerMixin(object):

tests/unix_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ def _test_simple_server(cls, path):
130130
def test_simple(self):
131131
path = mitogen.unix.make_socket_path()
132132
proc = subprocess.Popen(
133-
[sys.executable, __file__, 'ClientTest_server', path]
133+
[sys.executable, __file__, 'ClientTest_server', path],
134+
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
134135
)
135136
try:
136137
self._test_simple_client(path)
@@ -139,7 +140,9 @@ def test_simple(self):
139140
mitogen.context_id = 0
140141
mitogen.parent_id = None
141142
mitogen.parent_ids = []
142-
proc.wait()
143+
b_stdout, _ = proc.communicate()
144+
self.assertEqual(proc.returncode, 0)
145+
self.assertEqual(b_stdout.decode(), '')
143146

144147

145148
if __name__ == '__main__':

0 commit comments

Comments
 (0)