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

Reply via email to