diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-08-21 21:51:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-21 21:51:31 (GMT) |
commit | 9a83f651f31b47b3f6c8b210f7807b26e8c373a5 (patch) | |
tree | 3e86a6cfa48d9d8f310c3bbcf0239da1e60da5f1 /Lib/test/test_subprocess.py | |
parent | 4cab2cd0c05fcda5fcb128c9eb230253fff88c21 (diff) | |
download | cpython-9a83f651f31b47b3f6c8b210f7807b26e8c373a5.zip cpython-9a83f651f31b47b3f6c8b210f7807b26e8c373a5.tar.gz cpython-9a83f651f31b47b3f6c8b210f7807b26e8c373a5.tar.bz2 |
Add test_subprocess.test_nonexisting_with_pipes() (#3133)
bpo-30121: Test the Popen failure when Popen was created with pipes.
Create also NONEXISTING_CMD variable in test_subprocess.py.
Diffstat (limited to 'Lib/test/test_subprocess.py')
-rw-r--r-- | Lib/test/test_subprocess.py | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 8cda1e8..c24fd1e 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -49,6 +49,8 @@ if mswindows: else: SETBINARY = '' +NONEXISTING_CMD = ('nonexisting_i_hope',) + class BaseTestCase(unittest.TestCase): def setUp(self): @@ -1145,13 +1147,54 @@ class ProcessTestCase(BaseTestCase): # 1024 times (each call leaked two fds). for i in range(1024): with self.assertRaises(OSError) as c: - subprocess.Popen(['nonexisting_i_hope'], + subprocess.Popen(NONEXISTING_CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # ignore errors that indicate the command was not found if c.exception.errno not in (errno.ENOENT, errno.EACCES): raise c.exception + def test_nonexisting_with_pipes(self): + # bpo-30121: Popen with pipes must close properly pipes on error. + # Previously, os.close() was called with a Windows handle which is not + # a valid file descriptor. + # + # Run the test in a subprocess to control how the CRT reports errors + # and to get stderr content. + try: + import msvcrt + msvcrt.CrtSetReportMode + except (AttributeError, ImportError): + self.skipTest("need msvcrt.CrtSetReportMode") + + code = textwrap.dedent(f""" + import msvcrt + import subprocess + + cmd = {NONEXISTING_CMD!r} + + for report_type in [msvcrt.CRT_WARN, + msvcrt.CRT_ERROR, + msvcrt.CRT_ASSERT]: + msvcrt.CrtSetReportMode(report_type, msvcrt.CRTDBG_MODE_FILE) + msvcrt.CrtSetReportFile(report_type, msvcrt.CRTDBG_FILE_STDERR) + + try: + subprocess.Popen([cmd], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + except OSError: + pass + """) + cmd = [sys.executable, "-c", code] + proc = subprocess.Popen(cmd, + stderr=subprocess.PIPE, + universal_newlines=True) + with proc: + stderr = proc.communicate()[1] + self.assertEqual(stderr, "") + self.assertEqual(proc.returncode, 0) + @unittest.skipIf(threading is None, "threading required") def test_double_close_on_error(self): # Issue #18851 @@ -1164,7 +1207,7 @@ class ProcessTestCase(BaseTestCase): t.start() try: with self.assertRaises(EnvironmentError): - subprocess.Popen(['nonexisting_i_hope'], + subprocess.Popen(NONEXISTING_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -2430,7 +2473,7 @@ class POSIXProcessTestCase(BaseTestCase): # should trigger the wait() of p time.sleep(0.2) with self.assertRaises(OSError) as c: - with subprocess.Popen(['nonexisting_i_hope'], + with subprocess.Popen(NONEXISTING_CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: pass @@ -2876,7 +2919,7 @@ class ContextManagerTests(BaseTestCase): def test_invalid_args(self): with self.assertRaises((FileNotFoundError, PermissionError)) as c: - with subprocess.Popen(['nonexisting_i_hope'], + with subprocess.Popen(NONEXISTING_CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: pass |