1 | n/a | """Tests for proactor_events.py""" |
---|
2 | n/a | |
---|
3 | n/a | import socket |
---|
4 | n/a | import unittest |
---|
5 | n/a | from unittest import mock |
---|
6 | n/a | |
---|
7 | n/a | import asyncio |
---|
8 | n/a | from asyncio.proactor_events import BaseProactorEventLoop |
---|
9 | n/a | from asyncio.proactor_events import _ProactorSocketTransport |
---|
10 | n/a | from asyncio.proactor_events import _ProactorWritePipeTransport |
---|
11 | n/a | from asyncio.proactor_events import _ProactorDuplexPipeTransport |
---|
12 | n/a | from asyncio import test_utils |
---|
13 | n/a | |
---|
14 | n/a | |
---|
15 | n/a | def close_transport(transport): |
---|
16 | n/a | # Don't call transport.close() because the event loop and the IOCP proactor |
---|
17 | n/a | # are mocked |
---|
18 | n/a | if transport._sock is None: |
---|
19 | n/a | return |
---|
20 | n/a | transport._sock.close() |
---|
21 | n/a | transport._sock = None |
---|
22 | n/a | |
---|
23 | n/a | |
---|
24 | n/a | class ProactorSocketTransportTests(test_utils.TestCase): |
---|
25 | n/a | |
---|
26 | n/a | def setUp(self): |
---|
27 | n/a | super().setUp() |
---|
28 | n/a | self.loop = self.new_test_loop() |
---|
29 | n/a | self.addCleanup(self.loop.close) |
---|
30 | n/a | self.proactor = mock.Mock() |
---|
31 | n/a | self.loop._proactor = self.proactor |
---|
32 | n/a | self.protocol = test_utils.make_test_protocol(asyncio.Protocol) |
---|
33 | n/a | self.sock = mock.Mock(socket.socket) |
---|
34 | n/a | |
---|
35 | n/a | def socket_transport(self, waiter=None): |
---|
36 | n/a | transport = _ProactorSocketTransport(self.loop, self.sock, |
---|
37 | n/a | self.protocol, waiter=waiter) |
---|
38 | n/a | self.addCleanup(close_transport, transport) |
---|
39 | n/a | return transport |
---|
40 | n/a | |
---|
41 | n/a | def test_ctor(self): |
---|
42 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
43 | n/a | tr = self.socket_transport(waiter=fut) |
---|
44 | n/a | test_utils.run_briefly(self.loop) |
---|
45 | n/a | self.assertIsNone(fut.result()) |
---|
46 | n/a | self.protocol.connection_made(tr) |
---|
47 | n/a | self.proactor.recv.assert_called_with(self.sock, 4096) |
---|
48 | n/a | |
---|
49 | n/a | def test_loop_reading(self): |
---|
50 | n/a | tr = self.socket_transport() |
---|
51 | n/a | tr._loop_reading() |
---|
52 | n/a | self.loop._proactor.recv.assert_called_with(self.sock, 4096) |
---|
53 | n/a | self.assertFalse(self.protocol.data_received.called) |
---|
54 | n/a | self.assertFalse(self.protocol.eof_received.called) |
---|
55 | n/a | |
---|
56 | n/a | def test_loop_reading_data(self): |
---|
57 | n/a | res = asyncio.Future(loop=self.loop) |
---|
58 | n/a | res.set_result(b'data') |
---|
59 | n/a | |
---|
60 | n/a | tr = self.socket_transport() |
---|
61 | n/a | tr._read_fut = res |
---|
62 | n/a | tr._loop_reading(res) |
---|
63 | n/a | self.loop._proactor.recv.assert_called_with(self.sock, 4096) |
---|
64 | n/a | self.protocol.data_received.assert_called_with(b'data') |
---|
65 | n/a | |
---|
66 | n/a | def test_loop_reading_no_data(self): |
---|
67 | n/a | res = asyncio.Future(loop=self.loop) |
---|
68 | n/a | res.set_result(b'') |
---|
69 | n/a | |
---|
70 | n/a | tr = self.socket_transport() |
---|
71 | n/a | self.assertRaises(AssertionError, tr._loop_reading, res) |
---|
72 | n/a | |
---|
73 | n/a | tr.close = mock.Mock() |
---|
74 | n/a | tr._read_fut = res |
---|
75 | n/a | tr._loop_reading(res) |
---|
76 | n/a | self.assertFalse(self.loop._proactor.recv.called) |
---|
77 | n/a | self.assertTrue(self.protocol.eof_received.called) |
---|
78 | n/a | self.assertTrue(tr.close.called) |
---|
79 | n/a | |
---|
80 | n/a | def test_loop_reading_aborted(self): |
---|
81 | n/a | err = self.loop._proactor.recv.side_effect = ConnectionAbortedError() |
---|
82 | n/a | |
---|
83 | n/a | tr = self.socket_transport() |
---|
84 | n/a | tr._fatal_error = mock.Mock() |
---|
85 | n/a | tr._loop_reading() |
---|
86 | n/a | tr._fatal_error.assert_called_with( |
---|
87 | n/a | err, |
---|
88 | n/a | 'Fatal read error on pipe transport') |
---|
89 | n/a | |
---|
90 | n/a | def test_loop_reading_aborted_closing(self): |
---|
91 | n/a | self.loop._proactor.recv.side_effect = ConnectionAbortedError() |
---|
92 | n/a | |
---|
93 | n/a | tr = self.socket_transport() |
---|
94 | n/a | tr._closing = True |
---|
95 | n/a | tr._fatal_error = mock.Mock() |
---|
96 | n/a | tr._loop_reading() |
---|
97 | n/a | self.assertFalse(tr._fatal_error.called) |
---|
98 | n/a | |
---|
99 | n/a | def test_loop_reading_aborted_is_fatal(self): |
---|
100 | n/a | self.loop._proactor.recv.side_effect = ConnectionAbortedError() |
---|
101 | n/a | tr = self.socket_transport() |
---|
102 | n/a | tr._closing = False |
---|
103 | n/a | tr._fatal_error = mock.Mock() |
---|
104 | n/a | tr._loop_reading() |
---|
105 | n/a | self.assertTrue(tr._fatal_error.called) |
---|
106 | n/a | |
---|
107 | n/a | def test_loop_reading_conn_reset_lost(self): |
---|
108 | n/a | err = self.loop._proactor.recv.side_effect = ConnectionResetError() |
---|
109 | n/a | |
---|
110 | n/a | tr = self.socket_transport() |
---|
111 | n/a | tr._closing = False |
---|
112 | n/a | tr._fatal_error = mock.Mock() |
---|
113 | n/a | tr._force_close = mock.Mock() |
---|
114 | n/a | tr._loop_reading() |
---|
115 | n/a | self.assertFalse(tr._fatal_error.called) |
---|
116 | n/a | tr._force_close.assert_called_with(err) |
---|
117 | n/a | |
---|
118 | n/a | def test_loop_reading_exception(self): |
---|
119 | n/a | err = self.loop._proactor.recv.side_effect = (OSError()) |
---|
120 | n/a | |
---|
121 | n/a | tr = self.socket_transport() |
---|
122 | n/a | tr._fatal_error = mock.Mock() |
---|
123 | n/a | tr._loop_reading() |
---|
124 | n/a | tr._fatal_error.assert_called_with( |
---|
125 | n/a | err, |
---|
126 | n/a | 'Fatal read error on pipe transport') |
---|
127 | n/a | |
---|
128 | n/a | def test_write(self): |
---|
129 | n/a | tr = self.socket_transport() |
---|
130 | n/a | tr._loop_writing = mock.Mock() |
---|
131 | n/a | tr.write(b'data') |
---|
132 | n/a | self.assertEqual(tr._buffer, None) |
---|
133 | n/a | tr._loop_writing.assert_called_with(data=b'data') |
---|
134 | n/a | |
---|
135 | n/a | def test_write_no_data(self): |
---|
136 | n/a | tr = self.socket_transport() |
---|
137 | n/a | tr.write(b'') |
---|
138 | n/a | self.assertFalse(tr._buffer) |
---|
139 | n/a | |
---|
140 | n/a | def test_write_more(self): |
---|
141 | n/a | tr = self.socket_transport() |
---|
142 | n/a | tr._write_fut = mock.Mock() |
---|
143 | n/a | tr._loop_writing = mock.Mock() |
---|
144 | n/a | tr.write(b'data') |
---|
145 | n/a | self.assertEqual(tr._buffer, b'data') |
---|
146 | n/a | self.assertFalse(tr._loop_writing.called) |
---|
147 | n/a | |
---|
148 | n/a | def test_loop_writing(self): |
---|
149 | n/a | tr = self.socket_transport() |
---|
150 | n/a | tr._buffer = bytearray(b'data') |
---|
151 | n/a | tr._loop_writing() |
---|
152 | n/a | self.loop._proactor.send.assert_called_with(self.sock, b'data') |
---|
153 | n/a | self.loop._proactor.send.return_value.add_done_callback.\ |
---|
154 | n/a | assert_called_with(tr._loop_writing) |
---|
155 | n/a | |
---|
156 | n/a | @mock.patch('asyncio.proactor_events.logger') |
---|
157 | n/a | def test_loop_writing_err(self, m_log): |
---|
158 | n/a | err = self.loop._proactor.send.side_effect = OSError() |
---|
159 | n/a | tr = self.socket_transport() |
---|
160 | n/a | tr._fatal_error = mock.Mock() |
---|
161 | n/a | tr._buffer = [b'da', b'ta'] |
---|
162 | n/a | tr._loop_writing() |
---|
163 | n/a | tr._fatal_error.assert_called_with( |
---|
164 | n/a | err, |
---|
165 | n/a | 'Fatal write error on pipe transport') |
---|
166 | n/a | tr._conn_lost = 1 |
---|
167 | n/a | |
---|
168 | n/a | tr.write(b'data') |
---|
169 | n/a | tr.write(b'data') |
---|
170 | n/a | tr.write(b'data') |
---|
171 | n/a | tr.write(b'data') |
---|
172 | n/a | tr.write(b'data') |
---|
173 | n/a | self.assertEqual(tr._buffer, None) |
---|
174 | n/a | m_log.warning.assert_called_with('socket.send() raised exception.') |
---|
175 | n/a | |
---|
176 | n/a | def test_loop_writing_stop(self): |
---|
177 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
178 | n/a | fut.set_result(b'data') |
---|
179 | n/a | |
---|
180 | n/a | tr = self.socket_transport() |
---|
181 | n/a | tr._write_fut = fut |
---|
182 | n/a | tr._loop_writing(fut) |
---|
183 | n/a | self.assertIsNone(tr._write_fut) |
---|
184 | n/a | |
---|
185 | n/a | def test_loop_writing_closing(self): |
---|
186 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
187 | n/a | fut.set_result(1) |
---|
188 | n/a | |
---|
189 | n/a | tr = self.socket_transport() |
---|
190 | n/a | tr._write_fut = fut |
---|
191 | n/a | tr.close() |
---|
192 | n/a | tr._loop_writing(fut) |
---|
193 | n/a | self.assertIsNone(tr._write_fut) |
---|
194 | n/a | test_utils.run_briefly(self.loop) |
---|
195 | n/a | self.protocol.connection_lost.assert_called_with(None) |
---|
196 | n/a | |
---|
197 | n/a | def test_abort(self): |
---|
198 | n/a | tr = self.socket_transport() |
---|
199 | n/a | tr._force_close = mock.Mock() |
---|
200 | n/a | tr.abort() |
---|
201 | n/a | tr._force_close.assert_called_with(None) |
---|
202 | n/a | |
---|
203 | n/a | def test_close(self): |
---|
204 | n/a | tr = self.socket_transport() |
---|
205 | n/a | tr.close() |
---|
206 | n/a | test_utils.run_briefly(self.loop) |
---|
207 | n/a | self.protocol.connection_lost.assert_called_with(None) |
---|
208 | n/a | self.assertTrue(tr.is_closing()) |
---|
209 | n/a | self.assertEqual(tr._conn_lost, 1) |
---|
210 | n/a | |
---|
211 | n/a | self.protocol.connection_lost.reset_mock() |
---|
212 | n/a | tr.close() |
---|
213 | n/a | test_utils.run_briefly(self.loop) |
---|
214 | n/a | self.assertFalse(self.protocol.connection_lost.called) |
---|
215 | n/a | |
---|
216 | n/a | def test_close_write_fut(self): |
---|
217 | n/a | tr = self.socket_transport() |
---|
218 | n/a | tr._write_fut = mock.Mock() |
---|
219 | n/a | tr.close() |
---|
220 | n/a | test_utils.run_briefly(self.loop) |
---|
221 | n/a | self.assertFalse(self.protocol.connection_lost.called) |
---|
222 | n/a | |
---|
223 | n/a | def test_close_buffer(self): |
---|
224 | n/a | tr = self.socket_transport() |
---|
225 | n/a | tr._buffer = [b'data'] |
---|
226 | n/a | tr.close() |
---|
227 | n/a | test_utils.run_briefly(self.loop) |
---|
228 | n/a | self.assertFalse(self.protocol.connection_lost.called) |
---|
229 | n/a | |
---|
230 | n/a | @mock.patch('asyncio.base_events.logger') |
---|
231 | n/a | def test_fatal_error(self, m_logging): |
---|
232 | n/a | tr = self.socket_transport() |
---|
233 | n/a | tr._force_close = mock.Mock() |
---|
234 | n/a | tr._fatal_error(None) |
---|
235 | n/a | self.assertTrue(tr._force_close.called) |
---|
236 | n/a | self.assertTrue(m_logging.error.called) |
---|
237 | n/a | |
---|
238 | n/a | def test_force_close(self): |
---|
239 | n/a | tr = self.socket_transport() |
---|
240 | n/a | tr._buffer = [b'data'] |
---|
241 | n/a | read_fut = tr._read_fut = mock.Mock() |
---|
242 | n/a | write_fut = tr._write_fut = mock.Mock() |
---|
243 | n/a | tr._force_close(None) |
---|
244 | n/a | |
---|
245 | n/a | read_fut.cancel.assert_called_with() |
---|
246 | n/a | write_fut.cancel.assert_called_with() |
---|
247 | n/a | test_utils.run_briefly(self.loop) |
---|
248 | n/a | self.protocol.connection_lost.assert_called_with(None) |
---|
249 | n/a | self.assertEqual(None, tr._buffer) |
---|
250 | n/a | self.assertEqual(tr._conn_lost, 1) |
---|
251 | n/a | |
---|
252 | n/a | def test_force_close_idempotent(self): |
---|
253 | n/a | tr = self.socket_transport() |
---|
254 | n/a | tr._closing = True |
---|
255 | n/a | tr._force_close(None) |
---|
256 | n/a | test_utils.run_briefly(self.loop) |
---|
257 | n/a | self.assertFalse(self.protocol.connection_lost.called) |
---|
258 | n/a | |
---|
259 | n/a | def test_fatal_error_2(self): |
---|
260 | n/a | tr = self.socket_transport() |
---|
261 | n/a | tr._buffer = [b'data'] |
---|
262 | n/a | tr._force_close(None) |
---|
263 | n/a | |
---|
264 | n/a | test_utils.run_briefly(self.loop) |
---|
265 | n/a | self.protocol.connection_lost.assert_called_with(None) |
---|
266 | n/a | self.assertEqual(None, tr._buffer) |
---|
267 | n/a | |
---|
268 | n/a | def test_call_connection_lost(self): |
---|
269 | n/a | tr = self.socket_transport() |
---|
270 | n/a | tr._call_connection_lost(None) |
---|
271 | n/a | self.assertTrue(self.protocol.connection_lost.called) |
---|
272 | n/a | self.assertTrue(self.sock.close.called) |
---|
273 | n/a | |
---|
274 | n/a | def test_write_eof(self): |
---|
275 | n/a | tr = self.socket_transport() |
---|
276 | n/a | self.assertTrue(tr.can_write_eof()) |
---|
277 | n/a | tr.write_eof() |
---|
278 | n/a | self.sock.shutdown.assert_called_with(socket.SHUT_WR) |
---|
279 | n/a | tr.write_eof() |
---|
280 | n/a | self.assertEqual(self.sock.shutdown.call_count, 1) |
---|
281 | n/a | tr.close() |
---|
282 | n/a | |
---|
283 | n/a | def test_write_eof_buffer(self): |
---|
284 | n/a | tr = self.socket_transport() |
---|
285 | n/a | f = asyncio.Future(loop=self.loop) |
---|
286 | n/a | tr._loop._proactor.send.return_value = f |
---|
287 | n/a | tr.write(b'data') |
---|
288 | n/a | tr.write_eof() |
---|
289 | n/a | self.assertTrue(tr._eof_written) |
---|
290 | n/a | self.assertFalse(self.sock.shutdown.called) |
---|
291 | n/a | tr._loop._proactor.send.assert_called_with(self.sock, b'data') |
---|
292 | n/a | f.set_result(4) |
---|
293 | n/a | self.loop._run_once() |
---|
294 | n/a | self.sock.shutdown.assert_called_with(socket.SHUT_WR) |
---|
295 | n/a | tr.close() |
---|
296 | n/a | |
---|
297 | n/a | def test_write_eof_write_pipe(self): |
---|
298 | n/a | tr = _ProactorWritePipeTransport( |
---|
299 | n/a | self.loop, self.sock, self.protocol) |
---|
300 | n/a | self.assertTrue(tr.can_write_eof()) |
---|
301 | n/a | tr.write_eof() |
---|
302 | n/a | self.assertTrue(tr.is_closing()) |
---|
303 | n/a | self.loop._run_once() |
---|
304 | n/a | self.assertTrue(self.sock.close.called) |
---|
305 | n/a | tr.close() |
---|
306 | n/a | |
---|
307 | n/a | def test_write_eof_buffer_write_pipe(self): |
---|
308 | n/a | tr = _ProactorWritePipeTransport(self.loop, self.sock, self.protocol) |
---|
309 | n/a | f = asyncio.Future(loop=self.loop) |
---|
310 | n/a | tr._loop._proactor.send.return_value = f |
---|
311 | n/a | tr.write(b'data') |
---|
312 | n/a | tr.write_eof() |
---|
313 | n/a | self.assertTrue(tr.is_closing()) |
---|
314 | n/a | self.assertFalse(self.sock.shutdown.called) |
---|
315 | n/a | tr._loop._proactor.send.assert_called_with(self.sock, b'data') |
---|
316 | n/a | f.set_result(4) |
---|
317 | n/a | self.loop._run_once() |
---|
318 | n/a | self.loop._run_once() |
---|
319 | n/a | self.assertTrue(self.sock.close.called) |
---|
320 | n/a | tr.close() |
---|
321 | n/a | |
---|
322 | n/a | def test_write_eof_duplex_pipe(self): |
---|
323 | n/a | tr = _ProactorDuplexPipeTransport( |
---|
324 | n/a | self.loop, self.sock, self.protocol) |
---|
325 | n/a | self.assertFalse(tr.can_write_eof()) |
---|
326 | n/a | with self.assertRaises(NotImplementedError): |
---|
327 | n/a | tr.write_eof() |
---|
328 | n/a | close_transport(tr) |
---|
329 | n/a | |
---|
330 | n/a | def test_pause_resume_reading(self): |
---|
331 | n/a | tr = self.socket_transport() |
---|
332 | n/a | futures = [] |
---|
333 | n/a | for msg in [b'data1', b'data2', b'data3', b'data4', b'']: |
---|
334 | n/a | f = asyncio.Future(loop=self.loop) |
---|
335 | n/a | f.set_result(msg) |
---|
336 | n/a | futures.append(f) |
---|
337 | n/a | self.loop._proactor.recv.side_effect = futures |
---|
338 | n/a | self.loop._run_once() |
---|
339 | n/a | self.assertFalse(tr._paused) |
---|
340 | n/a | self.loop._run_once() |
---|
341 | n/a | self.protocol.data_received.assert_called_with(b'data1') |
---|
342 | n/a | self.loop._run_once() |
---|
343 | n/a | self.protocol.data_received.assert_called_with(b'data2') |
---|
344 | n/a | tr.pause_reading() |
---|
345 | n/a | self.assertTrue(tr._paused) |
---|
346 | n/a | for i in range(10): |
---|
347 | n/a | self.loop._run_once() |
---|
348 | n/a | self.protocol.data_received.assert_called_with(b'data2') |
---|
349 | n/a | tr.resume_reading() |
---|
350 | n/a | self.assertFalse(tr._paused) |
---|
351 | n/a | self.loop._run_once() |
---|
352 | n/a | self.protocol.data_received.assert_called_with(b'data3') |
---|
353 | n/a | self.loop._run_once() |
---|
354 | n/a | self.protocol.data_received.assert_called_with(b'data4') |
---|
355 | n/a | tr.close() |
---|
356 | n/a | |
---|
357 | n/a | |
---|
358 | n/a | def pause_writing_transport(self, high): |
---|
359 | n/a | tr = self.socket_transport() |
---|
360 | n/a | tr.set_write_buffer_limits(high=high) |
---|
361 | n/a | |
---|
362 | n/a | self.assertEqual(tr.get_write_buffer_size(), 0) |
---|
363 | n/a | self.assertFalse(self.protocol.pause_writing.called) |
---|
364 | n/a | self.assertFalse(self.protocol.resume_writing.called) |
---|
365 | n/a | return tr |
---|
366 | n/a | |
---|
367 | n/a | def test_pause_resume_writing(self): |
---|
368 | n/a | tr = self.pause_writing_transport(high=4) |
---|
369 | n/a | |
---|
370 | n/a | # write a large chunk, must pause writing |
---|
371 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
372 | n/a | self.loop._proactor.send.return_value = fut |
---|
373 | n/a | tr.write(b'large data') |
---|
374 | n/a | self.loop._run_once() |
---|
375 | n/a | self.assertTrue(self.protocol.pause_writing.called) |
---|
376 | n/a | |
---|
377 | n/a | # flush the buffer |
---|
378 | n/a | fut.set_result(None) |
---|
379 | n/a | self.loop._run_once() |
---|
380 | n/a | self.assertEqual(tr.get_write_buffer_size(), 0) |
---|
381 | n/a | self.assertTrue(self.protocol.resume_writing.called) |
---|
382 | n/a | |
---|
383 | n/a | def test_pause_writing_2write(self): |
---|
384 | n/a | tr = self.pause_writing_transport(high=4) |
---|
385 | n/a | |
---|
386 | n/a | # first short write, the buffer is not full (3 <= 4) |
---|
387 | n/a | fut1 = asyncio.Future(loop=self.loop) |
---|
388 | n/a | self.loop._proactor.send.return_value = fut1 |
---|
389 | n/a | tr.write(b'123') |
---|
390 | n/a | self.loop._run_once() |
---|
391 | n/a | self.assertEqual(tr.get_write_buffer_size(), 3) |
---|
392 | n/a | self.assertFalse(self.protocol.pause_writing.called) |
---|
393 | n/a | |
---|
394 | n/a | # fill the buffer, must pause writing (6 > 4) |
---|
395 | n/a | tr.write(b'abc') |
---|
396 | n/a | self.loop._run_once() |
---|
397 | n/a | self.assertEqual(tr.get_write_buffer_size(), 6) |
---|
398 | n/a | self.assertTrue(self.protocol.pause_writing.called) |
---|
399 | n/a | |
---|
400 | n/a | def test_pause_writing_3write(self): |
---|
401 | n/a | tr = self.pause_writing_transport(high=4) |
---|
402 | n/a | |
---|
403 | n/a | # first short write, the buffer is not full (1 <= 4) |
---|
404 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
405 | n/a | self.loop._proactor.send.return_value = fut |
---|
406 | n/a | tr.write(b'1') |
---|
407 | n/a | self.loop._run_once() |
---|
408 | n/a | self.assertEqual(tr.get_write_buffer_size(), 1) |
---|
409 | n/a | self.assertFalse(self.protocol.pause_writing.called) |
---|
410 | n/a | |
---|
411 | n/a | # second short write, the buffer is not full (3 <= 4) |
---|
412 | n/a | tr.write(b'23') |
---|
413 | n/a | self.loop._run_once() |
---|
414 | n/a | self.assertEqual(tr.get_write_buffer_size(), 3) |
---|
415 | n/a | self.assertFalse(self.protocol.pause_writing.called) |
---|
416 | n/a | |
---|
417 | n/a | # fill the buffer, must pause writing (6 > 4) |
---|
418 | n/a | tr.write(b'abc') |
---|
419 | n/a | self.loop._run_once() |
---|
420 | n/a | self.assertEqual(tr.get_write_buffer_size(), 6) |
---|
421 | n/a | self.assertTrue(self.protocol.pause_writing.called) |
---|
422 | n/a | |
---|
423 | n/a | def test_dont_pause_writing(self): |
---|
424 | n/a | tr = self.pause_writing_transport(high=4) |
---|
425 | n/a | |
---|
426 | n/a | # write a large chunk which completes immedialty, |
---|
427 | n/a | # it should not pause writing |
---|
428 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
429 | n/a | fut.set_result(None) |
---|
430 | n/a | self.loop._proactor.send.return_value = fut |
---|
431 | n/a | tr.write(b'very large data') |
---|
432 | n/a | self.loop._run_once() |
---|
433 | n/a | self.assertEqual(tr.get_write_buffer_size(), 0) |
---|
434 | n/a | self.assertFalse(self.protocol.pause_writing.called) |
---|
435 | n/a | |
---|
436 | n/a | |
---|
437 | n/a | class BaseProactorEventLoopTests(test_utils.TestCase): |
---|
438 | n/a | |
---|
439 | n/a | def setUp(self): |
---|
440 | n/a | super().setUp() |
---|
441 | n/a | |
---|
442 | n/a | self.sock = test_utils.mock_nonblocking_socket() |
---|
443 | n/a | self.proactor = mock.Mock() |
---|
444 | n/a | |
---|
445 | n/a | self.ssock, self.csock = mock.Mock(), mock.Mock() |
---|
446 | n/a | |
---|
447 | n/a | class EventLoop(BaseProactorEventLoop): |
---|
448 | n/a | def _socketpair(s): |
---|
449 | n/a | return (self.ssock, self.csock) |
---|
450 | n/a | |
---|
451 | n/a | self.loop = EventLoop(self.proactor) |
---|
452 | n/a | self.set_event_loop(self.loop) |
---|
453 | n/a | |
---|
454 | n/a | @mock.patch.object(BaseProactorEventLoop, 'call_soon') |
---|
455 | n/a | @mock.patch.object(BaseProactorEventLoop, '_socketpair') |
---|
456 | n/a | def test_ctor(self, socketpair, call_soon): |
---|
457 | n/a | ssock, csock = socketpair.return_value = ( |
---|
458 | n/a | mock.Mock(), mock.Mock()) |
---|
459 | n/a | loop = BaseProactorEventLoop(self.proactor) |
---|
460 | n/a | self.assertIs(loop._ssock, ssock) |
---|
461 | n/a | self.assertIs(loop._csock, csock) |
---|
462 | n/a | self.assertEqual(loop._internal_fds, 1) |
---|
463 | n/a | call_soon.assert_called_with(loop._loop_self_reading) |
---|
464 | n/a | loop.close() |
---|
465 | n/a | |
---|
466 | n/a | def test_close_self_pipe(self): |
---|
467 | n/a | self.loop._close_self_pipe() |
---|
468 | n/a | self.assertEqual(self.loop._internal_fds, 0) |
---|
469 | n/a | self.assertTrue(self.ssock.close.called) |
---|
470 | n/a | self.assertTrue(self.csock.close.called) |
---|
471 | n/a | self.assertIsNone(self.loop._ssock) |
---|
472 | n/a | self.assertIsNone(self.loop._csock) |
---|
473 | n/a | |
---|
474 | n/a | # Don't call close(): _close_self_pipe() cannot be called twice |
---|
475 | n/a | self.loop._closed = True |
---|
476 | n/a | |
---|
477 | n/a | def test_close(self): |
---|
478 | n/a | self.loop._close_self_pipe = mock.Mock() |
---|
479 | n/a | self.loop.close() |
---|
480 | n/a | self.assertTrue(self.loop._close_self_pipe.called) |
---|
481 | n/a | self.assertTrue(self.proactor.close.called) |
---|
482 | n/a | self.assertIsNone(self.loop._proactor) |
---|
483 | n/a | |
---|
484 | n/a | self.loop._close_self_pipe.reset_mock() |
---|
485 | n/a | self.loop.close() |
---|
486 | n/a | self.assertFalse(self.loop._close_self_pipe.called) |
---|
487 | n/a | |
---|
488 | n/a | def test_sock_recv(self): |
---|
489 | n/a | self.loop.sock_recv(self.sock, 1024) |
---|
490 | n/a | self.proactor.recv.assert_called_with(self.sock, 1024) |
---|
491 | n/a | |
---|
492 | n/a | def test_sock_sendall(self): |
---|
493 | n/a | self.loop.sock_sendall(self.sock, b'data') |
---|
494 | n/a | self.proactor.send.assert_called_with(self.sock, b'data') |
---|
495 | n/a | |
---|
496 | n/a | def test_sock_connect(self): |
---|
497 | n/a | self.loop.sock_connect(self.sock, ('1.2.3.4', 123)) |
---|
498 | n/a | self.proactor.connect.assert_called_with(self.sock, ('1.2.3.4', 123)) |
---|
499 | n/a | |
---|
500 | n/a | def test_sock_accept(self): |
---|
501 | n/a | self.loop.sock_accept(self.sock) |
---|
502 | n/a | self.proactor.accept.assert_called_with(self.sock) |
---|
503 | n/a | |
---|
504 | n/a | def test_socketpair(self): |
---|
505 | n/a | class EventLoop(BaseProactorEventLoop): |
---|
506 | n/a | # override the destructor to not log a ResourceWarning |
---|
507 | n/a | def __del__(self): |
---|
508 | n/a | pass |
---|
509 | n/a | self.assertRaises( |
---|
510 | n/a | NotImplementedError, EventLoop, self.proactor) |
---|
511 | n/a | |
---|
512 | n/a | def test_make_socket_transport(self): |
---|
513 | n/a | tr = self.loop._make_socket_transport(self.sock, asyncio.Protocol()) |
---|
514 | n/a | self.assertIsInstance(tr, _ProactorSocketTransport) |
---|
515 | n/a | close_transport(tr) |
---|
516 | n/a | |
---|
517 | n/a | def test_loop_self_reading(self): |
---|
518 | n/a | self.loop._loop_self_reading() |
---|
519 | n/a | self.proactor.recv.assert_called_with(self.ssock, 4096) |
---|
520 | n/a | self.proactor.recv.return_value.add_done_callback.assert_called_with( |
---|
521 | n/a | self.loop._loop_self_reading) |
---|
522 | n/a | |
---|
523 | n/a | def test_loop_self_reading_fut(self): |
---|
524 | n/a | fut = mock.Mock() |
---|
525 | n/a | self.loop._loop_self_reading(fut) |
---|
526 | n/a | self.assertTrue(fut.result.called) |
---|
527 | n/a | self.proactor.recv.assert_called_with(self.ssock, 4096) |
---|
528 | n/a | self.proactor.recv.return_value.add_done_callback.assert_called_with( |
---|
529 | n/a | self.loop._loop_self_reading) |
---|
530 | n/a | |
---|
531 | n/a | def test_loop_self_reading_exception(self): |
---|
532 | n/a | self.loop.close = mock.Mock() |
---|
533 | n/a | self.loop.call_exception_handler = mock.Mock() |
---|
534 | n/a | self.proactor.recv.side_effect = OSError() |
---|
535 | n/a | self.loop._loop_self_reading() |
---|
536 | n/a | self.assertTrue(self.loop.call_exception_handler.called) |
---|
537 | n/a | |
---|
538 | n/a | def test_write_to_self(self): |
---|
539 | n/a | self.loop._write_to_self() |
---|
540 | n/a | self.csock.send.assert_called_with(b'\0') |
---|
541 | n/a | |
---|
542 | n/a | def test_process_events(self): |
---|
543 | n/a | self.loop._process_events([]) |
---|
544 | n/a | |
---|
545 | n/a | @mock.patch('asyncio.base_events.logger') |
---|
546 | n/a | def test_create_server(self, m_log): |
---|
547 | n/a | pf = mock.Mock() |
---|
548 | n/a | call_soon = self.loop.call_soon = mock.Mock() |
---|
549 | n/a | |
---|
550 | n/a | self.loop._start_serving(pf, self.sock) |
---|
551 | n/a | self.assertTrue(call_soon.called) |
---|
552 | n/a | |
---|
553 | n/a | # callback |
---|
554 | n/a | loop = call_soon.call_args[0][0] |
---|
555 | n/a | loop() |
---|
556 | n/a | self.proactor.accept.assert_called_with(self.sock) |
---|
557 | n/a | |
---|
558 | n/a | # conn |
---|
559 | n/a | fut = mock.Mock() |
---|
560 | n/a | fut.result.return_value = (mock.Mock(), mock.Mock()) |
---|
561 | n/a | |
---|
562 | n/a | make_tr = self.loop._make_socket_transport = mock.Mock() |
---|
563 | n/a | loop(fut) |
---|
564 | n/a | self.assertTrue(fut.result.called) |
---|
565 | n/a | self.assertTrue(make_tr.called) |
---|
566 | n/a | |
---|
567 | n/a | # exception |
---|
568 | n/a | fut.result.side_effect = OSError() |
---|
569 | n/a | loop(fut) |
---|
570 | n/a | self.assertTrue(self.sock.close.called) |
---|
571 | n/a | self.assertTrue(m_log.error.called) |
---|
572 | n/a | |
---|
573 | n/a | def test_create_server_cancel(self): |
---|
574 | n/a | pf = mock.Mock() |
---|
575 | n/a | call_soon = self.loop.call_soon = mock.Mock() |
---|
576 | n/a | |
---|
577 | n/a | self.loop._start_serving(pf, self.sock) |
---|
578 | n/a | loop = call_soon.call_args[0][0] |
---|
579 | n/a | |
---|
580 | n/a | # cancelled |
---|
581 | n/a | fut = asyncio.Future(loop=self.loop) |
---|
582 | n/a | fut.cancel() |
---|
583 | n/a | loop(fut) |
---|
584 | n/a | self.assertTrue(self.sock.close.called) |
---|
585 | n/a | |
---|
586 | n/a | def test_stop_serving(self): |
---|
587 | n/a | sock = mock.Mock() |
---|
588 | n/a | self.loop._stop_serving(sock) |
---|
589 | n/a | self.assertTrue(sock.close.called) |
---|
590 | n/a | self.proactor._stop_serving.assert_called_with(sock) |
---|
591 | n/a | |
---|
592 | n/a | |
---|
593 | n/a | if __name__ == '__main__': |
---|
594 | n/a | unittest.main() |
---|