1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehTests for kqueue wrapper.
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport socket
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport errno
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport time
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport select
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test import test_support
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif not hasattr(select, "kqueue"):
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    raise unittest.SkipTest("test works only on BSD")
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestKQueue(unittest.TestCase):
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_create_queue(self):
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq = select.kqueue()
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(kq.fileno() > 0, kq.fileno())
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(not kq.closed)
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.close()
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(kq.closed)
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ValueError, kq.fileno)
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_create_event(self):
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        fd = sys.stderr.fileno()
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(fd)
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        other = select.kevent(1000)
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.ident, fd)
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.filter, select.KQ_FILTER_READ)
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.flags, select.KQ_EV_ADD)
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.fflags, 0)
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.data, 0)
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.udata, 0)
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev, ev)
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertNotEqual(ev, other)
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(cmp(ev, other), -1)
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(ev < other)
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(other >= ev)
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, cmp, ev, None)
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, cmp, ev, 1)
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, cmp, ev, "ev")
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(fd, select.KQ_FILTER_WRITE)
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.ident, fd)
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.flags, select.KQ_EV_ADD)
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.fflags, 0)
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.data, 0)
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.udata, 0)
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev, ev)
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertNotEqual(ev, other)
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(fd, select.KQ_FILTER_WRITE, select.KQ_EV_ONESHOT)
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.ident, fd)
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.filter, select.KQ_FILTER_WRITE)
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.flags, select.KQ_EV_ONESHOT)
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.fflags, 0)
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.data, 0)
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.udata, 0)
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev, ev)
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertNotEqual(ev, other)
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(1, 2, 3, 4, 5, 6)
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.ident, 1)
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.filter, 2)
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.flags, 3)
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.fflags, 4)
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.data, 5)
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.udata, 6)
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev, ev)
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertNotEqual(ev, other)
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        bignum = sys.maxsize * 2 + 1
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(bignum, 1, 2, 3, sys.maxsize, bignum)
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.ident, bignum)
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.filter, 1)
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.flags, 2)
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.fflags, 3)
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.data, sys.maxsize)
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev.udata, bignum)
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(ev, ev)
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertNotEqual(ev, other)
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_queue_event(self):
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        serverSocket = socket.socket()
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        serverSocket.bind(('127.0.0.1', 0))
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        serverSocket.listen(1)
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        client = socket.socket()
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        client.setblocking(False)
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except socket.error, e:
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(e.args[0], errno.EINPROGRESS)
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            #raise AssertionError("Connect should have raised EINPROGRESS")
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            pass # FreeBSD doesn't raise an exception here
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        server, addr = serverSocket.accept()
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq = select.kqueue()
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq2 = select.kqueue.fromfd(kq.fileno())
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(server.fileno(),
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_WRITE,
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_ADD | select.KQ_EV_ENABLE)
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.control([ev], 0)
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(server.fileno(),
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_READ,
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_ADD | select.KQ_EV_ENABLE)
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.control([ev], 0)
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(client.fileno(),
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_WRITE,
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_ADD | select.KQ_EV_ENABLE)
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq2.control([ev], 0)
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(client.fileno(),
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_READ,
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_ADD | select.KQ_EV_ENABLE)
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq2.control([ev], 0)
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        events = kq.control(None, 4, 1)
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        events = set((e.ident, e.filter) for e in events)
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(events, set([
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (client.fileno(), select.KQ_FILTER_WRITE),
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (server.fileno(), select.KQ_FILTER_WRITE)]))
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        client.send("Hello!")
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        server.send("world!!!")
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # We may need to call it several times
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for i in range(10):
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            events = kq.control(None, 4, 1)
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if len(events) == 4:
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                break
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            time.sleep(1.0)
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.fail('timeout waiting for event notifications')
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        events = set((e.ident, e.filter) for e in events)
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(events, set([
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (client.fileno(), select.KQ_FILTER_WRITE),
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (client.fileno(), select.KQ_FILTER_READ),
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (server.fileno(), select.KQ_FILTER_WRITE),
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (server.fileno(), select.KQ_FILTER_READ)]))
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Remove completely client, and server read part
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(client.fileno(),
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_WRITE,
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_DELETE)
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.control([ev], 0)
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(client.fileno(),
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_READ,
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_DELETE)
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.control([ev], 0)
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ev = select.kevent(server.fileno(),
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_FILTER_READ,
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           select.KQ_EV_DELETE)
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.control([ev], 0, 0)
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        events = kq.control([], 4, 0.99)
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        events = set((e.ident, e.filter) for e in events)
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(events, set([
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (server.fileno(), select.KQ_FILTER_WRITE)]))
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        client.close()
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        server.close()
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        serverSocket.close()
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testPair(self):
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq = select.kqueue()
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a, b = socket.socketpair()
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a.send(b'foo')
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        event1 = select.kevent(a, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        event2 = select.kevent(b, select.KQ_FILTER_READ, select.KQ_EV_ADD | select.KQ_EV_ENABLE)
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        r = kq.control([event1, event2], 1, 1)
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(r)
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertFalse(r[0].flags & select.KQ_EV_ERROR)
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(b.recv(r[0].data), b'foo')
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a.close()
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        b.close()
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        kq.close()
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main():
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_support.run_unittest(TestKQueue)
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__":
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_main()
188