test_ioctl.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import array
  2. import unittest
  3. from test.test_support import run_unittest, import_module, get_attribute
  4. import os, struct
  5. fcntl = import_module('fcntl')
  6. termios = import_module('termios')
  7. get_attribute(termios, 'TIOCGPGRP') #Can't run tests without this feature
  8. try:
  9. tty = open("/dev/tty", "r")
  10. except IOError:
  11. raise unittest.SkipTest("Unable to open /dev/tty")
  12. else:
  13. # Skip if another process is in foreground
  14. r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ")
  15. tty.close()
  16. rpgrp = struct.unpack("i", r)[0]
  17. if rpgrp not in (os.getpgrp(), os.getsid(0)):
  18. raise unittest.SkipTest("Neither the process group nor the session "
  19. "are attached to /dev/tty")
  20. del tty, r, rpgrp
  21. try:
  22. import pty
  23. except ImportError:
  24. pty = None
  25. class IoctlTests(unittest.TestCase):
  26. def test_ioctl(self):
  27. # If this process has been put into the background, TIOCGPGRP returns
  28. # the session ID instead of the process group id.
  29. ids = (os.getpgrp(), os.getsid(0))
  30. tty = open("/dev/tty", "r")
  31. r = fcntl.ioctl(tty, termios.TIOCGPGRP, " ")
  32. rpgrp = struct.unpack("i", r)[0]
  33. self.assertIn(rpgrp, ids)
  34. def _check_ioctl_mutate_len(self, nbytes=None):
  35. buf = array.array('i')
  36. intsize = buf.itemsize
  37. ids = (os.getpgrp(), os.getsid(0))
  38. # A fill value unlikely to be in `ids`
  39. fill = -12345
  40. if nbytes is not None:
  41. # Extend the buffer so that it is exactly `nbytes` bytes long
  42. buf.extend([fill] * (nbytes // intsize))
  43. self.assertEqual(len(buf) * intsize, nbytes) # sanity check
  44. else:
  45. buf.append(fill)
  46. with open("/dev/tty", "r") as tty:
  47. r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, 1)
  48. rpgrp = buf[0]
  49. self.assertEqual(r, 0)
  50. self.assertIn(rpgrp, ids)
  51. def test_ioctl_mutate(self):
  52. self._check_ioctl_mutate_len()
  53. def test_ioctl_mutate_1024(self):
  54. # Issue #9758: a mutable buffer of exactly 1024 bytes wouldn't be
  55. # copied back after the system call.
  56. self._check_ioctl_mutate_len(1024)
  57. def test_ioctl_mutate_2048(self):
  58. # Test with a larger buffer, just for the record.
  59. self._check_ioctl_mutate_len(2048)
  60. def test_ioctl_signed_unsigned_code_param(self):
  61. if not pty:
  62. raise unittest.SkipTest('pty module required')
  63. mfd, sfd = pty.openpty()
  64. try:
  65. if termios.TIOCSWINSZ < 0:
  66. set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ
  67. set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffffL
  68. else:
  69. set_winsz_opcode_pos = termios.TIOCSWINSZ
  70. set_winsz_opcode_maybe_neg, = struct.unpack("i",
  71. struct.pack("I", termios.TIOCSWINSZ))
  72. our_winsz = struct.pack("HHHH",80,25,0,0)
  73. # test both with a positive and potentially negative ioctl code
  74. new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
  75. new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
  76. finally:
  77. os.close(mfd)
  78. os.close(sfd)
  79. def test_main():
  80. run_unittest(IoctlTests)
  81. if __name__ == "__main__":
  82. test_main()