test_ioctl.py revision 888a39b54c4f47ee25d53b157e2c50402627cd0b
1import unittest
2from test.test_support import SkipTest, run_unittest
3import os, struct
4try:
5    import fcntl, termios
6except ImportError:
7    raise SkipTest("No fcntl or termios module")
8if not hasattr(termios,'TIOCGPGRP'):
9    raise SkipTest("termios module doesn't have TIOCGPGRP")
10
11try:
12    tty = open("/dev/tty", "r")
13    tty.close()
14except IOError:
15    raise SkipTest("Unable to open /dev/tty")
16
17try:
18    import pty
19except ImportError:
20    pty = None
21
22class IoctlTests(unittest.TestCase):
23    def test_ioctl(self):
24        # If this process has been put into the background, TIOCGPGRP returns
25        # the session ID instead of the process group id.
26        ids = (os.getpgrp(), os.getsid(0))
27        tty = open("/dev/tty", "r")
28        r = fcntl.ioctl(tty, termios.TIOCGPGRP, "    ")
29        rpgrp = struct.unpack("i", r)[0]
30        self.assert_(rpgrp in ids, "%s not in %s" % (rpgrp, ids))
31
32    def test_ioctl_mutate(self):
33        import array
34        buf = array.array('i', [0])
35        ids = (os.getpgrp(), os.getsid(0))
36        tty = open("/dev/tty", "r")
37        r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, 1)
38        rpgrp = buf[0]
39        self.assertEquals(r, 0)
40        self.assert_(rpgrp in ids, "%s not in %s" % (rpgrp, ids))
41
42    def test_ioctl_signed_unsigned_code_param(self):
43        if not pty:
44            raise SkipTest('pty module required')
45        mfd, sfd = pty.openpty()
46        try:
47            if termios.TIOCSWINSZ < 0:
48                set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ
49                set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffffL
50            else:
51                set_winsz_opcode_pos = termios.TIOCSWINSZ
52                set_winsz_opcode_maybe_neg, = struct.unpack("i",
53                        struct.pack("I", termios.TIOCSWINSZ))
54
55            our_winsz = struct.pack("HHHH",80,25,0,0)
56            # test both with a positive and potentially negative ioctl code
57            new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
58            new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
59        finally:
60            os.close(mfd)
61            os.close(sfd)
62
63def test_main():
64    run_unittest(IoctlTests)
65
66if __name__ == "__main__":
67    test_main()
68