blob: 6a2bf6ea7b77c9e9ecbc3f4a70174de72dec7298 [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 Storchakab1973c22013-08-20 20:38:21 +03007try:
8 import threading
9except ImportError:
10 threading = None
11import time
12import unittest
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020013from test.support import TESTFN, run_unittest, reap_threads, cpython_only
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000014
15try:
16 select.poll
17except AttributeError:
Brett Cannoncd8efa32012-11-14 15:16:53 -050018 raise unittest.SkipTest("select.poll not defined")
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000019
20
21def find_ready_matching(ready, flag):
22 match = []
23 for fd, mode in ready:
24 if mode & flag:
25 match.append(fd)
26 return match
27
Thomas Wouters89f507f2006-12-13 04:49:30 +000028class PollTests(unittest.TestCase):
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000029
Thomas Wouters89f507f2006-12-13 04:49:30 +000030 def test_poll1(self):
31 # Basic functional test of poll object
32 # Create a bunch of pipe and test that poll works with them.
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000033
Thomas Wouters89f507f2006-12-13 04:49:30 +000034 p = select.poll()
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000035
Thomas Wouters89f507f2006-12-13 04:49:30 +000036 NUM_PIPES = 12
Guido van Rossumbdab7d32007-07-11 20:43:16 +000037 MSG = b" This is a test."
Thomas Wouters89f507f2006-12-13 04:49:30 +000038 MSG_LEN = len(MSG)
39 readers = []
40 writers = []
41 r2w = {}
42 w2r = {}
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000043
Thomas Wouters89f507f2006-12-13 04:49:30 +000044 for i in range(NUM_PIPES):
45 rd, wr = os.pipe()
Christian Heimes4fbc72b2008-03-22 00:47:35 +000046 p.register(rd)
47 p.modify(rd, select.POLLIN)
Thomas Wouters89f507f2006-12-13 04:49:30 +000048 p.register(wr, select.POLLOUT)
49 readers.append(rd)
50 writers.append(wr)
51 r2w[rd] = wr
52 w2r[wr] = rd
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000053
Thomas Wouters89f507f2006-12-13 04:49:30 +000054 bufs = []
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000055
Thomas Wouters89f507f2006-12-13 04:49:30 +000056 while writers:
57 ready = p.poll()
58 ready_writers = find_ready_matching(ready, select.POLLOUT)
59 if not ready_writers:
Collin Winter3add4d72007-08-29 23:37:32 +000060 raise RuntimeError("no pipes ready for writing")
Thomas Wouters89f507f2006-12-13 04:49:30 +000061 wr = random.choice(ready_writers)
62 os.write(wr, MSG)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000063
Thomas Wouters89f507f2006-12-13 04:49:30 +000064 ready = p.poll()
65 ready_readers = find_ready_matching(ready, select.POLLIN)
66 if not ready_readers:
Collin Winter3add4d72007-08-29 23:37:32 +000067 raise RuntimeError("no pipes ready for reading")
Thomas Wouters89f507f2006-12-13 04:49:30 +000068 rd = random.choice(ready_readers)
69 buf = os.read(rd, MSG_LEN)
70 self.assertEqual(len(buf), MSG_LEN)
71 bufs.append(buf)
72 os.close(r2w[rd]) ; os.close( rd )
73 p.unregister( r2w[rd] )
74 p.unregister( rd )
75 writers.remove(r2w[rd])
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000076
Thomas Wouters89f507f2006-12-13 04:49:30 +000077 self.assertEqual(bufs, [MSG] * NUM_PIPES)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000078
Richard Oudkerk53dff0c2012-12-09 16:05:20 +000079 def test_poll_unit_tests(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +000080 # returns NVAL for invalid file descriptor
Richard Oudkerk53dff0c2012-12-09 16:05:20 +000081 FD, w = os.pipe()
82 os.close(FD)
83 os.close(w)
Thomas Wouters89f507f2006-12-13 04:49:30 +000084 p = select.poll()
85 p.register(FD)
86 r = p.poll()
87 self.assertEqual(r[0], (FD, select.POLLNVAL))
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000088
Thomas Wouters89f507f2006-12-13 04:49:30 +000089 f = open(TESTFN, 'w')
90 fd = f.fileno()
91 p = select.poll()
92 p.register(f)
93 r = p.poll()
94 self.assertEqual(r[0][0], fd)
95 f.close()
96 r = p.poll()
97 self.assertEqual(r[0], (fd, select.POLLNVAL))
98 os.unlink(TESTFN)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +000099
Thomas Wouters89f507f2006-12-13 04:49:30 +0000100 # type error for invalid arguments
101 p = select.poll()
102 self.assertRaises(TypeError, p.register, p)
103 self.assertRaises(TypeError, p.unregister, p)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000104
Thomas Wouters89f507f2006-12-13 04:49:30 +0000105 # can't unregister non-existent object
106 p = select.poll()
107 self.assertRaises(KeyError, p.unregister, 3)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000108
Thomas Wouters89f507f2006-12-13 04:49:30 +0000109 # Test error cases
110 pollster = select.poll()
111 class Nope:
112 pass
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000113
Thomas Wouters89f507f2006-12-13 04:49:30 +0000114 class Almost:
115 def fileno(self):
116 return 'fileno'
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000117
Thomas Wouters89f507f2006-12-13 04:49:30 +0000118 self.assertRaises(TypeError, pollster.register, Nope(), 0)
119 self.assertRaises(TypeError, pollster.register, Almost(), 0)
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000120
Thomas Wouters89f507f2006-12-13 04:49:30 +0000121 # Another test case for poll(). This is copied from the test case for
122 # select(), modified to use poll() instead.
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000123
Thomas Wouters89f507f2006-12-13 04:49:30 +0000124 def test_poll2(self):
125 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 +0000126 proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
127 bufsize=0)
Martin Panter3cf0b252016-08-12 11:59:52 +0000128 proc.__enter__()
129 self.addCleanup(proc.__exit__, None, None, None)
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000130 p = proc.stdout
Thomas Wouters89f507f2006-12-13 04:49:30 +0000131 pollster = select.poll()
132 pollster.register( p, select.POLLIN )
133 for tout in (0, 1000, 2000, 4000, 8000, 16000) + (-1,)*10:
134 fdlist = pollster.poll(tout)
135 if (fdlist == []):
136 continue
137 fd, flags = fdlist[0]
138 if flags & select.POLLHUP:
139 line = p.readline()
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000140 if line != b"":
Thomas Wouters89f507f2006-12-13 04:49:30 +0000141 self.fail('error: pipe seems to be closed, but still returns data')
142 continue
Andrew M. Kuchling3227cc82000-08-25 01:18:45 +0000143
Thomas Wouters89f507f2006-12-13 04:49:30 +0000144 elif flags & select.POLLIN:
145 line = p.readline()
146 if not line:
147 break
Richard Oudkerk07c34bf2012-12-09 16:05:22 +0000148 self.assertEqual(line, b'testing...\n')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000149 continue
150 else:
151 self.fail('Unexpected return value from select.poll: %s' % fdlist)
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 Storchaka5da107a2013-12-14 19:12:02 +0200164 # Issues #15989, #17919
165 self.assertRaises(OverflowError, pollster.register, 0, -1)
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200166 self.assertRaises(OverflowError, pollster.register, 0, 1 << 64)
Serhiy Storchaka5da107a2013-12-14 19:12:02 +0200167 self.assertRaises(OverflowError, pollster.modify, 1, -1)
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200168 self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64)
169
170 @cpython_only
171 def test_poll_c_limits(self):
172 from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX
173 pollster = select.poll()
174 pollster.register(1)
175
176 # Issues #15989, #17919
177 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1)
Serhiy Storchaka5da107a2013-12-14 19:12:02 +0200178 self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1)
179 self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1)
180 self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1)
Serhiy Storchaka78980432013-01-15 01:12:17 +0200181
Serhiy Storchakab1973c22013-08-20 20:38:21 +0300182 @unittest.skipUnless(threading, 'Threading required for this test.')
183 @reap_threads
184 def test_threaded_poll(self):
185 r, w = os.pipe()
186 self.addCleanup(os.close, r)
187 self.addCleanup(os.close, w)
188 rfds = []
189 for i in range(10):
190 fd = os.dup(r)
191 self.addCleanup(os.close, fd)
192 rfds.append(fd)
193 pollster = select.poll()
194 for fd in rfds:
195 pollster.register(fd, select.POLLIN)
196
197 t = threading.Thread(target=pollster.poll)
198 t.start()
199 try:
200 time.sleep(0.5)
201 # trigger ufds array reallocation
202 for fd in rfds:
203 pollster.unregister(fd)
204 pollster.register(w, select.POLLOUT)
205 self.assertRaises(RuntimeError, pollster.poll)
206 finally:
207 # and make the call to poll() from the thread return
208 os.write(w, b'spam')
209 t.join()
210
211
Thomas Wouters89f507f2006-12-13 04:49:30 +0000212def test_main():
213 run_unittest(PollTests)
Neal Norwitz0f46bbf2005-11-03 05:00:25 +0000214
Thomas Wouters89f507f2006-12-13 04:49:30 +0000215if __name__ == '__main__':
216 test_main()