Skip to content

Commit 9a6e70f

Browse files
committed
Restructure the tests, perform cleanup.
Signed-off-by: Soumendra Ganguly <[email protected]>
1 parent 26c0928 commit 9a6e70f

File tree

1 file changed

+51
-37
lines changed

1 file changed

+51
-37
lines changed

Lib/test/test_pty.py

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
TEST_STRING_1 = b"I wish to buy a fish license.\n"
2323
TEST_STRING_2 = b"For my pet fish, Eric.\n"
2424

25+
try:
26+
_TIOCGWINSZ = tty.TIOCGWINSZ
27+
_TIOCSWINSZ = tty.TIOCSWINSZ
28+
_HAVE_WINSZ = True
29+
except AttributeError:
30+
_HAVE_WINSZ = False
31+
2532
if verbose:
2633
def debug(msg):
2734
print(msg)
@@ -80,11 +87,17 @@ def expectedFailureOnBSD(fun):
8087
return unittest.expectedFailure(fun)
8188
return fun
8289

90+
def _get_term_winsz(fd):
91+
s = struct.pack("HHHH", 0, 0, 0, 0)
92+
return fcntl.ioctl(fd, _TIOCGWINSZ, s)
93+
94+
def _set_term_winsz(fd, winsz):
95+
fcntl.ioctl(fd, _TIOCSWINSZ, winsz)
96+
8397

8498
# Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
8599
# because pty code is not too portable.
86100
# XXX(nnorwitz): these tests leak fds when there is an error.
87-
# Soumendra: test_openpty may leave tty in abnormal state upon failure.
88101
class PtyTest(unittest.TestCase):
89102
def setUp(self):
90103
old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
@@ -98,62 +111,70 @@ def setUp(self):
98111
self.addCleanup(signal.alarm, 0)
99112
signal.alarm(10)
100113

114+
# Save original stdin window size
115+
self.stdin_rows = None
116+
self.stdin_cols = None
117+
if _HAVE_WINSZ:
118+
try:
119+
stdin_dim = os.get_terminal_size(pty.STDIN_FILENO)
120+
self.stdin_rows = stdin_dim.lines
121+
self.stdin_cols = stdin_dim.columns
122+
old_stdin_winsz = struct.pack("HHHH", self.stdin_rows,
123+
self.stdin_cols, 0, 0)
124+
self.addCleanup(_set_term_winsz, pty.STDIN_FILENO, old_stdin_winsz)
125+
except OSError:
126+
# possible reason: current stdin is not a tty
127+
pass
128+
101129
def handle_sig(self, sig, frame):
102130
self.fail("isatty hung")
103131

104-
# RELEVANT ANYMORE?
105132
@staticmethod
106133
def handle_sighup(signum, frame):
107134
# bpo-38547: if the process is the session leader, os.close(master_fd)
108135
# of "master_fd, slave_name = pty.master_open()" raises SIGHUP
109136
# signal: just ignore the signal.
137+
#
138+
# NOTE: the above comment is from an older version of the test;
139+
# master_open() is not being used anymore.
110140
pass
111141

112142
@expectedFailureIfStdinIsTTY
113143
def test_openpty(self):
114144
try:
115145
mode = tty.tcgetattr(pty.STDIN_FILENO)
116146
except tty.error:
117-
# pty.STDIN_FILENO not a tty?
147+
# possible reason: current stdin is not a tty
118148
debug("tty.tcgetattr(pty.STDIN_FILENO) failed")
119149
mode = None
120150

121-
try:
122-
TIOCGWINSZ = tty.TIOCGWINSZ
123-
TIOCSWINSZ = tty.TIOCSWINSZ
124-
except AttributeError:
125-
debug("TIOCSWINSZ/TIOCGWINSZ not available")
126-
winsz = None
127-
else:
151+
new_stdin_winsz = None
152+
if _HAVE_WINSZ:
128153
try:
129154
debug("Setting pty.STDIN_FILENO window size")
130-
current_stdin_winsz = os.get_terminal_size(pty.STDIN_FILENO)
131-
132155
# Set number of columns and rows to be the
133156
# floors of 1/5 of respective original values
134-
winsz = struct.pack("HHHH", current_stdin_winsz.lines//5,
135-
current_stdin_winsz.columns//5, 0, 0)
136-
fcntl.ioctl(pty.STDIN_FILENO, TIOCSWINSZ, winsz)
157+
target_stdin_winsz = struct.pack("HHHH", self.stdin_rows//5,
158+
self.stdin_cols//5, 0, 0)
159+
_set_term_winsz(pty.STDIN_FILENO, target_stdin_winsz)
137160

138161
# Were we able to set the window size
139162
# of pty.STDIN_FILENO successfully?
140-
s = struct.pack("HHHH", 0, 0, 0, 0)
141-
new_stdin_winsz = fcntl.ioctl(pty.STDIN_FILENO, TIOCGWINSZ, s)
142-
self.assertEqual(new_stdin_winsz, winsz,
163+
new_stdin_winsz = _get_term_winsz(pty.STDIN_FILENO)
164+
self.assertEqual(new_stdin_winsz, target_stdin_winsz,
143165
"pty.STDIN_FILENO window size unchanged")
144166
except OSError:
145-
# pty.STDIN_FILENO not a tty?
146-
debug("Failed to set pty.STDIN_FILENO window size")
147-
winsz = None
167+
# possible reason: current stdin is not a tty
168+
warnings.warn("Failed to set pty.STDIN_FILENO window size")
169+
pass
148170

149171
try:
150172
debug("Calling pty.openpty()")
151173
try:
152-
master_fd, slave_fd = pty.openpty(mode, winsz)
174+
master_fd, slave_fd = pty.openpty(mode, new_stdin_winsz)
153175
except TypeError:
154176
master_fd, slave_fd = pty.openpty()
155-
debug("Got master_fd '%d', slave_fd '%d'" %
156-
(master_fd, slave_fd))
177+
debug(f"Got master_fd '{master_fd}', slave_fd '{slave_fd}'")
157178
except OSError:
158179
# " An optional feature could not be imported " ... ?
159180
raise unittest.SkipTest("Pseudo-terminals (seemingly) not functional.")
@@ -163,15 +184,16 @@ def test_openpty(self):
163184
if mode:
164185
self.assertEqual(tty.tcgetattr(slave_fd), mode,
165186
"openpty() failed to set slave termios")
166-
if winsz:
167-
s = struct.pack("HHHH", 0, 0, 0, 0)
168-
self.assertEqual(fcntl.ioctl(slave_fd, TIOCGWINSZ, s), winsz,
187+
if new_stdin_winsz:
188+
self.assertEqual(_get_term_winsz(slave_fd), new_stdin_winsz,
169189
"openpty() failed to set slave window size")
170190

171-
# RELEVANT ANYMORE?
172191
# Solaris requires reading the fd before anything is returned.
173192
# My guess is that since we open and close the slave fd
174193
# in master_open(), we need to read the EOF.
194+
#
195+
# NOTE: the above comment is from an older version of the test;
196+
# master_open() is not being used anymore.
175197

176198
# Ensure the fd is non-blocking in case there's nothing to read.
177199
blocking = os.get_blocking(master_fd)
@@ -205,13 +227,6 @@ def test_openpty(self):
205227
# to ignore this signal.
206228
os.close(master_fd)
207229

208-
if winsz:
209-
winsz = struct.pack("HHHH", current_stdin_winsz.lines,
210-
current_stdin_winsz.columns, 0, 0)
211-
fcntl.ioctl(pty.STDIN_FILENO, TIOCSWINSZ, winsz)
212-
213-
# pty.openpty() passed.
214-
215230
def test_fork(self):
216231
debug("calling pty.fork()")
217232
pid, master_fd = pty.fork()
@@ -295,8 +310,6 @@ def test_fork(self):
295310

296311
os.close(master_fd)
297312

298-
# pty.fork() passed.
299-
300313
@expectedFailureOnBSD
301314
def test_master_read(self):
302315
debug("Calling pty.openpty()")
@@ -407,6 +420,7 @@ def test__copy_eof_on_all(self):
407420
with self.assertRaises(IndexError):
408421
pty._copy(masters[0])
409422

423+
410424
def tearDownModule():
411425
reap_children()
412426

0 commit comments

Comments
 (0)