bpo-31178: Avoid concatenating bytes with str in subprocess error (#3… · python/cpython@3fc499b
@@ -1542,6 +1542,53 @@ def test_exception_bad_args_0(self):
15421542else:
15431543self.fail("Expected OSError: %s" % desired_exception)
154415441545+# We mock the __del__ method for Popen in the next two tests
1546+# because it does cleanup based on the pid returned by fork_exec
1547+# along with issuing a resource warning if it still exists. Since
1548+# we don't actually spawn a process in these tests we can forego
1549+# the destructor. An alternative would be to set _child_created to
1550+# False before the destructor is called but there is no easy way
1551+# to do that
1552+class PopenNoDestructor(subprocess.Popen):
1553+def __del__(self):
1554+pass
1555+1556+@mock.patch("subprocess._posixsubprocess.fork_exec")
1557+def test_exception_errpipe_normal(self, fork_exec):
1558+"""Test error passing done through errpipe_write in the good case"""
1559+def proper_error(*args):
1560+errpipe_write = args[13]
1561+# Write the hex for the error code EISDIR: 'is a directory'
1562+err_code = '{:x}'.format(errno.EISDIR).encode()
1563+os.write(errpipe_write, b"OSError:" + err_code + b":")
1564+return 0
1565+1566+fork_exec.side_effect = proper_error
1567+1568+with self.assertRaises(IsADirectoryError):
1569+self.PopenNoDestructor(["non_existent_command"])
1570+1571+@mock.patch("subprocess._posixsubprocess.fork_exec")
1572+def test_exception_errpipe_bad_data(self, fork_exec):
1573+"""Test error passing done through errpipe_write where its not
1574+ in the expected format"""
1575+error_data = b"\xFF\x00\xDE\xAD"
1576+def bad_error(*args):
1577+errpipe_write = args[13]
1578+# Anything can be in the pipe, no assumptions should
1579+# be made about its encoding, so we'll write some
1580+# arbitrary hex bytes to test it out
1581+os.write(errpipe_write, error_data)
1582+return 0
1583+1584+fork_exec.side_effect = bad_error
1585+1586+with self.assertRaises(subprocess.SubprocessError) as e:
1587+self.PopenNoDestructor(["non_existent_command"])
1588+1589+self.assertIn(repr(error_data), str(e.exception))
1590+1591+15451592def test_restore_signals(self):
15461593# Code coverage for both values of restore_signals to make sure it
15471594# at least does not blow up.