blob: 3d0428efa19a79623de2c063e29016cb0d0df8b2 [file] [log] [blame]
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001"""
2Tests for kqueue wrapper.
3"""
4import socket
5import errno
6import time
7import select
8import sys
9import unittest
10
Benjamin Petersonee8712c2008-05-20 21:35:26 +000011from test import support
Christian Heimes4fbc72b2008-03-22 00:47:35 +000012if not hasattr(select, "kqueue"):
Benjamin Petersone549ead2009-03-28 21:42:05 +000013 raise unittest.SkipTest("test works only on BSD")
Christian Heimes4fbc72b2008-03-22 00:47:35 +000014
15class TestKQueue(unittest.TestCase):
16 def test_create_queue(self):
17 kq = select.kqueue()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000018 self.assertTrue(kq.fileno() > 0, kq.fileno())
19 self.assertTrue(not kq.closed)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000020 kq.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000021 self.assertTrue(kq.closed)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000022 self.assertRaises(ValueError, kq.fileno)
23
24 def test_create_event(self):
Mark Dickinsona56c4672009-01-27 18:17:45 +000025 from operator import lt, le, gt, ge
Christian Heimes4fbc72b2008-03-22 00:47:35 +000026 fd = sys.stderr.fileno()
27 ev = select.kevent(fd)
28 other = select.kevent(1000)
29 self.assertEqual(ev.ident, fd)
30 self.assertEqual(ev.filter, select.KQ_FILTER_READ)
31 self.assertEqual(ev.flags, select.KQ_EV_ADD)
32 self.assertEqual(ev.fflags, 0)
33 self.assertEqual(ev.data, 0)
34 self.assertEqual(ev.udata, 0)
35 self.assertEqual(ev, ev)
36 self.assertNotEqual(ev, other)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000037 self.assertTrue(ev < other)
38 self.assertTrue(other >= ev)
Mark Dickinsona56c4672009-01-27 18:17:45 +000039 for op in lt, le, gt, ge:
40 self.assertRaises(TypeError, op, ev, None)
41 self.assertRaises(TypeError, op, ev, 1)
42 self.assertRaises(TypeError, op, ev, "ev")
Christian Heimes4fbc72b2008-03-22 00:47:35 +000043
44 ev = select.kevent(fd, select.KQ_FILTER_WRITE)
45 self.assertEqual(ev.ident, fd)
46 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
47 self.assertEqual(ev.flags, select.KQ_EV_ADD)
48 self.assertEqual(ev.fflags, 0)
49 self.assertEqual(ev.data, 0)
50 self.assertEqual(ev.udata, 0)
51 self.assertEqual(ev, ev)
52 self.assertNotEqual(ev, other)
53
54 ev = select.kevent(fd, select.KQ_FILTER_WRITE, select.KQ_EV_ONESHOT)
55 self.assertEqual(ev.ident, fd)
56 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
57 self.assertEqual(ev.flags, select.KQ_EV_ONESHOT)
58 self.assertEqual(ev.fflags, 0)
59 self.assertEqual(ev.data, 0)
60 self.assertEqual(ev.udata, 0)
61 self.assertEqual(ev, ev)
62 self.assertNotEqual(ev, other)
63
64 ev = select.kevent(1, 2, 3, 4, 5, 6)
65 self.assertEqual(ev.ident, 1)
66 self.assertEqual(ev.filter, 2)
67 self.assertEqual(ev.flags, 3)
68 self.assertEqual(ev.fflags, 4)
69 self.assertEqual(ev.data, 5)
70 self.assertEqual(ev.udata, 6)
71 self.assertEqual(ev, ev)
72 self.assertNotEqual(ev, other)
73
Antoine Pitroud83f1e62009-11-04 21:10:38 +000074 bignum = sys.maxsize * 2 + 1
75 ev = select.kevent(bignum, 1, 2, 3, sys.maxsize, bignum)
76 self.assertEqual(ev.ident, bignum)
77 self.assertEqual(ev.filter, 1)
78 self.assertEqual(ev.flags, 2)
79 self.assertEqual(ev.fflags, 3)
80 self.assertEqual(ev.data, sys.maxsize)
81 self.assertEqual(ev.udata, bignum)
82 self.assertEqual(ev, ev)
83 self.assertNotEqual(ev, other)
84
Christian Heimes4fbc72b2008-03-22 00:47:35 +000085 def test_queue_event(self):
86 serverSocket = socket.socket()
87 serverSocket.bind(('127.0.0.1', 0))
88 serverSocket.listen(1)
89 client = socket.socket()
90 client.setblocking(False)
91 try:
92 client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
93 except socket.error as e:
94 self.assertEquals(e.args[0], errno.EINPROGRESS)
95 else:
96 #raise AssertionError("Connect should have raised EINPROGRESS")
97 pass # FreeBSD doesn't raise an exception here
98 server, addr = serverSocket.accept()
99
100 if sys.platform.startswith("darwin"):
101 flags = select.KQ_EV_ADD | select.KQ_EV_ENABLE
102 else:
103 flags = 0
104
105 kq = select.kqueue()
106 kq2 = select.kqueue.fromfd(kq.fileno())
107
108 ev = select.kevent(server.fileno(),
109 select.KQ_FILTER_WRITE,
110 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
111 kq.control([ev], 0)
112 ev = select.kevent(server.fileno(),
113 select.KQ_FILTER_READ,
114 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
115 kq.control([ev], 0)
116 ev = select.kevent(client.fileno(),
117 select.KQ_FILTER_WRITE,
118 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
119 kq2.control([ev], 0)
120 ev = select.kevent(client.fileno(),
121 select.KQ_FILTER_READ,
122 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
123 kq2.control([ev], 0)
124
125 events = kq.control(None, 4, 1)
126 events = [(e.ident, e.filter, e.flags) for e in events]
127 events.sort()
128 self.assertEquals(events, [
129 (client.fileno(), select.KQ_FILTER_WRITE, flags),
130 (server.fileno(), select.KQ_FILTER_WRITE, flags)])
131
132 client.send(b"Hello!")
133 server.send(b"world!!!")
134
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000135 # We may need to call it several times
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000136 for i in range(10):
137 events = kq.control(None, 4, 1)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000138 if len(events) == 4:
139 break
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000140 time.sleep(1.0)
141 else:
142 self.fail('timeout waiting for event notifications')
143
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000144 events = [(e.ident, e.filter, e.flags) for e in events]
145 events.sort()
146
147 self.assertEquals(events, [
148 (client.fileno(), select.KQ_FILTER_WRITE, flags),
149 (client.fileno(), select.KQ_FILTER_READ, flags),
150 (server.fileno(), select.KQ_FILTER_WRITE, flags),
151 (server.fileno(), select.KQ_FILTER_READ, flags)])
152
153 # Remove completely client, and server read part
154 ev = select.kevent(client.fileno(),
155 select.KQ_FILTER_WRITE,
156 select.KQ_EV_DELETE)
157 kq.control([ev], 0)
158 ev = select.kevent(client.fileno(),
159 select.KQ_FILTER_READ,
160 select.KQ_EV_DELETE)
161 kq.control([ev], 0)
162 ev = select.kevent(server.fileno(),
163 select.KQ_FILTER_READ,
164 select.KQ_EV_DELETE)
165 kq.control([ev], 0, 0)
166
167 events = kq.control([], 4, 0.99)
168 events = [(e.ident, e.filter, e.flags) for e in events]
169 events.sort()
170 self.assertEquals(events, [
171 (server.fileno(), select.KQ_FILTER_WRITE, flags)])
172
173 client.close()
174 server.close()
175 serverSocket.close()
176
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000177 def testPair(self):
178 kq = select.kqueue()
179 a, b = socket.socketpair()
180
181 a.send(b'foo')
182 event1 = select.kevent(a, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
183 event2 = select.kevent(b, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
184 r = kq.control([event1, event2], 1, 1)
185 self.assertTrue(r)
186 self.assertFalse(r[0].flags & select.KQ_EV_ERROR)
187 self.assertEquals(b.recv(r[0].data), b'foo')
188
189 a.close()
190 b.close()
191 kq.close()
192
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000193def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000194 support.run_unittest(TestKQueue)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000195
196if __name__ == "__main__":
197 test_main()