blob: a1e5c3dbf8756821a3718edc49fb8d9c6090695c [file] [log] [blame]
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +00001# Test case for the os.poll() function
Fred Drake004d5e62000-10-23 17:22:08 +00002
Serhiy Storchakab1973c22013-08-20 20:38:21 +03003import os
Christian Heimes06888972013-08-20 22:09:41 +02004import subprocess
Serhiy Storchakab1973c22013-08-20 20:38:21 +03005import random
6import select
Serhiy Storchaka78980432013-01-15 01:12:17 +02007import _testcapi
Serhiy Storchakab1973c22013-08-20 20:38:21 +03008try:
9 import threading
10except ImportError:
11 threading = None
12import time
13import unittest
14from test.support import TESTFN, run_unittest, reap_threads
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000015
16try:
17 select.poll
18except AttributeError:
Brett Cannoncd8efa32012-11-14 15:16:53 -050019 raise unittest.SkipTest("select.poll not defined")
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000020
21
22def find_ready_matching(ready, flag):
23 match = []
24 for fd, mode in ready:
25 if mode & flag:
26 match.append(fd)
27 return match
28
Thomas Wouters89f507f2006-12-13 04:49:30 +000029class PollTests(unittest.TestCase):
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000030
Thomas Wouters89f507f2006-12-13 04:49:30 +000031 def test_poll1(self):
32 # Basic functional test of poll object
33 # Create a bunch of pipe and test that poll works with them.
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000034
Thomas Wouters89f507f2006-12-13 04:49:30 +000035 p = select.poll()
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000036
Thomas Wouters89f507f2006-12-13 04:49:30 +000037 NUM_PIPES = 12
Guido van Rossumbdab7d32007-07-11 20:43:16 +000038 MSG = b" This is a test."
Thomas Wouters89f507f2006-12-13 04:49:30 +000039 MSG_LEN = len(MSG)
40 readers = []
41 writers = []
42 r2w = {}
43 w2r = {}
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000044
Thomas Wouters89f507f2006-12-13 04:49:30 +000045 for i in range(NUM_PIPES):
46 rd, wr = os.pipe()
Christian Heimes4fbc72b2008-03-22 00:47:35 +000047 p.register(rd)
48 p.modify(rd, select.POLLIN)
Thomas Wouters89f507f2006-12-13 04:49:30 +000049 p.register(wr, select.POLLOUT)
50 readers.append(rd)
51 writers.append(wr)
52 r2w[rd] = wr
53 w2r[wr] = rd
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000054
Thomas Wouters89f507f2006-12-13 04:49:30 +000055 bufs = []
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000056
Thomas Wouters89f507f2006-12-13 04:49:30 +000057 while writers:
58 ready = p.poll()
59 ready_writers = find_ready_matching(ready, select.POLLOUT)
60 if not ready_writers:
Collin Winter3add4d72007-08-29 23:37:32 +000061 raise RuntimeError("no pipes ready for writing")
Thomas Wouters89f507f2006-12-13 04:49:30 +000062 wr = random.choice(ready_writers)
63 os.write(wr, MSG)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000064
Thomas Wouters89f507f2006-12-13 04:49:30 +000065 ready = p.poll()
66 ready_readers = find_ready_matching(ready, select.POLLIN)
67 if not ready_readers:
Collin Winter3add4d72007-08-29 23:37:32 +000068 raise RuntimeError("no pipes ready for reading")
Thomas Wouters89f507f2006-12-13 04:49:30 +000069 rd = random.choice(ready_readers)
70 buf = os.read(rd, MSG_LEN)
71 self.assertEqual(len(buf), MSG_LEN)
72 bufs.append(buf)
73 os.close(r2w[rd]) ; os.close( rd )
74 p.unregister( r2w[rd] )
75 p.unregister( rd )
76 writers.remove(r2w[rd])
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000077
Thomas Wouters89f507f2006-12-13 04:49:30 +000078 self.assertEqual(bufs, [MSG] * NUM_PIPES)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000079
Richard Oudkerk53dff0c2012-12-09 16:05:20 +000080 def test_poll_unit_tests(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +000081 # returns NVAL for invalid file descriptor
Richard Oudkerk53dff0c2012-12-09 16:05:20 +000082 FD, w = os.pipe()
83 os.close(FD)
84 os.close(w)
Thomas Wouters89f507f2006-12-13 04:49:30 +000085 p = select.poll()
86 p.register(FD)
87 r = p.poll()
88 self.assertEqual(r[0], (FD, select.POLLNVAL))
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000089
Thomas Wouters89f507f2006-12-13 04:49:30 +000090 f = open(TESTFN, 'w')
91 fd = f.fileno()
92 p = select.poll()
93 p.register(f)
94 r = p.poll()
95 self.assertEqual(r[0][0], fd)
96 f.close()
97 r = p.poll()
98 self.assertEqual(r[0], (fd, select.POLLNVAL))
99 os.unlink(TESTFN)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000100
Thomas Wouters89f507f2006-12-13 04:49:30 +0000101 # type error for invalid arguments
102 p = select.poll()
103 self.assertRaises(TypeError, p.register, p)
104 self.assertRaises(TypeError, p.unregister, p)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000105
Thomas Wouters89f507f2006-12-13 04:49:30 +0000106 # can't unregister non-existent object
107 p = select.poll()
108 self.assertRaises(KeyError, p.unregister, 3)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000109
Thomas Wouters89f507f2006-12-13 04:49:30 +0000110 # Test error cases
111 pollster = select.poll()
112 class Nope:
113 pass
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000114
Thomas Wouters89f507f2006-12-13 04:49:30 +0000115 class Almost:
116 def fileno(self):
117 return 'fileno'
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000118
Thomas Wouters89f507f2006-12-13 04:49:30 +0000119 self.assertRaises(TypeError, pollster.register, Nope(), 0)
120 self.assertRaises(TypeError, pollster.register, Almost(), 0)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000121
Thomas Wouters89f507f2006-12-13 04:49:30 +0000122 # Another test case for poll(). This is copied from the test case for
123 # select(), modified to use poll() instead.
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000124
Thomas Wouters89f507f2006-12-13 04:49:30 +0000125 def test_poll2(self):
126 cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done'
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000127 proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
128 bufsize=0)
129 p = proc.stdout
Thomas Wouters89f507f2006-12-13 04:49:30 +0000130 pollster = select.poll()
131 pollster.register( p, select.POLLIN )
132 for tout in (0, 1000, 2000, 4000, 8000, 16000) + (-1,)*10:
133 fdlist = pollster.poll(tout)
134 if (fdlist == []):
135 continue
136 fd, flags = fdlist[0]
137 if flags & select.POLLHUP:
138 line = p.readline()
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000139 if line != b"":
Thomas Wouters89f507f2006-12-13 04:49:30 +0000140 self.fail('error: pipe seems to be closed, but still returns data')
141 continue
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000142
Thomas Wouters89f507f2006-12-13 04:49:30 +0000143 elif flags & select.POLLIN:
144 line = p.readline()
145 if not line:
146 break
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000147 self.assertEqual(line, b'testing...\n')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000148 continue
149 else:
150 self.fail('Unexpected return value from select.poll: %s' % fdlist)
151 p.close()
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000152
Thomas Wouters89f507f2006-12-13 04:49:30 +0000153 def test_poll3(self):
154 # test int overflow
155 pollster = select.poll()
156 pollster.register(1)
Neal Norwitz0f46bbf2005-11-03 05:00:25 +0000157
Guido van Rossume2a383d2007-01-15 16:59:06 +0000158 self.assertRaises(OverflowError, pollster.poll, 1 << 64)
Neal Norwitz0f46bbf2005-11-03 05:00:25 +0000159
Thomas Wouters89f507f2006-12-13 04:49:30 +0000160 x = 2 + 3
161 if x != 5:
162 self.fail('Overflow must have occurred')
Tim Peters536cf992005-12-25 23:18:31 +0000163
Serhiy Storchaka78980432013-01-15 01:12:17 +0200164 pollster = select.poll()
165 # Issue 15989
166 self.assertRaises(OverflowError, pollster.register, 0,
167 _testcapi.SHRT_MAX + 1)
168 self.assertRaises(OverflowError, pollster.register, 0,
169 _testcapi.USHRT_MAX + 1)
170 self.assertRaises(OverflowError, pollster.poll, _testcapi.INT_MAX + 1)
171 self.assertRaises(OverflowError, pollster.poll, _testcapi.UINT_MAX + 1)
172
Serhiy Storchakab1973c22013-08-20 20:38:21 +0300173 @unittest.skipUnless(threading, 'Threading required for this test.')
174 @reap_threads
175 def test_threaded_poll(self):
176 r, w = os.pipe()
177 self.addCleanup(os.close, r)
178 self.addCleanup(os.close, w)
179 rfds = []
180 for i in range(10):
181 fd = os.dup(r)
182 self.addCleanup(os.close, fd)
183 rfds.append(fd)
184 pollster = select.poll()
185 for fd in rfds:
186 pollster.register(fd, select.POLLIN)
187
188 t = threading.Thread(target=pollster.poll)
189 t.start()
190 try:
191 time.sleep(0.5)
192 # trigger ufds array reallocation
193 for fd in rfds:
194 pollster.unregister(fd)
195 pollster.register(w, select.POLLOUT)
196 self.assertRaises(RuntimeError, pollster.poll)
197 finally:
198 # and make the call to poll() from the thread return
199 os.write(w, b'spam')
200 t.join()
201
202
Thomas Wouters89f507f2006-12-13 04:49:30 +0000203def test_main():
204 run_unittest(PollTests)
Neal Norwitz0f46bbf2005-11-03 05:00:25 +0000205
Thomas Wouters89f507f2006-12-13 04:49:30 +0000206if __name__ == '__main__':
207 test_main()