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):

15421542

else:

15431543

self.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+15451592

def test_restore_signals(self):

15461593

# Code coverage for both values of restore_signals to make sure it

15471594

# at least does not blow up.