Refactor test_preexec_errpipe to not create an uncollectable reference cycle.

This commit is contained in:
Gregory P. Smith 2012-11-11 10:00:49 -08:00
commit 859035d2ef
1 changed files with 18 additions and 19 deletions

View File

@ -1189,22 +1189,15 @@ class POSIXProcessTestCase(BaseTestCase):
self.fail("Exception raised by preexec_fn did not make it " self.fail("Exception raised by preexec_fn did not make it "
"to the parent process.") "to the parent process.")
@unittest.skipIf(not os.path.exists("/dev/zero"), "/dev/zero required.") class _TestExecuteChildPopen(subprocess.Popen):
def test_preexec_errpipe_does_not_double_close_pipes(self): """Used to test behavior at the end of _execute_child."""
"""Issue16140: Don't double close pipes on preexec error.""" def __init__(self, testcase, *args, **kwargs):
class SafeConstructorPopen(subprocess.Popen): self._testcase = testcase
def __init__(self):
pass # Do nothing so we can modify the instance for testing.
def RealPopen(self, *args, **kwargs):
subprocess.Popen.__init__(self, *args, **kwargs) subprocess.Popen.__init__(self, *args, **kwargs)
def raise_it():
raise RuntimeError("force the _execute_child() errpipe_data path.")
p = SafeConstructorPopen() def _execute_child(self, *args, **kwargs):
def _test_fds_execute_child_wrapper(*args, **kwargs):
try: try:
subprocess.Popen._execute_child(p, *args, **kwargs) subprocess.Popen._execute_child(self, *args, **kwargs)
finally: finally:
# Open a bunch of file descriptors and verify that # Open a bunch of file descriptors and verify that
# none of them are the same as the ones the Popen # none of them are the same as the ones the Popen
@ -1213,17 +1206,23 @@ class POSIXProcessTestCase(BaseTestCase):
for _ in range(8)] for _ in range(8)]
try: try:
for fd in devzero_fds: for fd in devzero_fds:
self.assertNotIn(fd, ( self._testcase.assertNotIn(
p.stdin.fileno(), p.stdout.fileno(), fd, (self.stdin.fileno(), self.stdout.fileno(),
p.stderr.fileno()), self.stderr.fileno()),
msg="At least one fd was closed early.") msg="At least one fd was closed early.")
finally: finally:
map(os.close, devzero_fds) map(os.close, devzero_fds)
p._execute_child = _test_fds_execute_child_wrapper @unittest.skipIf(not os.path.exists("/dev/zero"), "/dev/zero required.")
def test_preexec_errpipe_does_not_double_close_pipes(self):
"""Issue16140: Don't double close pipes on preexec error."""
def raise_it():
raise RuntimeError("force the _execute_child() errpipe_data path.")
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
p.RealPopen([sys.executable, "-c", "pass"], self._TestExecuteChildPopen(
self, [sys.executable, "-c", "pass"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, preexec_fn=raise_it) stderr=subprocess.PIPE, preexec_fn=raise_it)