1 """Tests for base_events.py""" 2 3 import errno 4 import logging 5 import math 6 import os 7 import socket 8 import sys 9 import threading 10 import time 11 import unittest 12 from unittest import mock 13 14 import asyncio 15 from asyncio import base_events 16 from asyncio import constants 17 from asyncio import test_utils 18 try: 19 from test import support 20 except ImportError: 21 from asyncio import test_support as support 22 try: 23 from test.support.script_helper import assert_python_ok 24 except ImportError: 25 try: 26 from test.script_helper import assert_python_ok 27 except ImportError: 28 from asyncio.test_support import assert_python_ok 29 30 31 MOCK_ANY = mock.ANY 32 PY34 = sys.version_info >= (3, 4) 33 34 35 def mock_socket_module(): 36 m_socket = mock.MagicMock(spec=socket) 37 for name in ( 38 'AF_INET', 'AF_INET6', 'AF_UNSPEC', 'IPPROTO_TCP', 'IPPROTO_UDP', 39 'SOCK_STREAM', 'SOCK_DGRAM', 'SOL_SOCKET', 'SO_REUSEADDR', 'inet_pton' 40 ): 41 if hasattr(socket, name): 42 setattr(m_socket, name, getattr(socket, name)) 43 else: 44 delattr(m_socket, name) 45 46 m_socket.socket = mock.MagicMock() 47 m_socket.socket.return_value = test_utils.mock_nonblocking_socket() 48 m_socket.getaddrinfo._is_coroutine = False 49 50 return m_socket 51 52 53 def patch_socket(f): 54 return mock.patch('asyncio.base_events.socket', 55 new_callable=mock_socket_module)(f) 56 57 58 class BaseEventTests(test_utils.TestCase): 59 60 def test_ipaddr_info(self): 61 UNSPEC = socket.AF_UNSPEC 62 INET = socket.AF_INET 63 INET6 = socket.AF_INET6 64 STREAM = socket.SOCK_STREAM 65 DGRAM = socket.SOCK_DGRAM 66 TCP = socket.IPPROTO_TCP 67 UDP = socket.IPPROTO_UDP 68 69 self.assertEqual( 70 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 71 base_events._ipaddr_info('1.2.3.4', 1, INET, STREAM, TCP)) 72 73 self.assertEqual( 74 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 75 base_events._ipaddr_info(b'1.2.3.4', 1, INET, STREAM, TCP)) 76 77 self.assertEqual( 78 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 79 base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, TCP)) 80 81 self.assertEqual( 82 (INET, DGRAM, UDP, '', ('1.2.3.4', 1)), 83 base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, UDP)) 84 85 # Socket type STREAM implies TCP protocol. 86 self.assertEqual( 87 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 88 base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, 0)) 89 90 # Socket type DGRAM implies UDP protocol. 91 self.assertEqual( 92 (INET, DGRAM, UDP, '', ('1.2.3.4', 1)), 93 base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, 0)) 94 95 # No socket type. 96 self.assertIsNone( 97 base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, 0, 0)) 98 99 # IPv4 address with family IPv6. 100 self.assertIsNone( 101 base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP)) 102 103 self.assertEqual( 104 (INET6, STREAM, TCP, '', ('::3', 1)), 105 base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP)) 106 107 self.assertEqual( 108 (INET6, STREAM, TCP, '', ('::3', 1)), 109 base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP)) 110 111 # IPv6 address with family IPv4. 112 self.assertIsNone( 113 base_events._ipaddr_info('::3', 1, INET, STREAM, TCP)) 114 115 # IPv6 address with zone index. 116 self.assertIsNone( 117 base_events._ipaddr_info('::3%lo0', 1, INET6, STREAM, TCP)) 118 119 if hasattr(socket, 'SOCK_NONBLOCK'): 120 self.assertEqual( 121 None, 122 base_events._ipaddr_info( 123 '1.2.3.4', 1, INET, STREAM | socket.SOCK_NONBLOCK, TCP)) 124 125 126 def test_port_parameter_types(self): 127 # Test obscure kinds of arguments for "port". 128 INET = socket.AF_INET 129 STREAM = socket.SOCK_STREAM 130 TCP = socket.IPPROTO_TCP 131 132 self.assertEqual( 133 (INET, STREAM, TCP, '', ('1.2.3.4', 0)), 134 base_events._ipaddr_info('1.2.3.4', None, INET, STREAM, TCP)) 135 136 self.assertEqual( 137 (INET, STREAM, TCP, '', ('1.2.3.4', 0)), 138 base_events._ipaddr_info('1.2.3.4', b'', INET, STREAM, TCP)) 139 140 self.assertEqual( 141 (INET, STREAM, TCP, '', ('1.2.3.4', 0)), 142 base_events._ipaddr_info('1.2.3.4', '', INET, STREAM, TCP)) 143 144 self.assertEqual( 145 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 146 base_events._ipaddr_info('1.2.3.4', '1', INET, STREAM, TCP)) 147 148 self.assertEqual( 149 (INET, STREAM, TCP, '', ('1.2.3.4', 1)), 150 base_events._ipaddr_info('1.2.3.4', b'1', INET, STREAM, TCP)) 151 152 @patch_socket 153 def test_ipaddr_info_no_inet_pton(self, m_socket): 154 del m_socket.inet_pton 155 self.assertIsNone(base_events._ipaddr_info('1.2.3.4', 1, 156 socket.AF_INET, 157 socket.SOCK_STREAM, 158 socket.IPPROTO_TCP)) 159 160 161 class BaseEventLoopTests(test_utils.TestCase): 162 163 def setUp(self): 164 super().setUp() 165 self.loop = base_events.BaseEventLoop() 166 self.loop._selector = mock.Mock() 167 self.loop._selector.select.return_value = () 168 self.set_event_loop(self.loop) 169 170 def test_not_implemented(self): 171 m = mock.Mock() 172 self.assertRaises( 173 NotImplementedError, 174 self.loop._make_socket_transport, m, m) 175 self.assertRaises( 176 NotImplementedError, 177 self.loop._make_ssl_transport, m, m, m, m) 178 self.assertRaises( 179 NotImplementedError, 180 self.loop._make_datagram_transport, m, m) 181 self.assertRaises( 182 NotImplementedError, self.loop._process_events, []) 183 self.assertRaises( 184 NotImplementedError, self.loop._write_to_self) 185 self.assertRaises( 186 NotImplementedError, 187 self.loop._make_read_pipe_transport, m, m) 188 self.assertRaises( 189 NotImplementedError, 190 self.loop._make_write_pipe_transport, m, m) 191 gen = self.loop._make_subprocess_transport(m, m, m, m, m, m, m) 192 with self.assertRaises(NotImplementedError): 193 gen.send(None) 194 195 def test_close(self): 196 self.assertFalse(self.loop.is_closed()) 197 self.loop.close() 198 self.assertTrue(self.loop.is_closed()) 199 200 # it should be possible to call close() more than once 201 self.loop.close() 202 self.loop.close() 203 204 # operation blocked when the loop is closed 205 f = asyncio.Future(loop=self.loop) 206 self.assertRaises(RuntimeError, self.loop.run_forever) 207 self.assertRaises(RuntimeError, self.loop.run_until_complete, f) 208 209 def test__add_callback_handle(self): 210 h = asyncio.Handle(lambda: False, (), self.loop) 211 212 self.loop._add_callback(h) 213 self.assertFalse(self.loop._scheduled) 214 self.assertIn(h, self.loop._ready) 215 216 def test__add_callback_cancelled_handle(self): 217 h = asyncio.Handle(lambda: False, (), self.loop) 218 h.cancel() 219 220 self.loop._add_callback(h) 221 self.assertFalse(self.loop._scheduled) 222 self.assertFalse(self.loop._ready) 223 224 def test_set_default_executor(self): 225 executor = mock.Mock() 226 self.loop.set_default_executor(executor) 227 self.assertIs(executor, self.loop._default_executor) 228 229 def test_getnameinfo(self): 230 sockaddr = mock.Mock() 231 self.loop.run_in_executor = mock.Mock() 232 self.loop.getnameinfo(sockaddr) 233 self.assertEqual( 234 (None, socket.getnameinfo, sockaddr, 0), 235 self.loop.run_in_executor.call_args[0]) 236 237 def test_call_soon(self): 238 def cb(): 239 pass 240 241 h = self.loop.call_soon(cb) 242 self.assertEqual(h._callback, cb) 243 self.assertIsInstance(h, asyncio.Handle) 244 self.assertIn(h, self.loop._ready) 245 246 def test_call_soon_non_callable(self): 247 self.loop.set_debug(True) 248 with self.assertRaisesRegex(TypeError, 'a callable object'): 249 self.loop.call_soon(1) 250 251 def test_call_later(self): 252 def cb(): 253 pass 254 255 h = self.loop.call_later(10.0, cb) 256 self.assertIsInstance(h, asyncio.TimerHandle) 257 self.assertIn(h, self.loop._scheduled) 258 self.assertNotIn(h, self.loop._ready) 259 260 def test_call_later_negative_delays(self): 261 calls = [] 262 263 def cb(arg): 264 calls.append(arg) 265 266 self.loop._process_events = mock.Mock() 267 self.loop.call_later(-1, cb, 'a') 268 self.loop.call_later(-2, cb, 'b') 269 test_utils.run_briefly(self.loop) 270 self.assertEqual(calls, ['b', 'a']) 271 272 def test_time_and_call_at(self): 273 def cb(): 274 self.loop.stop() 275 276 self.loop._process_events = mock.Mock() 277 delay = 0.1 278 279 when = self.loop.time() + delay 280 self.loop.call_at(when, cb) 281 t0 = self.loop.time() 282 self.loop.run_forever() 283 dt = self.loop.time() - t0 284 285 # 50 ms: maximum granularity of the event loop 286 self.assertGreaterEqual(dt, delay - 0.050, dt) 287 # tolerate a difference of +800 ms because some Python buildbots 288 # are really slow 289 self.assertLessEqual(dt, 0.9, dt) 290 291 def check_thread(self, loop, debug): 292 def cb(): 293 pass 294 295 loop.set_debug(debug) 296 if debug: 297 msg = ("Non-thread-safe operation invoked on an event loop other " 298 "than the current one") 299 with self.assertRaisesRegex(RuntimeError, msg): 300 loop.call_soon(cb) 301 with self.assertRaisesRegex(RuntimeError, msg): 302 loop.call_later(60, cb) 303 with self.assertRaisesRegex(RuntimeError, msg): 304 loop.call_at(loop.time() + 60, cb) 305 else: 306 loop.call_soon(cb) 307 loop.call_later(60, cb) 308 loop.call_at(loop.time() + 60, cb) 309 310 def test_check_thread(self): 311 def check_in_thread(loop, event, debug, create_loop, fut): 312 # wait until the event loop is running 313 event.wait() 314 315 try: 316 if create_loop: 317 loop2 = base_events.BaseEventLoop() 318 try: 319 asyncio.set_event_loop(loop2) 320 self.check_thread(loop, debug) 321 finally: 322 asyncio.set_event_loop(None) 323 loop2.close() 324 else: 325 self.check_thread(loop, debug) 326 except Exception as exc: 327 loop.call_soon_threadsafe(fut.set_exception, exc) 328 else: 329 loop.call_soon_threadsafe(fut.set_result, None) 330 331 def test_thread(loop, debug, create_loop=False): 332 event = threading.Event() 333 fut = asyncio.Future(loop=loop) 334 loop.call_soon(event.set) 335 args = (loop, event, debug, create_loop, fut) 336 thread = threading.Thread(target=check_in_thread, args=args) 337 thread.start() 338 loop.run_until_complete(fut) 339 thread.join() 340 341 self.loop._process_events = mock.Mock() 342 self.loop._write_to_self = mock.Mock() 343 344 # raise RuntimeError if the thread has no event loop 345 test_thread(self.loop, True) 346 347 # check disabled if debug mode is disabled 348 test_thread(self.loop, False) 349 350 # raise RuntimeError if the event loop of the thread is not the called 351 # event loop 352 test_thread(self.loop, True, create_loop=True) 353 354 # check disabled if debug mode is disabled 355 test_thread(self.loop, False, create_loop=True) 356 357 def test_run_once_in_executor_plain(self): 358 def cb(): 359 pass 360 f = asyncio.Future(loop=self.loop) 361 executor = mock.Mock() 362 executor.submit.return_value = f 363 364 self.loop.set_default_executor(executor) 365 366 res = self.loop.run_in_executor(None, cb) 367 self.assertIs(f, res) 368 369 executor = mock.Mock() 370 executor.submit.return_value = f 371 res = self.loop.run_in_executor(executor, cb) 372 self.assertIs(f, res) 373 self.assertTrue(executor.submit.called) 374 375 f.cancel() # Don't complain about abandoned Future. 376 377 def test__run_once(self): 378 h1 = asyncio.TimerHandle(time.monotonic() + 5.0, lambda: True, (), 379 self.loop) 380 h2 = asyncio.TimerHandle(time.monotonic() + 10.0, lambda: True, (), 381 self.loop) 382 383 h1.cancel() 384 385 self.loop._process_events = mock.Mock() 386 self.loop._scheduled.append(h1) 387 self.loop._scheduled.append(h2) 388 self.loop._run_once() 389 390 t = self.loop._selector.select.call_args[0][0] 391 self.assertTrue(9.5 < t < 10.5, t) 392 self.assertEqual([h2], self.loop._scheduled) 393 self.assertTrue(self.loop._process_events.called) 394 395 def test_set_debug(self): 396 self.loop.set_debug(True) 397 self.assertTrue(self.loop.get_debug()) 398 self.loop.set_debug(False) 399 self.assertFalse(self.loop.get_debug()) 400 401 @mock.patch('asyncio.base_events.logger') 402 def test__run_once_logging(self, m_logger): 403 def slow_select(timeout): 404 # Sleep a bit longer than a second to avoid timer resolution 405 # issues. 406 time.sleep(1.1) 407 return [] 408 409 # logging needs debug flag 410 self.loop.set_debug(True) 411 412 # Log to INFO level if timeout > 1.0 sec. 413 self.loop._selector.select = slow_select 414 self.loop._process_events = mock.Mock() 415 self.loop._run_once() 416 self.assertEqual(logging.INFO, m_logger.log.call_args[0][0]) 417 418 def fast_select(timeout): 419 time.sleep(0.001) 420 return [] 421 422 self.loop._selector.select = fast_select 423 self.loop._run_once() 424 self.assertEqual(logging.DEBUG, m_logger.log.call_args[0][0]) 425 426 def test__run_once_schedule_handle(self): 427 handle = None 428 processed = False 429 430 def cb(loop): 431 nonlocal processed, handle 432 processed = True 433 handle = loop.call_soon(lambda: True) 434 435 h = asyncio.TimerHandle(time.monotonic() - 1, cb, (self.loop,), 436 self.loop) 437 438 self.loop._process_events = mock.Mock() 439 self.loop._scheduled.append(h) 440 self.loop._run_once() 441 442 self.assertTrue(processed) 443 self.assertEqual([handle], list(self.loop._ready)) 444 445 def test__run_once_cancelled_event_cleanup(self): 446 self.loop._process_events = mock.Mock() 447 448 self.assertTrue( 449 0 < base_events._MIN_CANCELLED_TIMER_HANDLES_FRACTION < 1.0) 450 451 def cb(): 452 pass 453 454 # Set up one "blocking" event that will not be cancelled to 455 # ensure later cancelled events do not make it to the head 456 # of the queue and get cleaned. 457 not_cancelled_count = 1 458 self.loop.call_later(3000, cb) 459 460 # Add less than threshold (base_events._MIN_SCHEDULED_TIMER_HANDLES) 461 # cancelled handles, ensure they aren't removed 462 463 cancelled_count = 2 464 for x in range(2): 465 h = self.loop.call_later(3600, cb) 466 h.cancel() 467 468 # Add some cancelled events that will be at head and removed 469 cancelled_count += 2 470 for x in range(2): 471 h = self.loop.call_later(100, cb) 472 h.cancel() 473 474 # This test is invalid if _MIN_SCHEDULED_TIMER_HANDLES is too low 475 self.assertLessEqual(cancelled_count + not_cancelled_count, 476 base_events._MIN_SCHEDULED_TIMER_HANDLES) 477 478 self.assertEqual(self.loop._timer_cancelled_count, cancelled_count) 479 480 self.loop._run_once() 481 482 cancelled_count -= 2 483 484 self.assertEqual(self.loop._timer_cancelled_count, cancelled_count) 485 486 self.assertEqual(len(self.loop._scheduled), 487 cancelled_count + not_cancelled_count) 488 489 # Need enough events to pass _MIN_CANCELLED_TIMER_HANDLES_FRACTION 490 # so that deletion of cancelled events will occur on next _run_once 491 add_cancel_count = int(math.ceil( 492 base_events._MIN_SCHEDULED_TIMER_HANDLES * 493 base_events._MIN_CANCELLED_TIMER_HANDLES_FRACTION)) + 1 494 495 add_not_cancel_count = max(base_events._MIN_SCHEDULED_TIMER_HANDLES - 496 add_cancel_count, 0) 497 498 # Add some events that will not be cancelled 499 not_cancelled_count += add_not_cancel_count 500 for x in range(add_not_cancel_count): 501 self.loop.call_later(3600, cb) 502 503 # Add enough cancelled events 504 cancelled_count += add_cancel_count 505 for x in range(add_cancel_count): 506 h = self.loop.call_later(3600, cb) 507 h.cancel() 508 509 # Ensure all handles are still scheduled 510 self.assertEqual(len(self.loop._scheduled), 511 cancelled_count + not_cancelled_count) 512 513 self.loop._run_once() 514 515 # Ensure cancelled events were removed 516 self.assertEqual(len(self.loop._scheduled), not_cancelled_count) 517 518 # Ensure only uncancelled events remain scheduled 519 self.assertTrue(all([not x._cancelled for x in self.loop._scheduled])) 520 521 def test_run_until_complete_type_error(self): 522 self.assertRaises(TypeError, 523 self.loop.run_until_complete, 'blah') 524 525 def test_run_until_complete_loop(self): 526 task = asyncio.Future(loop=self.loop) 527 other_loop = self.new_test_loop() 528 self.addCleanup(other_loop.close) 529 self.assertRaises(ValueError, 530 other_loop.run_until_complete, task) 531 532 def test_subprocess_exec_invalid_args(self): 533 args = [sys.executable, '-c', 'pass'] 534 535 # missing program parameter (empty args) 536 self.assertRaises(TypeError, 537 self.loop.run_until_complete, self.loop.subprocess_exec, 538 asyncio.SubprocessProtocol) 539 540 # expected multiple arguments, not a list 541 self.assertRaises(TypeError, 542 self.loop.run_until_complete, self.loop.subprocess_exec, 543 asyncio.SubprocessProtocol, args) 544 545 # program arguments must be strings, not int 546 self.assertRaises(TypeError, 547 self.loop.run_until_complete, self.loop.subprocess_exec, 548 asyncio.SubprocessProtocol, sys.executable, 123) 549 550 # universal_newlines, shell, bufsize must not be set 551 self.assertRaises(TypeError, 552 self.loop.run_until_complete, self.loop.subprocess_exec, 553 asyncio.SubprocessProtocol, *args, universal_newlines=True) 554 self.assertRaises(TypeError, 555 self.loop.run_until_complete, self.loop.subprocess_exec, 556 asyncio.SubprocessProtocol, *args, shell=True) 557 self.assertRaises(TypeError, 558 self.loop.run_until_complete, self.loop.subprocess_exec, 559 asyncio.SubprocessProtocol, *args, bufsize=4096) 560 561 def test_subprocess_shell_invalid_args(self): 562 # expected a string, not an int or a list 563 self.assertRaises(TypeError, 564 self.loop.run_until_complete, self.loop.subprocess_shell, 565 asyncio.SubprocessProtocol, 123) 566 self.assertRaises(TypeError, 567 self.loop.run_until_complete, self.loop.subprocess_shell, 568 asyncio.SubprocessProtocol, [sys.executable, '-c', 'pass']) 569 570 # universal_newlines, shell, bufsize must not be set 571 self.assertRaises(TypeError, 572 self.loop.run_until_complete, self.loop.subprocess_shell, 573 asyncio.SubprocessProtocol, 'exit 0', universal_newlines=True) 574 self.assertRaises(TypeError, 575 self.loop.run_until_complete, self.loop.subprocess_shell, 576 asyncio.SubprocessProtocol, 'exit 0', shell=True) 577 self.assertRaises(TypeError, 578 self.loop.run_until_complete, self.loop.subprocess_shell, 579 asyncio.SubprocessProtocol, 'exit 0', bufsize=4096) 580 581 def test_default_exc_handler_callback(self): 582 self.loop._process_events = mock.Mock() 583 584 def zero_error(fut): 585 fut.set_result(True) 586 1/0 587 588 # Test call_soon (events.Handle) 589 with mock.patch('asyncio.base_events.logger') as log: 590 fut = asyncio.Future(loop=self.loop) 591 self.loop.call_soon(zero_error, fut) 592 fut.add_done_callback(lambda fut: self.loop.stop()) 593 self.loop.run_forever() 594 log.error.assert_called_with( 595 test_utils.MockPattern('Exception in callback.*zero'), 596 exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) 597 598 # Test call_later (events.TimerHandle) 599 with mock.patch('asyncio.base_events.logger') as log: 600 fut = asyncio.Future(loop=self.loop) 601 self.loop.call_later(0.01, zero_error, fut) 602 fut.add_done_callback(lambda fut: self.loop.stop()) 603 self.loop.run_forever() 604 log.error.assert_called_with( 605 test_utils.MockPattern('Exception in callback.*zero'), 606 exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) 607 608 def test_default_exc_handler_coro(self): 609 self.loop._process_events = mock.Mock() 610 611 @asyncio.coroutine 612 def zero_error_coro(): 613 yield from asyncio.sleep(0.01, loop=self.loop) 614 1/0 615 616 # Test Future.__del__ 617 with mock.patch('asyncio.base_events.logger') as log: 618 fut = asyncio.ensure_future(zero_error_coro(), loop=self.loop) 619 fut.add_done_callback(lambda *args: self.loop.stop()) 620 self.loop.run_forever() 621 fut = None # Trigger Future.__del__ or futures._TracebackLogger 622 support.gc_collect() 623 if PY34: 624 # Future.__del__ in Python 3.4 logs error with 625 # an actual exception context 626 log.error.assert_called_with( 627 test_utils.MockPattern('.*exception was never retrieved'), 628 exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) 629 else: 630 # futures._TracebackLogger logs only textual traceback 631 log.error.assert_called_with( 632 test_utils.MockPattern( 633 '.*exception was never retrieved.*ZeroDiv'), 634 exc_info=False) 635 636 def test_set_exc_handler_invalid(self): 637 with self.assertRaisesRegex(TypeError, 'A callable object or None'): 638 self.loop.set_exception_handler('spam') 639 640 def test_set_exc_handler_custom(self): 641 def zero_error(): 642 1/0 643 644 def run_loop(): 645 handle = self.loop.call_soon(zero_error) 646 self.loop._run_once() 647 return handle 648 649 self.loop.set_debug(True) 650 self.loop._process_events = mock.Mock() 651 652 self.assertIsNone(self.loop.get_exception_handler()) 653 mock_handler = mock.Mock() 654 self.loop.set_exception_handler(mock_handler) 655 self.assertIs(self.loop.get_exception_handler(), mock_handler) 656 handle = run_loop() 657 mock_handler.assert_called_with(self.loop, { 658 'exception': MOCK_ANY, 659 'message': test_utils.MockPattern( 660 'Exception in callback.*zero_error'), 661 'handle': handle, 662 'source_traceback': handle._source_traceback, 663 }) 664 mock_handler.reset_mock() 665 666 self.loop.set_exception_handler(None) 667 with mock.patch('asyncio.base_events.logger') as log: 668 run_loop() 669 log.error.assert_called_with( 670 test_utils.MockPattern( 671 'Exception in callback.*zero'), 672 exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) 673 674 assert not mock_handler.called 675 676 def test_set_exc_handler_broken(self): 677 def run_loop(): 678 def zero_error(): 679 1/0 680 self.loop.call_soon(zero_error) 681 self.loop._run_once() 682 683 def handler(loop, context): 684 raise AttributeError('spam') 685 686 self.loop._process_events = mock.Mock() 687 688 self.loop.set_exception_handler(handler) 689 690 with mock.patch('asyncio.base_events.logger') as log: 691 run_loop() 692 log.error.assert_called_with( 693 test_utils.MockPattern( 694 'Unhandled error in exception handler'), 695 exc_info=(AttributeError, MOCK_ANY, MOCK_ANY)) 696 697 def test_default_exc_handler_broken(self): 698 _context = None 699 700 class Loop(base_events.BaseEventLoop): 701 702 _selector = mock.Mock() 703 _process_events = mock.Mock() 704 705 def default_exception_handler(self, context): 706 nonlocal _context 707 _context = context 708 # Simulates custom buggy "default_exception_handler" 709 raise ValueError('spam') 710 711 loop = Loop() 712 self.addCleanup(loop.close) 713 asyncio.set_event_loop(loop) 714 715 def run_loop(): 716 def zero_error(): 717 1/0 718 loop.call_soon(zero_error) 719 loop._run_once() 720 721 with mock.patch('asyncio.base_events.logger') as log: 722 run_loop() 723 log.error.assert_called_with( 724 'Exception in default exception handler', 725 exc_info=True) 726 727 def custom_handler(loop, context): 728 raise ValueError('ham') 729 730 _context = None 731 loop.set_exception_handler(custom_handler) 732 with mock.patch('asyncio.base_events.logger') as log: 733 run_loop() 734 log.error.assert_called_with( 735 test_utils.MockPattern('Exception in default exception.*' 736 'while handling.*in custom'), 737 exc_info=True) 738 739 # Check that original context was passed to default 740 # exception handler. 741 self.assertIn('context', _context) 742 self.assertIs(type(_context['context']['exception']), 743 ZeroDivisionError) 744 745 def test_set_task_factory_invalid(self): 746 with self.assertRaisesRegex( 747 TypeError, 'task factory must be a callable or None'): 748 749 self.loop.set_task_factory(1) 750 751 self.assertIsNone(self.loop.get_task_factory()) 752 753 def test_set_task_factory(self): 754 self.loop._process_events = mock.Mock() 755 756 class MyTask(asyncio.Task): 757 pass 758 759 @asyncio.coroutine 760 def coro(): 761 pass 762 763 factory = lambda loop, coro: MyTask(coro, loop=loop) 764 765 self.assertIsNone(self.loop.get_task_factory()) 766 self.loop.set_task_factory(factory) 767 self.assertIs(self.loop.get_task_factory(), factory) 768 769 task = self.loop.create_task(coro()) 770 self.assertTrue(isinstance(task, MyTask)) 771 self.loop.run_until_complete(task) 772 773 self.loop.set_task_factory(None) 774 self.assertIsNone(self.loop.get_task_factory()) 775 776 task = self.loop.create_task(coro()) 777 self.assertTrue(isinstance(task, asyncio.Task)) 778 self.assertFalse(isinstance(task, MyTask)) 779 self.loop.run_until_complete(task) 780 781 def test_env_var_debug(self): 782 code = '\n'.join(( 783 'import asyncio', 784 'loop = asyncio.get_event_loop()', 785 'print(loop.get_debug())')) 786 787 # Test with -E to not fail if the unit test was run with 788 # PYTHONASYNCIODEBUG set to a non-empty string 789 sts, stdout, stderr = assert_python_ok('-E', '-c', code) 790 self.assertEqual(stdout.rstrip(), b'False') 791 792 sts, stdout, stderr = assert_python_ok('-c', code, 793 PYTHONASYNCIODEBUG='') 794 self.assertEqual(stdout.rstrip(), b'False') 795 796 sts, stdout, stderr = assert_python_ok('-c', code, 797 PYTHONASYNCIODEBUG='1') 798 self.assertEqual(stdout.rstrip(), b'True') 799 800 sts, stdout, stderr = assert_python_ok('-E', '-c', code, 801 PYTHONASYNCIODEBUG='1') 802 self.assertEqual(stdout.rstrip(), b'False') 803 804 def test_create_task(self): 805 class MyTask(asyncio.Task): 806 pass 807 808 @asyncio.coroutine 809 def test(): 810 pass 811 812 class EventLoop(base_events.BaseEventLoop): 813 def create_task(self, coro): 814 return MyTask(coro, loop=loop) 815 816 loop = EventLoop() 817 self.set_event_loop(loop) 818 819 coro = test() 820 task = asyncio.ensure_future(coro, loop=loop) 821 self.assertIsInstance(task, MyTask) 822 823 # make warnings quiet 824 task._log_destroy_pending = False 825 coro.close() 826 827 def test_run_forever_keyboard_interrupt(self): 828 # Python issue #22601: ensure that the temporary task created by 829 # run_forever() consumes the KeyboardInterrupt and so don't log 830 # a warning 831 @asyncio.coroutine 832 def raise_keyboard_interrupt(): 833 raise KeyboardInterrupt 834 835 self.loop._process_events = mock.Mock() 836 self.loop.call_exception_handler = mock.Mock() 837 838 try: 839 self.loop.run_until_complete(raise_keyboard_interrupt()) 840 except KeyboardInterrupt: 841 pass 842 self.loop.close() 843 support.gc_collect() 844 845 self.assertFalse(self.loop.call_exception_handler.called) 846 847 def test_run_until_complete_baseexception(self): 848 # Python issue #22429: run_until_complete() must not schedule a pending 849 # call to stop() if the future raised a BaseException 850 @asyncio.coroutine 851 def raise_keyboard_interrupt(): 852 raise KeyboardInterrupt 853 854 self.loop._process_events = mock.Mock() 855 856 try: 857 self.loop.run_until_complete(raise_keyboard_interrupt()) 858 except KeyboardInterrupt: 859 pass 860 861 def func(): 862 self.loop.stop() 863 func.called = True 864 func.called = False 865 try: 866 self.loop.call_soon(func) 867 self.loop.run_forever() 868 except KeyboardInterrupt: 869 pass 870 self.assertTrue(func.called) 871 872 def test_single_selecter_event_callback_after_stopping(self): 873 # Python issue #25593: A stopped event loop may cause event callbacks 874 # to run more than once. 875 event_sentinel = object() 876 callcount = 0 877 doer = None 878 879 def proc_events(event_list): 880 nonlocal doer 881 if event_sentinel in event_list: 882 doer = self.loop.call_soon(do_event) 883 884 def do_event(): 885 nonlocal callcount 886 callcount += 1 887 self.loop.call_soon(clear_selector) 888 889 def clear_selector(): 890 doer.cancel() 891 self.loop._selector.select.return_value = () 892 893 self.loop._process_events = proc_events 894 self.loop._selector.select.return_value = (event_sentinel,) 895 896 for i in range(1, 3): 897 with self.subTest('Loop %d/2' % i): 898 self.loop.call_soon(self.loop.stop) 899 self.loop.run_forever() 900 self.assertEqual(callcount, 1) 901 902 def test_run_once(self): 903 # Simple test for test_utils.run_once(). It may seem strange 904 # to have a test for this (the function isn't even used!) but 905 # it's a de-factor standard API for library tests. This tests 906 # the idiom: loop.call_soon(loop.stop); loop.run_forever(). 907 count = 0 908 909 def callback(): 910 nonlocal count 911 count += 1 912 913 self.loop._process_events = mock.Mock() 914 self.loop.call_soon(callback) 915 test_utils.run_once(self.loop) 916 self.assertEqual(count, 1) 917 918 def test_run_forever_pre_stopped(self): 919 # Test that the old idiom for pre-stopping the loop works. 920 self.loop._process_events = mock.Mock() 921 self.loop.stop() 922 self.loop.run_forever() 923 self.loop._selector.select.assert_called_once_with(0) 924 925 926 class MyProto(asyncio.Protocol): 927 done = None 928 929 def __init__(self, create_future=False): 930 self.state = 'INITIAL' 931 self.nbytes = 0 932 if create_future: 933 self.done = asyncio.Future() 934 935 def connection_made(self, transport): 936 self.transport = transport 937 assert self.state == 'INITIAL', self.state 938 self.state = 'CONNECTED' 939 transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') 940 941 def data_received(self, data): 942 assert self.state == 'CONNECTED', self.state 943 self.nbytes += len(data) 944 945 def eof_received(self): 946 assert self.state == 'CONNECTED', self.state 947 self.state = 'EOF' 948 949 def connection_lost(self, exc): 950 assert self.state in ('CONNECTED', 'EOF'), self.state 951 self.state = 'CLOSED' 952 if self.done: 953 self.done.set_result(None) 954 955 956 class MyDatagramProto(asyncio.DatagramProtocol): 957 done = None 958 959 def __init__(self, create_future=False, loop=None): 960 self.state = 'INITIAL' 961 self.nbytes = 0 962 if create_future: 963 self.done = asyncio.Future(loop=loop) 964 965 def connection_made(self, transport): 966 self.transport = transport 967 assert self.state == 'INITIAL', self.state 968 self.state = 'INITIALIZED' 969 970 def datagram_received(self, data, addr): 971 assert self.state == 'INITIALIZED', self.state 972 self.nbytes += len(data) 973 974 def error_received(self, exc): 975 assert self.state == 'INITIALIZED', self.state 976 977 def connection_lost(self, exc): 978 assert self.state == 'INITIALIZED', self.state 979 self.state = 'CLOSED' 980 if self.done: 981 self.done.set_result(None) 982 983 984 class BaseEventLoopWithSelectorTests(test_utils.TestCase): 985 986 def setUp(self): 987 super().setUp() 988 self.loop = asyncio.new_event_loop() 989 self.set_event_loop(self.loop) 990 991 @patch_socket 992 def test_create_connection_multiple_errors(self, m_socket): 993 994 class MyProto(asyncio.Protocol): 995 pass 996 997 @asyncio.coroutine 998 def getaddrinfo(*args, **kw): 999 yield from [] 1000 return [(2, 1, 6, '', ('107.6.106.82', 80)), 1001 (2, 1, 6, '', ('107.6.106.82', 80))] 1002 1003 def getaddrinfo_task(*args, **kwds): 1004 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1005 1006 idx = -1 1007 errors = ['err1', 'err2'] 1008 1009 def _socket(*args, **kw): 1010 nonlocal idx, errors 1011 idx += 1 1012 raise OSError(errors[idx]) 1013 1014 m_socket.socket = _socket 1015 1016 self.loop.getaddrinfo = getaddrinfo_task 1017 1018 coro = self.loop.create_connection(MyProto, 'example.com', 80) 1019 with self.assertRaises(OSError) as cm: 1020 self.loop.run_until_complete(coro) 1021 1022 self.assertEqual(str(cm.exception), 'Multiple exceptions: err1, err2') 1023 1024 @patch_socket 1025 def test_create_connection_timeout(self, m_socket): 1026 # Ensure that the socket is closed on timeout 1027 sock = mock.Mock() 1028 m_socket.socket.return_value = sock 1029 1030 def getaddrinfo(*args, **kw): 1031 fut = asyncio.Future(loop=self.loop) 1032 addr = (socket.AF_INET, socket.SOCK_STREAM, 0, '', 1033 ('127.0.0.1', 80)) 1034 fut.set_result([addr]) 1035 return fut 1036 self.loop.getaddrinfo = getaddrinfo 1037 1038 with mock.patch.object(self.loop, 'sock_connect', 1039 side_effect=asyncio.TimeoutError): 1040 coro = self.loop.create_connection(MyProto, '127.0.0.1', 80) 1041 with self.assertRaises(asyncio.TimeoutError): 1042 self.loop.run_until_complete(coro) 1043 self.assertTrue(sock.close.called) 1044 1045 def test_create_connection_host_port_sock(self): 1046 coro = self.loop.create_connection( 1047 MyProto, 'example.com', 80, sock=object()) 1048 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1049 1050 def test_create_connection_wrong_sock(self): 1051 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 1052 with sock: 1053 coro = self.loop.create_connection(MyProto, sock=sock) 1054 with self.assertRaisesRegex(ValueError, 1055 'A Stream Socket was expected'): 1056 self.loop.run_until_complete(coro) 1057 1058 def test_create_server_wrong_sock(self): 1059 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 1060 with sock: 1061 coro = self.loop.create_server(MyProto, sock=sock) 1062 with self.assertRaisesRegex(ValueError, 1063 'A Stream Socket was expected'): 1064 self.loop.run_until_complete(coro) 1065 1066 @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), 1067 'no socket.SOCK_NONBLOCK (linux only)') 1068 def test_create_server_stream_bittype(self): 1069 sock = socket.socket( 1070 socket.AF_INET, socket.SOCK_STREAM | socket.SOCK_NONBLOCK) 1071 with sock: 1072 coro = self.loop.create_server(lambda: None, sock=sock) 1073 srv = self.loop.run_until_complete(coro) 1074 srv.close() 1075 self.loop.run_until_complete(srv.wait_closed()) 1076 1077 def test_create_datagram_endpoint_wrong_sock(self): 1078 sock = socket.socket(socket.AF_INET) 1079 with sock: 1080 coro = self.loop.create_datagram_endpoint(MyProto, sock=sock) 1081 with self.assertRaisesRegex(ValueError, 1082 'A UDP Socket was expected'): 1083 self.loop.run_until_complete(coro) 1084 1085 def test_create_connection_no_host_port_sock(self): 1086 coro = self.loop.create_connection(MyProto) 1087 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1088 1089 def test_create_connection_no_getaddrinfo(self): 1090 @asyncio.coroutine 1091 def getaddrinfo(*args, **kw): 1092 yield from [] 1093 1094 def getaddrinfo_task(*args, **kwds): 1095 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1096 1097 self.loop.getaddrinfo = getaddrinfo_task 1098 coro = self.loop.create_connection(MyProto, 'example.com', 80) 1099 self.assertRaises( 1100 OSError, self.loop.run_until_complete, coro) 1101 1102 def test_create_connection_connect_err(self): 1103 @asyncio.coroutine 1104 def getaddrinfo(*args, **kw): 1105 yield from [] 1106 return [(2, 1, 6, '', ('107.6.106.82', 80))] 1107 1108 def getaddrinfo_task(*args, **kwds): 1109 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1110 1111 self.loop.getaddrinfo = getaddrinfo_task 1112 self.loop.sock_connect = mock.Mock() 1113 self.loop.sock_connect.side_effect = OSError 1114 1115 coro = self.loop.create_connection(MyProto, 'example.com', 80) 1116 self.assertRaises( 1117 OSError, self.loop.run_until_complete, coro) 1118 1119 def test_create_connection_multiple(self): 1120 @asyncio.coroutine 1121 def getaddrinfo(*args, **kw): 1122 return [(2, 1, 6, '', ('0.0.0.1', 80)), 1123 (2, 1, 6, '', ('0.0.0.2', 80))] 1124 1125 def getaddrinfo_task(*args, **kwds): 1126 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1127 1128 self.loop.getaddrinfo = getaddrinfo_task 1129 self.loop.sock_connect = mock.Mock() 1130 self.loop.sock_connect.side_effect = OSError 1131 1132 coro = self.loop.create_connection( 1133 MyProto, 'example.com', 80, family=socket.AF_INET) 1134 with self.assertRaises(OSError): 1135 self.loop.run_until_complete(coro) 1136 1137 @patch_socket 1138 def test_create_connection_multiple_errors_local_addr(self, m_socket): 1139 1140 def bind(addr): 1141 if addr[0] == '0.0.0.1': 1142 err = OSError('Err') 1143 err.strerror = 'Err' 1144 raise err 1145 1146 m_socket.socket.return_value.bind = bind 1147 1148 @asyncio.coroutine 1149 def getaddrinfo(*args, **kw): 1150 return [(2, 1, 6, '', ('0.0.0.1', 80)), 1151 (2, 1, 6, '', ('0.0.0.2', 80))] 1152 1153 def getaddrinfo_task(*args, **kwds): 1154 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1155 1156 self.loop.getaddrinfo = getaddrinfo_task 1157 self.loop.sock_connect = mock.Mock() 1158 self.loop.sock_connect.side_effect = OSError('Err2') 1159 1160 coro = self.loop.create_connection( 1161 MyProto, 'example.com', 80, family=socket.AF_INET, 1162 local_addr=(None, 8080)) 1163 with self.assertRaises(OSError) as cm: 1164 self.loop.run_until_complete(coro) 1165 1166 self.assertTrue(str(cm.exception).startswith('Multiple exceptions: ')) 1167 self.assertTrue(m_socket.socket.return_value.close.called) 1168 1169 def _test_create_connection_ip_addr(self, m_socket, allow_inet_pton): 1170 # Test the fallback code, even if this system has inet_pton. 1171 if not allow_inet_pton: 1172 del m_socket.inet_pton 1173 1174 m_socket.getaddrinfo = socket.getaddrinfo 1175 sock = m_socket.socket.return_value 1176 1177 self.loop._add_reader = mock.Mock() 1178 self.loop._add_reader._is_coroutine = False 1179 self.loop._add_writer = mock.Mock() 1180 self.loop._add_writer._is_coroutine = False 1181 1182 coro = self.loop.create_connection(asyncio.Protocol, '1.2.3.4', 80) 1183 t, p = self.loop.run_until_complete(coro) 1184 try: 1185 sock.connect.assert_called_with(('1.2.3.4', 80)) 1186 _, kwargs = m_socket.socket.call_args 1187 self.assertEqual(kwargs['family'], m_socket.AF_INET) 1188 self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) 1189 finally: 1190 t.close() 1191 test_utils.run_briefly(self.loop) # allow transport to close 1192 1193 sock.family = socket.AF_INET6 1194 coro = self.loop.create_connection(asyncio.Protocol, '::1', 80) 1195 t, p = self.loop.run_until_complete(coro) 1196 try: 1197 # Without inet_pton we use getaddrinfo, which transforms ('::1', 80) 1198 # to ('::1', 80, 0, 0). The last 0s are flow info, scope id. 1199 [address] = sock.connect.call_args[0] 1200 host, port = address[:2] 1201 self.assertRegex(host, r'::(0\.)*1') 1202 self.assertEqual(port, 80) 1203 _, kwargs = m_socket.socket.call_args 1204 self.assertEqual(kwargs['family'], m_socket.AF_INET6) 1205 self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) 1206 finally: 1207 t.close() 1208 test_utils.run_briefly(self.loop) # allow transport to close 1209 1210 @patch_socket 1211 def test_create_connection_ip_addr(self, m_socket): 1212 self._test_create_connection_ip_addr(m_socket, True) 1213 1214 @patch_socket 1215 def test_create_connection_no_inet_pton(self, m_socket): 1216 self._test_create_connection_ip_addr(m_socket, False) 1217 1218 @patch_socket 1219 def test_create_connection_service_name(self, m_socket): 1220 m_socket.getaddrinfo = socket.getaddrinfo 1221 sock = m_socket.socket.return_value 1222 1223 self.loop._add_reader = mock.Mock() 1224 self.loop._add_reader._is_coroutine = False 1225 self.loop._add_writer = mock.Mock() 1226 self.loop._add_writer._is_coroutine = False 1227 1228 for service, port in ('http', 80), (b'http', 80): 1229 coro = self.loop.create_connection(asyncio.Protocol, 1230 '127.0.0.1', service) 1231 1232 t, p = self.loop.run_until_complete(coro) 1233 try: 1234 sock.connect.assert_called_with(('127.0.0.1', port)) 1235 _, kwargs = m_socket.socket.call_args 1236 self.assertEqual(kwargs['family'], m_socket.AF_INET) 1237 self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) 1238 finally: 1239 t.close() 1240 test_utils.run_briefly(self.loop) # allow transport to close 1241 1242 for service in 'nonsense', b'nonsense': 1243 coro = self.loop.create_connection(asyncio.Protocol, 1244 '127.0.0.1', service) 1245 1246 with self.assertRaises(OSError): 1247 self.loop.run_until_complete(coro) 1248 1249 def test_create_connection_no_local_addr(self): 1250 @asyncio.coroutine 1251 def getaddrinfo(host, *args, **kw): 1252 if host == 'example.com': 1253 return [(2, 1, 6, '', ('107.6.106.82', 80)), 1254 (2, 1, 6, '', ('107.6.106.82', 80))] 1255 else: 1256 return [] 1257 1258 def getaddrinfo_task(*args, **kwds): 1259 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1260 self.loop.getaddrinfo = getaddrinfo_task 1261 1262 coro = self.loop.create_connection( 1263 MyProto, 'example.com', 80, family=socket.AF_INET, 1264 local_addr=(None, 8080)) 1265 self.assertRaises( 1266 OSError, self.loop.run_until_complete, coro) 1267 1268 @patch_socket 1269 def test_create_connection_bluetooth(self, m_socket): 1270 # See http://bugs.python.org/issue27136, fallback to getaddrinfo when 1271 # we can't recognize an address is resolved, e.g. a Bluetooth address. 1272 addr = ('00:01:02:03:04:05', 1) 1273 1274 def getaddrinfo(host, port, *args, **kw): 1275 assert (host, port) == addr 1276 return [(999, 1, 999, '', (addr, 1))] 1277 1278 m_socket.getaddrinfo = getaddrinfo 1279 sock = m_socket.socket() 1280 coro = self.loop.sock_connect(sock, addr) 1281 self.loop.run_until_complete(coro) 1282 1283 def test_create_connection_ssl_server_hostname_default(self): 1284 self.loop.getaddrinfo = mock.Mock() 1285 1286 def mock_getaddrinfo(*args, **kwds): 1287 f = asyncio.Future(loop=self.loop) 1288 f.set_result([(socket.AF_INET, socket.SOCK_STREAM, 1289 socket.SOL_TCP, '', ('1.2.3.4', 80))]) 1290 return f 1291 1292 self.loop.getaddrinfo.side_effect = mock_getaddrinfo 1293 self.loop.sock_connect = mock.Mock() 1294 self.loop.sock_connect.return_value = () 1295 self.loop._make_ssl_transport = mock.Mock() 1296 1297 class _SelectorTransportMock: 1298 _sock = None 1299 1300 def get_extra_info(self, key): 1301 return mock.Mock() 1302 1303 def close(self): 1304 self._sock.close() 1305 1306 def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, 1307 **kwds): 1308 waiter.set_result(None) 1309 transport = _SelectorTransportMock() 1310 transport._sock = sock 1311 return transport 1312 1313 self.loop._make_ssl_transport.side_effect = mock_make_ssl_transport 1314 ANY = mock.ANY 1315 # First try the default server_hostname. 1316 self.loop._make_ssl_transport.reset_mock() 1317 coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True) 1318 transport, _ = self.loop.run_until_complete(coro) 1319 transport.close() 1320 self.loop._make_ssl_transport.assert_called_with( 1321 ANY, ANY, ANY, ANY, 1322 server_side=False, 1323 server_hostname='python.org') 1324 # Next try an explicit server_hostname. 1325 self.loop._make_ssl_transport.reset_mock() 1326 coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True, 1327 server_hostname='perl.com') 1328 transport, _ = self.loop.run_until_complete(coro) 1329 transport.close() 1330 self.loop._make_ssl_transport.assert_called_with( 1331 ANY, ANY, ANY, ANY, 1332 server_side=False, 1333 server_hostname='perl.com') 1334 # Finally try an explicit empty server_hostname. 1335 self.loop._make_ssl_transport.reset_mock() 1336 coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True, 1337 server_hostname='') 1338 transport, _ = self.loop.run_until_complete(coro) 1339 transport.close() 1340 self.loop._make_ssl_transport.assert_called_with(ANY, ANY, ANY, ANY, 1341 server_side=False, 1342 server_hostname='') 1343 1344 def test_create_connection_no_ssl_server_hostname_errors(self): 1345 # When not using ssl, server_hostname must be None. 1346 coro = self.loop.create_connection(MyProto, 'python.org', 80, 1347 server_hostname='') 1348 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1349 coro = self.loop.create_connection(MyProto, 'python.org', 80, 1350 server_hostname='python.org') 1351 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1352 1353 def test_create_connection_ssl_server_hostname_errors(self): 1354 # When using ssl, server_hostname may be None if host is non-empty. 1355 coro = self.loop.create_connection(MyProto, '', 80, ssl=True) 1356 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1357 coro = self.loop.create_connection(MyProto, None, 80, ssl=True) 1358 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1359 sock = socket.socket() 1360 coro = self.loop.create_connection(MyProto, None, None, 1361 ssl=True, sock=sock) 1362 self.addCleanup(sock.close) 1363 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1364 1365 def test_create_server_empty_host(self): 1366 # if host is empty string use None instead 1367 host = object() 1368 1369 @asyncio.coroutine 1370 def getaddrinfo(*args, **kw): 1371 nonlocal host 1372 host = args[0] 1373 yield from [] 1374 1375 def getaddrinfo_task(*args, **kwds): 1376 return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) 1377 1378 self.loop.getaddrinfo = getaddrinfo_task 1379 fut = self.loop.create_server(MyProto, '', 0) 1380 self.assertRaises(OSError, self.loop.run_until_complete, fut) 1381 self.assertIsNone(host) 1382 1383 def test_create_server_host_port_sock(self): 1384 fut = self.loop.create_server( 1385 MyProto, '0.0.0.0', 0, sock=object()) 1386 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1387 1388 def test_create_server_no_host_port_sock(self): 1389 fut = self.loop.create_server(MyProto) 1390 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1391 1392 def test_create_server_no_getaddrinfo(self): 1393 getaddrinfo = self.loop.getaddrinfo = mock.Mock() 1394 getaddrinfo.return_value = [] 1395 1396 f = self.loop.create_server(MyProto, 'python.org', 0) 1397 self.assertRaises(OSError, self.loop.run_until_complete, f) 1398 1399 @patch_socket 1400 def test_create_server_nosoreuseport(self, m_socket): 1401 m_socket.getaddrinfo = socket.getaddrinfo 1402 del m_socket.SO_REUSEPORT 1403 m_socket.socket.return_value = mock.Mock() 1404 1405 f = self.loop.create_server( 1406 MyProto, '0.0.0.0', 0, reuse_port=True) 1407 1408 self.assertRaises(ValueError, self.loop.run_until_complete, f) 1409 1410 @patch_socket 1411 def test_create_server_soreuseport_only_defined(self, m_socket): 1412 m_socket.getaddrinfo = socket.getaddrinfo 1413 m_socket.socket.return_value = mock.Mock() 1414 m_socket.SO_REUSEPORT = -1 1415 1416 f = self.loop.create_server( 1417 MyProto, '0.0.0.0', 0, reuse_port=True) 1418 1419 self.assertRaises(ValueError, self.loop.run_until_complete, f) 1420 1421 @patch_socket 1422 def test_create_server_cant_bind(self, m_socket): 1423 1424 class Err(OSError): 1425 strerror = 'error' 1426 1427 m_socket.getaddrinfo.return_value = [ 1428 (2, 1, 6, '', ('127.0.0.1', 10100))] 1429 m_socket.getaddrinfo._is_coroutine = False 1430 m_sock = m_socket.socket.return_value = mock.Mock() 1431 m_sock.bind.side_effect = Err 1432 1433 fut = self.loop.create_server(MyProto, '0.0.0.0', 0) 1434 self.assertRaises(OSError, self.loop.run_until_complete, fut) 1435 self.assertTrue(m_sock.close.called) 1436 1437 @patch_socket 1438 def test_create_datagram_endpoint_no_addrinfo(self, m_socket): 1439 m_socket.getaddrinfo.return_value = [] 1440 m_socket.getaddrinfo._is_coroutine = False 1441 1442 coro = self.loop.create_datagram_endpoint( 1443 MyDatagramProto, local_addr=('localhost', 0)) 1444 self.assertRaises( 1445 OSError, self.loop.run_until_complete, coro) 1446 1447 def test_create_datagram_endpoint_addr_error(self): 1448 coro = self.loop.create_datagram_endpoint( 1449 MyDatagramProto, local_addr='localhost') 1450 self.assertRaises( 1451 AssertionError, self.loop.run_until_complete, coro) 1452 coro = self.loop.create_datagram_endpoint( 1453 MyDatagramProto, local_addr=('localhost', 1, 2, 3)) 1454 self.assertRaises( 1455 AssertionError, self.loop.run_until_complete, coro) 1456 1457 def test_create_datagram_endpoint_connect_err(self): 1458 self.loop.sock_connect = mock.Mock() 1459 self.loop.sock_connect.side_effect = OSError 1460 1461 coro = self.loop.create_datagram_endpoint( 1462 asyncio.DatagramProtocol, remote_addr=('127.0.0.1', 0)) 1463 self.assertRaises( 1464 OSError, self.loop.run_until_complete, coro) 1465 1466 @patch_socket 1467 def test_create_datagram_endpoint_socket_err(self, m_socket): 1468 m_socket.getaddrinfo = socket.getaddrinfo 1469 m_socket.socket.side_effect = OSError 1470 1471 coro = self.loop.create_datagram_endpoint( 1472 asyncio.DatagramProtocol, family=socket.AF_INET) 1473 self.assertRaises( 1474 OSError, self.loop.run_until_complete, coro) 1475 1476 coro = self.loop.create_datagram_endpoint( 1477 asyncio.DatagramProtocol, local_addr=('127.0.0.1', 0)) 1478 self.assertRaises( 1479 OSError, self.loop.run_until_complete, coro) 1480 1481 @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 not supported or enabled') 1482 def test_create_datagram_endpoint_no_matching_family(self): 1483 coro = self.loop.create_datagram_endpoint( 1484 asyncio.DatagramProtocol, 1485 remote_addr=('127.0.0.1', 0), local_addr=('::1', 0)) 1486 self.assertRaises( 1487 ValueError, self.loop.run_until_complete, coro) 1488 1489 @patch_socket 1490 def test_create_datagram_endpoint_setblk_err(self, m_socket): 1491 m_socket.socket.return_value.setblocking.side_effect = OSError 1492 1493 coro = self.loop.create_datagram_endpoint( 1494 asyncio.DatagramProtocol, family=socket.AF_INET) 1495 self.assertRaises( 1496 OSError, self.loop.run_until_complete, coro) 1497 self.assertTrue( 1498 m_socket.socket.return_value.close.called) 1499 1500 def test_create_datagram_endpoint_noaddr_nofamily(self): 1501 coro = self.loop.create_datagram_endpoint( 1502 asyncio.DatagramProtocol) 1503 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1504 1505 @patch_socket 1506 def test_create_datagram_endpoint_cant_bind(self, m_socket): 1507 class Err(OSError): 1508 pass 1509 1510 m_socket.getaddrinfo = socket.getaddrinfo 1511 m_sock = m_socket.socket.return_value = mock.Mock() 1512 m_sock.bind.side_effect = Err 1513 1514 fut = self.loop.create_datagram_endpoint( 1515 MyDatagramProto, 1516 local_addr=('127.0.0.1', 0), family=socket.AF_INET) 1517 self.assertRaises(Err, self.loop.run_until_complete, fut) 1518 self.assertTrue(m_sock.close.called) 1519 1520 def test_create_datagram_endpoint_sock(self): 1521 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 1522 sock.bind(('127.0.0.1', 0)) 1523 fut = self.loop.create_datagram_endpoint( 1524 lambda: MyDatagramProto(create_future=True, loop=self.loop), 1525 sock=sock) 1526 transport, protocol = self.loop.run_until_complete(fut) 1527 transport.close() 1528 self.loop.run_until_complete(protocol.done) 1529 self.assertEqual('CLOSED', protocol.state) 1530 1531 def test_create_datagram_endpoint_sock_sockopts(self): 1532 class FakeSock: 1533 type = socket.SOCK_DGRAM 1534 1535 fut = self.loop.create_datagram_endpoint( 1536 MyDatagramProto, local_addr=('127.0.0.1', 0), sock=FakeSock()) 1537 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1538 1539 fut = self.loop.create_datagram_endpoint( 1540 MyDatagramProto, remote_addr=('127.0.0.1', 0), sock=FakeSock()) 1541 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1542 1543 fut = self.loop.create_datagram_endpoint( 1544 MyDatagramProto, family=1, sock=FakeSock()) 1545 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1546 1547 fut = self.loop.create_datagram_endpoint( 1548 MyDatagramProto, proto=1, sock=FakeSock()) 1549 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1550 1551 fut = self.loop.create_datagram_endpoint( 1552 MyDatagramProto, flags=1, sock=FakeSock()) 1553 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1554 1555 fut = self.loop.create_datagram_endpoint( 1556 MyDatagramProto, reuse_address=True, sock=FakeSock()) 1557 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1558 1559 fut = self.loop.create_datagram_endpoint( 1560 MyDatagramProto, reuse_port=True, sock=FakeSock()) 1561 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1562 1563 fut = self.loop.create_datagram_endpoint( 1564 MyDatagramProto, allow_broadcast=True, sock=FakeSock()) 1565 self.assertRaises(ValueError, self.loop.run_until_complete, fut) 1566 1567 def test_create_datagram_endpoint_sockopts(self): 1568 # Socket options should not be applied unless asked for. 1569 # SO_REUSEADDR defaults to on for UNIX. 1570 # SO_REUSEPORT is not available on all platforms. 1571 1572 coro = self.loop.create_datagram_endpoint( 1573 lambda: MyDatagramProto(create_future=True, loop=self.loop), 1574 local_addr=('127.0.0.1', 0)) 1575 transport, protocol = self.loop.run_until_complete(coro) 1576 sock = transport.get_extra_info('socket') 1577 1578 reuse_address_default_on = ( 1579 os.name == 'posix' and sys.platform != 'cygwin') 1580 reuseport_supported = hasattr(socket, 'SO_REUSEPORT') 1581 1582 if reuse_address_default_on: 1583 self.assertTrue( 1584 sock.getsockopt( 1585 socket.SOL_SOCKET, socket.SO_REUSEADDR)) 1586 else: 1587 self.assertFalse( 1588 sock.getsockopt( 1589 socket.SOL_SOCKET, socket.SO_REUSEADDR)) 1590 if reuseport_supported: 1591 self.assertFalse( 1592 sock.getsockopt( 1593 socket.SOL_SOCKET, socket.SO_REUSEPORT)) 1594 self.assertFalse( 1595 sock.getsockopt( 1596 socket.SOL_SOCKET, socket.SO_BROADCAST)) 1597 1598 transport.close() 1599 self.loop.run_until_complete(protocol.done) 1600 self.assertEqual('CLOSED', protocol.state) 1601 1602 coro = self.loop.create_datagram_endpoint( 1603 lambda: MyDatagramProto(create_future=True, loop=self.loop), 1604 local_addr=('127.0.0.1', 0), 1605 reuse_address=True, 1606 reuse_port=reuseport_supported, 1607 allow_broadcast=True) 1608 transport, protocol = self.loop.run_until_complete(coro) 1609 sock = transport.get_extra_info('socket') 1610 1611 self.assertTrue( 1612 sock.getsockopt( 1613 socket.SOL_SOCKET, socket.SO_REUSEADDR)) 1614 if reuseport_supported: 1615 self.assertTrue( 1616 sock.getsockopt( 1617 socket.SOL_SOCKET, socket.SO_REUSEPORT)) 1618 self.assertTrue( 1619 sock.getsockopt( 1620 socket.SOL_SOCKET, socket.SO_BROADCAST)) 1621 1622 transport.close() 1623 self.loop.run_until_complete(protocol.done) 1624 self.assertEqual('CLOSED', protocol.state) 1625 1626 @patch_socket 1627 def test_create_datagram_endpoint_nosoreuseport(self, m_socket): 1628 del m_socket.SO_REUSEPORT 1629 m_socket.socket.return_value = mock.Mock() 1630 1631 coro = self.loop.create_datagram_endpoint( 1632 lambda: MyDatagramProto(loop=self.loop), 1633 local_addr=('127.0.0.1', 0), 1634 reuse_address=False, 1635 reuse_port=True) 1636 1637 self.assertRaises(ValueError, self.loop.run_until_complete, coro) 1638 1639 @patch_socket 1640 def test_create_datagram_endpoint_ip_addr(self, m_socket): 1641 def getaddrinfo(*args, **kw): 1642 self.fail('should not have called getaddrinfo') 1643 1644 m_socket.getaddrinfo = getaddrinfo 1645 m_socket.socket.return_value.bind = bind = mock.Mock() 1646 self.loop._add_reader = mock.Mock() 1647 self.loop._add_reader._is_coroutine = False 1648 1649 reuseport_supported = hasattr(socket, 'SO_REUSEPORT') 1650 coro = self.loop.create_datagram_endpoint( 1651 lambda: MyDatagramProto(loop=self.loop), 1652 local_addr=('1.2.3.4', 0), 1653 reuse_address=False, 1654 reuse_port=reuseport_supported) 1655 1656 t, p = self.loop.run_until_complete(coro) 1657 try: 1658 bind.assert_called_with(('1.2.3.4', 0)) 1659 m_socket.socket.assert_called_with(family=m_socket.AF_INET, 1660 proto=m_socket.IPPROTO_UDP, 1661 type=m_socket.SOCK_DGRAM) 1662 finally: 1663 t.close() 1664 test_utils.run_briefly(self.loop) # allow transport to close 1665 1666 def test_accept_connection_retry(self): 1667 sock = mock.Mock() 1668 sock.accept.side_effect = BlockingIOError() 1669 1670 self.loop._accept_connection(MyProto, sock) 1671 self.assertFalse(sock.close.called) 1672 1673 @mock.patch('asyncio.base_events.logger') 1674 def test_accept_connection_exception(self, m_log): 1675 sock = mock.Mock() 1676 sock.fileno.return_value = 10 1677 sock.accept.side_effect = OSError(errno.EMFILE, 'Too many open files') 1678 self.loop._remove_reader = mock.Mock() 1679 self.loop.call_later = mock.Mock() 1680 1681 self.loop._accept_connection(MyProto, sock) 1682 self.assertTrue(m_log.error.called) 1683 self.assertFalse(sock.close.called) 1684 self.loop._remove_reader.assert_called_with(10) 1685 self.loop.call_later.assert_called_with(constants.ACCEPT_RETRY_DELAY, 1686 # self.loop._start_serving 1687 mock.ANY, 1688 MyProto, sock, None, None, mock.ANY) 1689 1690 def test_call_coroutine(self): 1691 @asyncio.coroutine 1692 def simple_coroutine(): 1693 pass 1694 1695 self.loop.set_debug(True) 1696 coro_func = simple_coroutine 1697 coro_obj = coro_func() 1698 self.addCleanup(coro_obj.close) 1699 for func in (coro_func, coro_obj): 1700 with self.assertRaises(TypeError): 1701 self.loop.call_soon(func) 1702 with self.assertRaises(TypeError): 1703 self.loop.call_soon_threadsafe(func) 1704 with self.assertRaises(TypeError): 1705 self.loop.call_later(60, func) 1706 with self.assertRaises(TypeError): 1707 self.loop.call_at(self.loop.time() + 60, func) 1708 with self.assertRaises(TypeError): 1709 self.loop.run_in_executor(None, func) 1710 1711 @mock.patch('asyncio.base_events.logger') 1712 def test_log_slow_callbacks(self, m_logger): 1713 def stop_loop_cb(loop): 1714 loop.stop() 1715 1716 @asyncio.coroutine 1717 def stop_loop_coro(loop): 1718 yield from () 1719 loop.stop() 1720 1721 asyncio.set_event_loop(self.loop) 1722 self.loop.set_debug(True) 1723 self.loop.slow_callback_duration = 0.0 1724 1725 # slow callback 1726 self.loop.call_soon(stop_loop_cb, self.loop) 1727 self.loop.run_forever() 1728 fmt, *args = m_logger.warning.call_args[0] 1729 self.assertRegex(fmt % tuple(args), 1730 "^Executing <Handle.*stop_loop_cb.*> " 1731 "took .* seconds$") 1732 1733 # slow task 1734 asyncio.ensure_future(stop_loop_coro(self.loop), loop=self.loop) 1735 self.loop.run_forever() 1736 fmt, *args = m_logger.warning.call_args[0] 1737 self.assertRegex(fmt % tuple(args), 1738 "^Executing <Task.*stop_loop_coro.*> " 1739 "took .* seconds$") 1740 1741 1742 class RunningLoopTests(unittest.TestCase): 1743 1744 def test_running_loop_within_a_loop(self): 1745 @asyncio.coroutine 1746 def runner(loop): 1747 loop.run_forever() 1748 1749 loop = asyncio.new_event_loop() 1750 outer_loop = asyncio.new_event_loop() 1751 try: 1752 with self.assertRaisesRegex(RuntimeError, 1753 'while another loop is running'): 1754 outer_loop.run_until_complete(runner(loop)) 1755 finally: 1756 loop.close() 1757 outer_loop.close() 1758 1759 1760 if __name__ == '__main__': 1761 unittest.main() 1762