blob: 5c9f7c9ceafcec35996dced16df0bc28ecc7c69b [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
Victor Stinner46b20912011-06-29 14:59:10 +020026
27 fd = os.open(os.devnull, os.O_WRONLY)
28 self.addCleanup(os.close, fd)
29
Christian Heimes4fbc72b2008-03-22 00:47:35 +000030 ev = select.kevent(fd)
31 other = select.kevent(1000)
32 self.assertEqual(ev.ident, fd)
33 self.assertEqual(ev.filter, select.KQ_FILTER_READ)
34 self.assertEqual(ev.flags, select.KQ_EV_ADD)
35 self.assertEqual(ev.fflags, 0)
36 self.assertEqual(ev.data, 0)
37 self.assertEqual(ev.udata, 0)
38 self.assertEqual(ev, ev)
39 self.assertNotEqual(ev, other)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000040 self.assertTrue(ev < other)
41 self.assertTrue(other >= ev)
Mark Dickinsona56c4672009-01-27 18:17:45 +000042 for op in lt, le, gt, ge:
43 self.assertRaises(TypeError, op, ev, None)
44 self.assertRaises(TypeError, op, ev, 1)
45 self.assertRaises(TypeError, op, ev, "ev")
Christian Heimes4fbc72b2008-03-22 00:47:35 +000046
47 ev = select.kevent(fd, select.KQ_FILTER_WRITE)
48 self.assertEqual(ev.ident, fd)
49 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
50 self.assertEqual(ev.flags, select.KQ_EV_ADD)
51 self.assertEqual(ev.fflags, 0)
52 self.assertEqual(ev.data, 0)
53 self.assertEqual(ev.udata, 0)
54 self.assertEqual(ev, ev)
55 self.assertNotEqual(ev, other)
56
57 ev = select.kevent(fd, select.KQ_FILTER_WRITE, select.KQ_EV_ONESHOT)
58 self.assertEqual(ev.ident, fd)
59 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
60 self.assertEqual(ev.flags, select.KQ_EV_ONESHOT)
61 self.assertEqual(ev.fflags, 0)
62 self.assertEqual(ev.data, 0)
63 self.assertEqual(ev.udata, 0)
64 self.assertEqual(ev, ev)
65 self.assertNotEqual(ev, other)
66
67 ev = select.kevent(1, 2, 3, 4, 5, 6)
68 self.assertEqual(ev.ident, 1)
69 self.assertEqual(ev.filter, 2)
70 self.assertEqual(ev.flags, 3)
71 self.assertEqual(ev.fflags, 4)
72 self.assertEqual(ev.data, 5)
73 self.assertEqual(ev.udata, 6)
74 self.assertEqual(ev, ev)
75 self.assertNotEqual(ev, other)
76
Antoine Pitroud83f1e62009-11-04 21:10:38 +000077 bignum = sys.maxsize * 2 + 1
78 ev = select.kevent(bignum, 1, 2, 3, sys.maxsize, bignum)
79 self.assertEqual(ev.ident, bignum)
80 self.assertEqual(ev.filter, 1)
81 self.assertEqual(ev.flags, 2)
82 self.assertEqual(ev.fflags, 3)
83 self.assertEqual(ev.data, sys.maxsize)
84 self.assertEqual(ev.udata, bignum)
85 self.assertEqual(ev, ev)
86 self.assertNotEqual(ev, other)
87
Christian Heimes4fbc72b2008-03-22 00:47:35 +000088 def test_queue_event(self):
89 serverSocket = socket.socket()
90 serverSocket.bind(('127.0.0.1', 0))
91 serverSocket.listen(1)
92 client = socket.socket()
93 client.setblocking(False)
94 try:
95 client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
96 except socket.error as e:
Ezio Melottib3aedd42010-11-20 19:04:17 +000097 self.assertEqual(e.args[0], errno.EINPROGRESS)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000098 else:
99 #raise AssertionError("Connect should have raised EINPROGRESS")
100 pass # FreeBSD doesn't raise an exception here
101 server, addr = serverSocket.accept()
102
103 if sys.platform.startswith("darwin"):
104 flags = select.KQ_EV_ADD | select.KQ_EV_ENABLE
105 else:
106 flags = 0
107
108 kq = select.kqueue()
109 kq2 = select.kqueue.fromfd(kq.fileno())
110
111 ev = select.kevent(server.fileno(),
112 select.KQ_FILTER_WRITE,
113 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
114 kq.control([ev], 0)
115 ev = select.kevent(server.fileno(),
116 select.KQ_FILTER_READ,
117 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
118 kq.control([ev], 0)
119 ev = select.kevent(client.fileno(),
120 select.KQ_FILTER_WRITE,
121 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
122 kq2.control([ev], 0)
123 ev = select.kevent(client.fileno(),
124 select.KQ_FILTER_READ,
125 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
126 kq2.control([ev], 0)
127
128 events = kq.control(None, 4, 1)
129 events = [(e.ident, e.filter, e.flags) for e in events]
130 events.sort()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000131 self.assertEqual(events, [
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000132 (client.fileno(), select.KQ_FILTER_WRITE, flags),
133 (server.fileno(), select.KQ_FILTER_WRITE, flags)])
134
135 client.send(b"Hello!")
136 server.send(b"world!!!")
137
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000138 # We may need to call it several times
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000139 for i in range(10):
140 events = kq.control(None, 4, 1)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000141 if len(events) == 4:
142 break
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000143 time.sleep(1.0)
144 else:
145 self.fail('timeout waiting for event notifications')
146
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000147 events = [(e.ident, e.filter, e.flags) for e in events]
148 events.sort()
149
Ezio Melottib3aedd42010-11-20 19:04:17 +0000150 self.assertEqual(events, [
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000151 (client.fileno(), select.KQ_FILTER_WRITE, flags),
152 (client.fileno(), select.KQ_FILTER_READ, flags),
153 (server.fileno(), select.KQ_FILTER_WRITE, flags),
154 (server.fileno(), select.KQ_FILTER_READ, flags)])
155
156 # Remove completely client, and server read part
157 ev = select.kevent(client.fileno(),
158 select.KQ_FILTER_WRITE,
159 select.KQ_EV_DELETE)
160 kq.control([ev], 0)
161 ev = select.kevent(client.fileno(),
162 select.KQ_FILTER_READ,
163 select.KQ_EV_DELETE)
164 kq.control([ev], 0)
165 ev = select.kevent(server.fileno(),
166 select.KQ_FILTER_READ,
167 select.KQ_EV_DELETE)
168 kq.control([ev], 0, 0)
169
170 events = kq.control([], 4, 0.99)
171 events = [(e.ident, e.filter, e.flags) for e in events]
172 events.sort()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000173 self.assertEqual(events, [
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000174 (server.fileno(), select.KQ_FILTER_WRITE, flags)])
175
176 client.close()
177 server.close()
178 serverSocket.close()
179
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000180 def testPair(self):
181 kq = select.kqueue()
182 a, b = socket.socketpair()
183
184 a.send(b'foo')
185 event1 = select.kevent(a, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
186 event2 = select.kevent(b, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
187 r = kq.control([event1, event2], 1, 1)
188 self.assertTrue(r)
189 self.assertFalse(r[0].flags & select.KQ_EV_ERROR)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000190 self.assertEqual(b.recv(r[0].data), b'foo')
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000191
192 a.close()
193 b.close()
194 kq.close()
195
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000196def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000197 support.run_unittest(TestKQueue)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000198
199if __name__ == "__main__":
200 test_main()