blob: 7a1b7b1e3f9b280bab70d86ae336a3757adec6ae [file] [log] [blame]
Neal Norwitz7d814522003-03-21 01:39:14 +00001import pty, os, sys, signal
Barry Warsaw04f357c2002-07-23 19:04:11 +00002from test.test_support import verbose, TestFailed, TestSkipped
Fred Drake4c136ee2000-06-30 23:22:35 +00003
Thomas Woutersb0dbeef2001-03-22 14:50:24 +00004TEST_STRING_1 = "I wish to buy a fish license.\n"
5TEST_STRING_2 = "For my pet fish, Eric.\n"
Fred Drake4c136ee2000-06-30 23:22:35 +00006
7if verbose:
8 def debug(msg):
9 print msg
10else:
11 def debug(msg):
12 pass
13
14# Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
15# because pty code is not too portable.
16
Neal Norwitz7d814522003-03-21 01:39:14 +000017def test_basic_pty():
18 try:
19 debug("Calling master_open()")
20 master_fd, slave_name = pty.master_open()
21 debug("Got master_fd '%d', slave_name '%s'"%(master_fd, slave_name))
22 debug("Calling slave_open(%s)"%`slave_name`)
23 slave_fd = pty.slave_open(slave_name)
24 debug("Got slave_fd '%d'"%slave_fd)
25 except OSError:
26 # " An optional feature could not be imported " ... ?
27 raise TestSkipped, "Pseudo-terminals (seemingly) not functional."
28
29 if not os.isatty(slave_fd):
30 raise TestFailed, "slave_fd is not a tty"
31
32 # IRIX apparently turns \n into \r\n. Allow that, but avoid allowing other
33 # differences (like extra whitespace, trailing garbage, etc.)
34
35 debug("Writing to slave_fd")
36 os.write(slave_fd, TEST_STRING_1)
37 s1 = os.read(master_fd, 1024)
38 sys.stdout.write(s1.replace("\r\n", "\n"))
39
40 debug("Writing chunked output")
41 os.write(slave_fd, TEST_STRING_2[:5])
42 os.write(slave_fd, TEST_STRING_2[5:])
43 s2 = os.read(master_fd, 1024)
44 sys.stdout.write(s2.replace("\r\n", "\n"))
45
46 os.close(slave_fd)
47 os.close(master_fd)
48
49def handle_sig(sig, frame):
50 raise TestFailed, "isatty hung"
51
52# isatty() and close() can hang on some platforms
53# set an alarm before running the test to make sure we don't hang forever
54old_alarm = signal.signal(signal.SIGALRM, handle_sig)
55signal.alarm(10)
56
Fred Drake4c136ee2000-06-30 23:22:35 +000057try:
Neal Norwitz7d814522003-03-21 01:39:14 +000058 test_basic_pty()
59finally:
60 # remove alarm, restore old alarm handler
61 signal.alarm(0)
62 signal.signal(signal.SIGALRM, old_alarm)
Fred Drake4c136ee2000-06-30 23:22:35 +000063
64# basic pty passed.
65
66debug("calling pty.fork()")
67pid, master_fd = pty.fork()
68if pid == pty.CHILD:
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000069 # stdout should be connected to a tty.
70 if not os.isatty(1):
71 debug("Child's fd 1 is not a tty?!")
72 os._exit(3)
73
74 # After pty.fork(), the child should already be a session leader.
Tim Petersa19a1682001-03-29 04:36:09 +000075 # (on those systems that have that concept.)
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000076 debug("In child, calling os.setsid()")
Fred Drake4c136ee2000-06-30 23:22:35 +000077 try:
Fred Drake4c136ee2000-06-30 23:22:35 +000078 os.setsid()
79 except OSError:
80 # Good, we already were session leader
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000081 debug("Good: OSError was raised.")
Fred Drake4c136ee2000-06-30 23:22:35 +000082 pass
83 except AttributeError:
84 # Have pty, but not setsid() ?
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000085 debug("No setsid() available ?")
Fred Drake4c136ee2000-06-30 23:22:35 +000086 pass
87 except:
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000088 # We don't want this error to propagate, escaping the call to
89 # os._exit() and causing very peculiar behavior in the calling
Fred Drake4c136ee2000-06-30 23:22:35 +000090 # regrtest.py !
Thomas Woutersb0dbeef2001-03-22 14:50:24 +000091 # Note: could add traceback printing here.
92 debug("An unexpected error was raised.")
Fred Drake4c136ee2000-06-30 23:22:35 +000093 os._exit(1)
94 else:
95 debug("os.setsid() succeeded! (bad!)")
96 os._exit(2)
97 os._exit(4)
98else:
99 debug("Waiting for child (%d) to finish."%pid)
100 (pid, status) = os.waitpid(pid, 0)
Guido van Rossum54e54c62001-09-04 19:14:14 +0000101 res = status >> 8
Thomas Woutersb0dbeef2001-03-22 14:50:24 +0000102 debug("Child (%d) exited with status %d (%d)."%(pid, res, status))
103 if res == 1:
Fred Drake4c136ee2000-06-30 23:22:35 +0000104 raise TestFailed, "Child raised an unexpected exception in os.setsid()"
Thomas Woutersb0dbeef2001-03-22 14:50:24 +0000105 elif res == 2:
Fred Drake4c136ee2000-06-30 23:22:35 +0000106 raise TestFailed, "pty.fork() failed to make child a session leader."
Thomas Woutersb0dbeef2001-03-22 14:50:24 +0000107 elif res == 3:
Fred Drake4c136ee2000-06-30 23:22:35 +0000108 raise TestFailed, "Child spawned by pty.fork() did not have a tty as stdout"
Thomas Woutersb0dbeef2001-03-22 14:50:24 +0000109 elif res != 4:
110 raise TestFailed, "pty.fork() failed for unknown reasons."
Fred Drake4c136ee2000-06-30 23:22:35 +0000111
112os.close(master_fd)
113
114# pty.fork() passed.