https://github.com/python/cpython/commit/c709d3b50323c3b393365c8f0820a97069ca50f8 commit: c709d3b50323c3b393365c8f0820a97069ca50f8 branch: 3.13 author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com> committer: serhiy-storchaka <storch...@gmail.com> date: 2025-04-21T06:49:45Z summary:
[3.13] gh-132742: Add more tests for fcntl.ioctl() (GH-132756) (GH-132764) Test with different types of argument: integer, mutable and immutable buffers, immutable buffer with mutable_flag set to false. (cherry picked from commit a04390b4dad071195f834db347aa686292811051) Co-authored-by: Serhiy Storchaka <storch...@gmail.com> files: M Lib/test/test_ioctl.py diff --git a/Lib/test/test_ioctl.py b/Lib/test/test_ioctl.py index 7b7067eb7b61d4..c1aac8eec58330 100644 --- a/Lib/test/test_ioctl.py +++ b/Lib/test/test_ioctl.py @@ -14,7 +14,7 @@ else: with tty: # Skip if another process is in foreground - r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ") + r = fcntl.ioctl(tty, termios.TIOCGPGRP, struct.pack("i", 0)) rpgrp = struct.unpack("i", r)[0] if rpgrp not in (os.getpgrp(), os.getsid(0)): raise unittest.SkipTest("Neither the process group nor the session " @@ -27,19 +27,54 @@ pty = None class IoctlTests(unittest.TestCase): - def test_ioctl(self): + def test_ioctl_immutable_buf(self): # If this process has been put into the background, TIOCGPGRP returns # the session ID instead of the process group id. ids = (os.getpgrp(), os.getsid(0)) with open("/dev/tty", "rb") as tty: - r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ") - rpgrp = struct.unpack("i", r)[0] + # string + buf = " "*8 + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf) + self.assertIsInstance(r, bytes) + rpgrp = memoryview(r).cast('i')[0] self.assertIn(rpgrp, ids) - def _check_ioctl_mutate_len(self, nbytes=None): + # bytes + buf = b" "*8 + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf) + self.assertIsInstance(r, bytes) + rpgrp = memoryview(r).cast('i')[0] + self.assertIn(rpgrp, ids) + + # read-only buffer + r = fcntl.ioctl(tty, termios.TIOCGPGRP, memoryview(buf)) + self.assertIsInstance(r, bytes) + rpgrp = memoryview(r).cast('i')[0] + self.assertIn(rpgrp, ids) + + def test_ioctl_mutable_buf(self): + ids = (os.getpgrp(), os.getsid(0)) + with open("/dev/tty", "rb") as tty: + buf = bytearray(b" "*8) + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf) + self.assertEqual(r, 0) + rpgrp = memoryview(buf).cast('i')[0] + self.assertIn(rpgrp, ids) + + def test_ioctl_no_mutate_buf(self): + ids = (os.getpgrp(), os.getsid(0)) + with open("/dev/tty", "rb") as tty: + buf = bytearray(b" "*8) + save_buf = bytes(buf) + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, False) + self.assertEqual(bytes(buf), save_buf) + self.assertIsInstance(r, bytes) + rpgrp = memoryview(r).cast('i')[0] + self.assertIn(rpgrp, ids) + + def _create_int_buf(self, nbytes=None): buf = array.array('i') intsize = buf.itemsize - ids = (os.getpgrp(), os.getsid(0)) # A fill value unlikely to be in `ids` fill = -12345 if nbytes is not None: @@ -48,23 +83,59 @@ def _check_ioctl_mutate_len(self, nbytes=None): self.assertEqual(len(buf) * intsize, nbytes) # sanity check else: buf.append(fill) + return buf + + def _check_ioctl_mutate_len(self, nbytes=None): + ids = (os.getpgrp(), os.getsid(0)) + buf = self._create_int_buf(nbytes) with open("/dev/tty", "rb") as tty: - r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, True) + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf) rpgrp = buf[0] self.assertEqual(r, 0) self.assertIn(rpgrp, ids) + def _check_ioctl_not_mutate_len(self, nbytes=None): + ids = (os.getpgrp(), os.getsid(0)) + buf = self._create_int_buf(nbytes) + save_buf = bytes(buf) + with open("/dev/tty", "rb") as tty: + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, False) + self.assertIsInstance(r, bytes) + self.assertEqual(len(r), len(save_buf)) + self.assertEqual(bytes(buf), save_buf) + rpgrp = array.array('i', r)[0] + rpgrp = memoryview(r).cast('i')[0] + self.assertIn(rpgrp, ids) + + buf = bytes(buf) + with open("/dev/tty", "rb") as tty: + r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, True) + self.assertIsInstance(r, bytes) + self.assertEqual(len(r), len(save_buf)) + self.assertEqual(buf, save_buf) + rpgrp = array.array('i', r)[0] + rpgrp = memoryview(r).cast('i')[0] + self.assertIn(rpgrp, ids) + def test_ioctl_mutate(self): self._check_ioctl_mutate_len() + self._check_ioctl_not_mutate_len() def test_ioctl_mutate_1024(self): # Issue #9758: a mutable buffer of exactly 1024 bytes wouldn't be # copied back after the system call. self._check_ioctl_mutate_len(1024) + self._check_ioctl_not_mutate_len(1024) def test_ioctl_mutate_2048(self): # Test with a larger buffer, just for the record. self._check_ioctl_mutate_len(2048) + self.assertRaises(ValueError, self._check_ioctl_not_mutate_len, 2048) + + def test_ioctl_tcflush(self): + with open("/dev/tty", "rb") as tty: + r = fcntl.ioctl(tty, termios.TCFLSH, termios.TCIFLUSH) + self.assertEqual(r, 0) def test_ioctl_signed_unsigned_code_param(self): if not pty: _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com