Skip to content

Commit e511f54

Browse files
[3.11] gh-81002: Add tests for termios (GH-110386) (GH-110620)
(cherry picked from commit 92a9e98) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent de62c2c commit e511f54

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

Lib/test/test_termios.py

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import errno
2+
import os
3+
import sys
4+
import tempfile
5+
import unittest
6+
from test.support.import_helper import import_module
7+
8+
termios = import_module('termios')
9+
10+
11+
@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
12+
class TestFunctions(unittest.TestCase):
13+
14+
def setUp(self):
15+
master_fd, self.fd = os.openpty()
16+
self.addCleanup(os.close, master_fd)
17+
self.stream = self.enterContext(open(self.fd, 'wb', buffering=0))
18+
tmp = self.enterContext(tempfile.TemporaryFile(mode='wb', buffering=0))
19+
self.bad_fd = tmp.fileno()
20+
21+
def assertRaisesTermiosError(self, errno, callable, *args):
22+
with self.assertRaises(termios.error) as cm:
23+
callable(*args)
24+
self.assertEqual(cm.exception.args[0], errno)
25+
26+
def test_tcgetattr(self):
27+
attrs = termios.tcgetattr(self.fd)
28+
self.assertIsInstance(attrs, list)
29+
self.assertEqual(len(attrs), 7)
30+
for i in range(6):
31+
self.assertIsInstance(attrs[i], int)
32+
iflag, oflag, cflag, lflag, ispeed, ospeed, cc = attrs
33+
self.assertIsInstance(cc, list)
34+
self.assertEqual(len(cc), termios.NCCS)
35+
for i, x in enumerate(cc):
36+
if ((lflag & termios.ICANON) == 0 and
37+
(i == termios.VMIN or i == termios.VTIME)):
38+
self.assertIsInstance(x, int)
39+
else:
40+
self.assertIsInstance(x, bytes)
41+
self.assertEqual(len(x), 1)
42+
self.assertEqual(termios.tcgetattr(self.stream), attrs)
43+
44+
def test_tcgetattr_errors(self):
45+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcgetattr, self.bad_fd)
46+
self.assertRaises(ValueError, termios.tcgetattr, -1)
47+
self.assertRaises(OverflowError, termios.tcgetattr, 2**1000)
48+
self.assertRaises(TypeError, termios.tcgetattr, object())
49+
self.assertRaises(TypeError, termios.tcgetattr)
50+
51+
def test_tcsetattr(self):
52+
attrs = termios.tcgetattr(self.fd)
53+
termios.tcsetattr(self.fd, termios.TCSANOW, attrs)
54+
termios.tcsetattr(self.fd, termios.TCSADRAIN, attrs)
55+
termios.tcsetattr(self.fd, termios.TCSAFLUSH, attrs)
56+
termios.tcsetattr(self.stream, termios.TCSANOW, attrs)
57+
58+
def test_tcsetattr_errors(self):
59+
attrs = termios.tcgetattr(self.fd)
60+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, tuple(attrs))
61+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1])
62+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs + [0])
63+
for i in range(6):
64+
attrs2 = attrs[:]
65+
attrs2[i] = 2**1000
66+
self.assertRaises(OverflowError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
67+
attrs2[i] = object()
68+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
69+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1] + [attrs[-1][:-1]])
70+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs[:-1] + [attrs[-1] + [b'\0']])
71+
for i in range(len(attrs[-1])):
72+
attrs2 = attrs[:]
73+
attrs2[-1] = attrs2[-1][:]
74+
attrs2[-1][i] = 2**1000
75+
self.assertRaises(OverflowError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
76+
attrs2[-1][i] = object()
77+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
78+
attrs2[-1][i] = b''
79+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
80+
attrs2[-1][i] = b'\0\0'
81+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, attrs2)
82+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW, object())
83+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW)
84+
self.assertRaisesTermiosError(errno.EINVAL, termios.tcsetattr, self.fd, -1, attrs)
85+
self.assertRaises(OverflowError, termios.tcsetattr, self.fd, 2**1000, attrs)
86+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, object(), attrs)
87+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsetattr, self.bad_fd, termios.TCSANOW, attrs)
88+
self.assertRaises(ValueError, termios.tcsetattr, -1, termios.TCSANOW, attrs)
89+
self.assertRaises(OverflowError, termios.tcsetattr, 2**1000, termios.TCSANOW, attrs)
90+
self.assertRaises(TypeError, termios.tcsetattr, object(), termios.TCSANOW, attrs)
91+
self.assertRaises(TypeError, termios.tcsetattr, self.fd, termios.TCSANOW)
92+
93+
def test_tcsendbreak(self):
94+
try:
95+
termios.tcsendbreak(self.fd, 1)
96+
except termios.error as exc:
97+
if exc.args[0] == errno.ENOTTY and sys.platform.startswith('freebsd'):
98+
self.skipTest('termios.tcsendbreak() is not supported '
99+
'with pseudo-terminals (?) on this platform')
100+
raise
101+
termios.tcsendbreak(self.stream, 1)
102+
103+
def test_tcsendbreak_errors(self):
104+
self.assertRaises(OverflowError, termios.tcsendbreak, self.fd, 2**1000)
105+
self.assertRaises(TypeError, termios.tcsendbreak, self.fd, 0.0)
106+
self.assertRaises(TypeError, termios.tcsendbreak, self.fd, object())
107+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsendbreak, self.bad_fd, 0)
108+
self.assertRaises(ValueError, termios.tcsendbreak, -1, 0)
109+
self.assertRaises(OverflowError, termios.tcsendbreak, 2**1000, 0)
110+
self.assertRaises(TypeError, termios.tcsendbreak, object(), 0)
111+
self.assertRaises(TypeError, termios.tcsendbreak, self.fd)
112+
113+
def test_tcdrain(self):
114+
termios.tcdrain(self.fd)
115+
termios.tcdrain(self.stream)
116+
117+
def test_tcdrain_errors(self):
118+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcdrain, self.bad_fd)
119+
self.assertRaises(ValueError, termios.tcdrain, -1)
120+
self.assertRaises(OverflowError, termios.tcdrain, 2**1000)
121+
self.assertRaises(TypeError, termios.tcdrain, object())
122+
self.assertRaises(TypeError, termios.tcdrain)
123+
124+
def test_tcflush(self):
125+
termios.tcflush(self.fd, termios.TCIFLUSH)
126+
termios.tcflush(self.fd, termios.TCOFLUSH)
127+
termios.tcflush(self.fd, termios.TCIOFLUSH)
128+
129+
def test_tcflush_errors(self):
130+
self.assertRaisesTermiosError(errno.EINVAL, termios.tcflush, self.fd, -1)
131+
self.assertRaises(OverflowError, termios.tcflush, self.fd, 2**1000)
132+
self.assertRaises(TypeError, termios.tcflush, self.fd, object())
133+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcflush, self.bad_fd, termios.TCIFLUSH)
134+
self.assertRaises(ValueError, termios.tcflush, -1, termios.TCIFLUSH)
135+
self.assertRaises(OverflowError, termios.tcflush, 2**1000, termios.TCIFLUSH)
136+
self.assertRaises(TypeError, termios.tcflush, object(), termios.TCIFLUSH)
137+
self.assertRaises(TypeError, termios.tcflush, self.fd)
138+
139+
def test_tcflow(self):
140+
termios.tcflow(self.fd, termios.TCOOFF)
141+
termios.tcflow(self.fd, termios.TCOON)
142+
termios.tcflow(self.fd, termios.TCIOFF)
143+
termios.tcflow(self.fd, termios.TCION)
144+
145+
def test_tcflow_errors(self):
146+
self.assertRaisesTermiosError(errno.EINVAL, termios.tcflow, self.fd, -1)
147+
self.assertRaises(OverflowError, termios.tcflow, self.fd, 2**1000)
148+
self.assertRaises(TypeError, termios.tcflow, self.fd, object())
149+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcflow, self.bad_fd, termios.TCOON)
150+
self.assertRaises(ValueError, termios.tcflow, -1, termios.TCOON)
151+
self.assertRaises(OverflowError, termios.tcflow, 2**1000, termios.TCOON)
152+
self.assertRaises(TypeError, termios.tcflow, object(), termios.TCOON)
153+
self.assertRaises(TypeError, termios.tcflow, self.fd)
154+
155+
def test_tcgetwinsize(self):
156+
size = termios.tcgetwinsize(self.fd)
157+
self.assertIsInstance(size, tuple)
158+
self.assertEqual(len(size), 2)
159+
self.assertIsInstance(size[0], int)
160+
self.assertIsInstance(size[1], int)
161+
self.assertEqual(termios.tcgetwinsize(self.stream), size)
162+
163+
def test_tcgetwinsize_errors(self):
164+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcgetwinsize, self.bad_fd)
165+
self.assertRaises(ValueError, termios.tcgetwinsize, -1)
166+
self.assertRaises(OverflowError, termios.tcgetwinsize, 2**1000)
167+
self.assertRaises(TypeError, termios.tcgetwinsize, object())
168+
self.assertRaises(TypeError, termios.tcgetwinsize)
169+
170+
def test_tcsetwinsize(self):
171+
size = termios.tcgetwinsize(self.fd)
172+
termios.tcsetwinsize(self.fd, size)
173+
termios.tcsetwinsize(self.fd, list(size))
174+
termios.tcsetwinsize(self.stream, size)
175+
176+
def test_tcsetwinsize_errors(self):
177+
size = termios.tcgetwinsize(self.fd)
178+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, size[:-1])
179+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, size + (0,))
180+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, object())
181+
self.assertRaises(OverflowError, termios.tcsetwinsize, self.fd, (size[0], 2**1000))
182+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (size[0], float(size[1])))
183+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (size[0], object()))
184+
self.assertRaises(OverflowError, termios.tcsetwinsize, self.fd, (2**1000, size[1]))
185+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (float(size[0]), size[1]))
186+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd, (object(), size[1]))
187+
self.assertRaisesTermiosError(errno.ENOTTY, termios.tcsetwinsize, self.bad_fd, size)
188+
self.assertRaises(ValueError, termios.tcsetwinsize, -1, size)
189+
self.assertRaises(OverflowError, termios.tcsetwinsize, 2**1000, size)
190+
self.assertRaises(TypeError, termios.tcsetwinsize, object(), size)
191+
self.assertRaises(TypeError, termios.tcsetwinsize, self.fd)
192+
193+
194+
class TestModule(unittest.TestCase):
195+
def test_constants(self):
196+
self.assertIsInstance(termios.B0, int)
197+
self.assertIsInstance(termios.B38400, int)
198+
self.assertIsInstance(termios.TCSANOW, int)
199+
self.assertIsInstance(termios.TCSADRAIN, int)
200+
self.assertIsInstance(termios.TCSAFLUSH, int)
201+
self.assertIsInstance(termios.TCIFLUSH, int)
202+
self.assertIsInstance(termios.TCOFLUSH, int)
203+
self.assertIsInstance(termios.TCIOFLUSH, int)
204+
self.assertIsInstance(termios.TCOOFF, int)
205+
self.assertIsInstance(termios.TCOON, int)
206+
self.assertIsInstance(termios.TCIOFF, int)
207+
self.assertIsInstance(termios.TCION, int)
208+
self.assertIsInstance(termios.VTIME, int)
209+
self.assertIsInstance(termios.VMIN, int)
210+
self.assertIsInstance(termios.NCCS, int)
211+
self.assertLess(termios.VTIME, termios.NCCS)
212+
self.assertLess(termios.VMIN, termios.NCCS)
213+
214+
def test_exception(self):
215+
self.assertTrue(issubclass(termios.error, Exception))
216+
self.assertFalse(issubclass(termios.error, OSError))
217+
218+
219+
if __name__ == '__main__':
220+
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add tests for :mod:`termios`.

0 commit comments

Comments
 (0)