blob: 902c99c0f987c6fd23895fb65d874c963d2eeb5b [file] [log] [blame]
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001"""
2Tests for kqueue wrapper.
3"""
Christian Heimes4fbc72b2008-03-22 00:47:35 +00004import errno
Victor Stinner125b2ba2011-06-29 17:20:02 +02005import os
Christian Heimes4fbc72b2008-03-22 00:47:35 +00006import select
Victor Stinner125b2ba2011-06-29 17:20:02 +02007import socket
Christian Heimes4fbc72b2008-03-22 00:47:35 +00008import sys
Victor Stinner125b2ba2011-06-29 17:20:02 +02009import time
Christian Heimes4fbc72b2008-03-22 00:47:35 +000010import unittest
11
Benjamin Petersonee8712c2008-05-20 21:35:26 +000012from test import support
Christian Heimes4fbc72b2008-03-22 00:47:35 +000013if not hasattr(select, "kqueue"):
Benjamin Petersone549ead2009-03-28 21:42:05 +000014 raise unittest.SkipTest("test works only on BSD")
Christian Heimes4fbc72b2008-03-22 00:47:35 +000015
16class TestKQueue(unittest.TestCase):
17 def test_create_queue(self):
18 kq = select.kqueue()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000019 self.assertTrue(kq.fileno() > 0, kq.fileno())
20 self.assertTrue(not kq.closed)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000021 kq.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000022 self.assertTrue(kq.closed)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000023 self.assertRaises(ValueError, kq.fileno)
24
25 def test_create_event(self):
Mark Dickinsona56c4672009-01-27 18:17:45 +000026 from operator import lt, le, gt, ge
Victor Stinner46b20912011-06-29 14:59:10 +020027
28 fd = os.open(os.devnull, os.O_WRONLY)
29 self.addCleanup(os.close, fd)
30
Christian Heimes4fbc72b2008-03-22 00:47:35 +000031 ev = select.kevent(fd)
32 other = select.kevent(1000)
33 self.assertEqual(ev.ident, fd)
34 self.assertEqual(ev.filter, select.KQ_FILTER_READ)
35 self.assertEqual(ev.flags, select.KQ_EV_ADD)
36 self.assertEqual(ev.fflags, 0)
37 self.assertEqual(ev.data, 0)
38 self.assertEqual(ev.udata, 0)
39 self.assertEqual(ev, ev)
40 self.assertNotEqual(ev, other)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000041 self.assertTrue(ev < other)
42 self.assertTrue(other >= ev)
Mark Dickinsona56c4672009-01-27 18:17:45 +000043 for op in lt, le, gt, ge:
44 self.assertRaises(TypeError, op, ev, None)
45 self.assertRaises(TypeError, op, ev, 1)
46 self.assertRaises(TypeError, op, ev, "ev")
Christian Heimes4fbc72b2008-03-22 00:47:35 +000047
48 ev = select.kevent(fd, select.KQ_FILTER_WRITE)
49 self.assertEqual(ev.ident, fd)
50 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
51 self.assertEqual(ev.flags, select.KQ_EV_ADD)
52 self.assertEqual(ev.fflags, 0)
53 self.assertEqual(ev.data, 0)
54 self.assertEqual(ev.udata, 0)
55 self.assertEqual(ev, ev)
56 self.assertNotEqual(ev, other)
57
58 ev = select.kevent(fd, select.KQ_FILTER_WRITE, select.KQ_EV_ONESHOT)
59 self.assertEqual(ev.ident, fd)
60 self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
61 self.assertEqual(ev.flags, select.KQ_EV_ONESHOT)
62 self.assertEqual(ev.fflags, 0)
63 self.assertEqual(ev.data, 0)
64 self.assertEqual(ev.udata, 0)
65 self.assertEqual(ev, ev)
66 self.assertNotEqual(ev, other)
67
68 ev = select.kevent(1, 2, 3, 4, 5, 6)
69 self.assertEqual(ev.ident, 1)
70 self.assertEqual(ev.filter, 2)
71 self.assertEqual(ev.flags, 3)
72 self.assertEqual(ev.fflags, 4)
73 self.assertEqual(ev.data, 5)
74 self.assertEqual(ev.udata, 6)
75 self.assertEqual(ev, ev)
76 self.assertNotEqual(ev, other)
77
Antoine Pitroud83f1e62009-11-04 21:10:38 +000078 bignum = sys.maxsize * 2 + 1
79 ev = select.kevent(bignum, 1, 2, 3, sys.maxsize, bignum)
80 self.assertEqual(ev.ident, bignum)
81 self.assertEqual(ev.filter, 1)
82 self.assertEqual(ev.flags, 2)
83 self.assertEqual(ev.fflags, 3)
84 self.assertEqual(ev.data, sys.maxsize)
85 self.assertEqual(ev.udata, bignum)
86 self.assertEqual(ev, ev)
87 self.assertNotEqual(ev, other)
88
Christian Heimes4fbc72b2008-03-22 00:47:35 +000089 def test_queue_event(self):
90 serverSocket = socket.socket()
91 serverSocket.bind(('127.0.0.1', 0))
92 serverSocket.listen(1)
93 client = socket.socket()
94 client.setblocking(False)
95 try:
96 client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
Andrew Svetlov0832af62012-12-18 23:10:48 +020097 except OSError as e:
Ezio Melottib3aedd42010-11-20 19:04:17 +000098 self.assertEqual(e.args[0], errno.EINPROGRESS)
Christian Heimes4fbc72b2008-03-22 00:47:35 +000099 else:
100 #raise AssertionError("Connect should have raised EINPROGRESS")
101 pass # FreeBSD doesn't raise an exception here
102 server, addr = serverSocket.accept()
103
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000104 kq = select.kqueue()
105 kq2 = select.kqueue.fromfd(kq.fileno())
106
107 ev = select.kevent(server.fileno(),
108 select.KQ_FILTER_WRITE,
109 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
110 kq.control([ev], 0)
111 ev = select.kevent(server.fileno(),
112 select.KQ_FILTER_READ,
113 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
114 kq.control([ev], 0)
115 ev = select.kevent(client.fileno(),
116 select.KQ_FILTER_WRITE,
117 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
118 kq2.control([ev], 0)
119 ev = select.kevent(client.fileno(),
120 select.KQ_FILTER_READ,
121 select.KQ_EV_ADD | select.KQ_EV_ENABLE)
122 kq2.control([ev], 0)
123
124 events = kq.control(None, 4, 1)
Charles-Francois Natali7a03e2d2013-03-31 20:36:57 +0200125 events = set((e.ident, e.filter) for e in events)
126 self.assertEqual(events, set([
127 (client.fileno(), select.KQ_FILTER_WRITE),
128 (server.fileno(), select.KQ_FILTER_WRITE)]))
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000129
130 client.send(b"Hello!")
131 server.send(b"world!!!")
132
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000133 # We may need to call it several times
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000134 for i in range(10):
135 events = kq.control(None, 4, 1)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000136 if len(events) == 4:
137 break
Mark Dickinson3dfe55b2009-01-24 16:22:21 +0000138 time.sleep(1.0)
139 else:
140 self.fail('timeout waiting for event notifications')
141
Charles-Francois Natali7a03e2d2013-03-31 20:36:57 +0200142 events = set((e.ident, e.filter) for e in events)
143 self.assertEqual(events, set([
144 (client.fileno(), select.KQ_FILTER_WRITE),
145 (client.fileno(), select.KQ_FILTER_READ),
146 (server.fileno(), select.KQ_FILTER_WRITE),
147 (server.fileno(), select.KQ_FILTER_READ)]))
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000148
149 # Remove completely client, and server read part
150 ev = select.kevent(client.fileno(),
151 select.KQ_FILTER_WRITE,
152 select.KQ_EV_DELETE)
153 kq.control([ev], 0)
154 ev = select.kevent(client.fileno(),
155 select.KQ_FILTER_READ,
156 select.KQ_EV_DELETE)
157 kq.control([ev], 0)
158 ev = select.kevent(server.fileno(),
159 select.KQ_FILTER_READ,
160 select.KQ_EV_DELETE)
161 kq.control([ev], 0, 0)
162
163 events = kq.control([], 4, 0.99)
Charles-Francois Natali7a03e2d2013-03-31 20:36:57 +0200164 events = set((e.ident, e.filter) for e in events)
165 self.assertEqual(events, set([
166 (server.fileno(), select.KQ_FILTER_WRITE)]))
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000167
168 client.close()
169 server.close()
170 serverSocket.close()
171
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000172 def testPair(self):
173 kq = select.kqueue()
174 a, b = socket.socketpair()
175
176 a.send(b'foo')
177 event1 = select.kevent(a, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
178 event2 = select.kevent(b, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
179 r = kq.control([event1, event2], 1, 1)
180 self.assertTrue(r)
181 self.assertFalse(r[0].flags & select.KQ_EV_ERROR)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000182 self.assertEqual(b.recv(r[0].data), b'foo')
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000183
184 a.close()
185 b.close()
186 kq.close()
187
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000188def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000189 support.run_unittest(TestKQueue)
Christian Heimes4fbc72b2008-03-22 00:47:35 +0000190
191if __name__ == "__main__":
192 test_main()