diff options
Diffstat (limited to 'Lib/test/test_asyncio')
30 files changed, 0 insertions, 20838 deletions
diff --git a/Lib/test/test_asyncio/__init__.py b/Lib/test/test_asyncio/__init__.py deleted file mode 100644 index c77c7a8..0000000 --- a/Lib/test/test_asyncio/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -import os -from test.support import load_package_tests, import_module - -# Skip tests if we don't have concurrent.futures. -import_module('concurrent.futures') - -def load_tests(*args): - return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_asyncio/__main__.py b/Lib/test/test_asyncio/__main__.py deleted file mode 100644 index 40a23a2..0000000 --- a/Lib/test/test_asyncio/__main__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import load_tests -import unittest - -unittest.main() diff --git a/Lib/test/test_asyncio/echo.py b/Lib/test/test_asyncio/echo.py deleted file mode 100644 index 006364b..0000000 --- a/Lib/test/test_asyncio/echo.py +++ /dev/null @@ -1,8 +0,0 @@ -import os - -if __name__ == '__main__': - while True: - buf = os.read(0, 1024) - if not buf: - break - os.write(1, buf) diff --git a/Lib/test/test_asyncio/echo2.py b/Lib/test/test_asyncio/echo2.py deleted file mode 100644 index e83ca09..0000000 --- a/Lib/test/test_asyncio/echo2.py +++ /dev/null @@ -1,6 +0,0 @@ -import os - -if __name__ == '__main__': - buf = os.read(0, 1024) - os.write(1, b'OUT:'+buf) - os.write(2, b'ERR:'+buf) diff --git a/Lib/test/test_asyncio/echo3.py b/Lib/test/test_asyncio/echo3.py deleted file mode 100644 index 0644967..0000000 --- a/Lib/test/test_asyncio/echo3.py +++ /dev/null @@ -1,11 +0,0 @@ -import os - -if __name__ == '__main__': - while True: - buf = os.read(0, 1024) - if not buf: - break - try: - os.write(1, b'OUT:'+buf) - except OSError as ex: - os.write(2, b'ERR:' + ex.__class__.__name__.encode('ascii')) diff --git a/Lib/test/test_asyncio/functional.py b/Lib/test/test_asyncio/functional.py deleted file mode 100644 index 5cd0659..0000000 --- a/Lib/test/test_asyncio/functional.py +++ /dev/null @@ -1,274 +0,0 @@ -import asyncio -import asyncio.events -import contextlib -import os -import pprint -import select -import socket -import tempfile -import threading -from test import support - - -class FunctionalTestCaseMixin: - - def new_loop(self): - return asyncio.new_event_loop() - - def run_loop_briefly(self, *, delay=0.01): - self.loop.run_until_complete(asyncio.sleep(delay)) - - def loop_exception_handler(self, loop, context): - self.__unhandled_exceptions.append(context) - self.loop.default_exception_handler(context) - - def setUp(self): - self.loop = self.new_loop() - asyncio.set_event_loop(None) - - self.loop.set_exception_handler(self.loop_exception_handler) - self.__unhandled_exceptions = [] - - # Disable `_get_running_loop`. - self._old_get_running_loop = asyncio.events._get_running_loop - asyncio.events._get_running_loop = lambda: None - - def tearDown(self): - try: - self.loop.close() - - if self.__unhandled_exceptions: - print('Unexpected calls to loop.call_exception_handler():') - pprint.pprint(self.__unhandled_exceptions) - self.fail('unexpected calls to loop.call_exception_handler()') - - finally: - asyncio.events._get_running_loop = self._old_get_running_loop - asyncio.set_event_loop(None) - self.loop = None - - def tcp_server(self, server_prog, *, - family=socket.AF_INET, - addr=None, - timeout=support.LOOPBACK_TIMEOUT, - backlog=1, - max_clients=10): - - if addr is None: - if hasattr(socket, 'AF_UNIX') and family == socket.AF_UNIX: - with tempfile.NamedTemporaryFile() as tmp: - addr = tmp.name - else: - addr = ('127.0.0.1', 0) - - sock = socket.create_server(addr, family=family, backlog=backlog) - if timeout is None: - raise RuntimeError('timeout is required') - if timeout <= 0: - raise RuntimeError('only blocking sockets are supported') - sock.settimeout(timeout) - - return TestThreadedServer( - self, sock, server_prog, timeout, max_clients) - - def tcp_client(self, client_prog, - family=socket.AF_INET, - timeout=support.LOOPBACK_TIMEOUT): - - sock = socket.socket(family, socket.SOCK_STREAM) - - if timeout is None: - raise RuntimeError('timeout is required') - if timeout <= 0: - raise RuntimeError('only blocking sockets are supported') - sock.settimeout(timeout) - - return TestThreadedClient( - self, sock, client_prog, timeout) - - def unix_server(self, *args, **kwargs): - if not hasattr(socket, 'AF_UNIX'): - raise NotImplementedError - return self.tcp_server(*args, family=socket.AF_UNIX, **kwargs) - - def unix_client(self, *args, **kwargs): - if not hasattr(socket, 'AF_UNIX'): - raise NotImplementedError - return self.tcp_client(*args, family=socket.AF_UNIX, **kwargs) - - @contextlib.contextmanager - def unix_sock_name(self): - with tempfile.TemporaryDirectory() as td: - fn = os.path.join(td, 'sock') - try: - yield fn - finally: - try: - os.unlink(fn) - except OSError: - pass - - def _abort_socket_test(self, ex): - try: - self.loop.stop() - finally: - self.fail(ex) - - -############################################################################## -# Socket Testing Utilities -############################################################################## - - -class TestSocketWrapper: - - def __init__(self, sock): - self.__sock = sock - - def recv_all(self, n): - buf = b'' - while len(buf) < n: - data = self.recv(n - len(buf)) - if data == b'': - raise ConnectionAbortedError - buf += data - return buf - - def start_tls(self, ssl_context, *, - server_side=False, - server_hostname=None): - - ssl_sock = ssl_context.wrap_socket( - self.__sock, server_side=server_side, - server_hostname=server_hostname, - do_handshake_on_connect=False) - - try: - ssl_sock.do_handshake() - except: - ssl_sock.close() - raise - finally: - self.__sock.close() - - self.__sock = ssl_sock - - def __getattr__(self, name): - return getattr(self.__sock, name) - - def __repr__(self): - return '<{} {!r}>'.format(type(self).__name__, self.__sock) - - -class SocketThread(threading.Thread): - - def stop(self): - self._active = False - self.join() - - def __enter__(self): - self.start() - return self - - def __exit__(self, *exc): - self.stop() - - -class TestThreadedClient(SocketThread): - - def __init__(self, test, sock, prog, timeout): - threading.Thread.__init__(self, None, None, 'test-client') - self.daemon = True - - self._timeout = timeout - self._sock = sock - self._active = True - self._prog = prog - self._test = test - - def run(self): - try: - self._prog(TestSocketWrapper(self._sock)) - except Exception as ex: - self._test._abort_socket_test(ex) - - -class TestThreadedServer(SocketThread): - - def __init__(self, test, sock, prog, timeout, max_clients): - threading.Thread.__init__(self, None, None, 'test-server') - self.daemon = True - - self._clients = 0 - self._finished_clients = 0 - self._max_clients = max_clients - self._timeout = timeout - self._sock = sock - self._active = True - - self._prog = prog - - self._s1, self._s2 = socket.socketpair() - self._s1.setblocking(False) - - self._test = test - - def stop(self): - try: - if self._s2 and self._s2.fileno() != -1: - try: - self._s2.send(b'stop') - except OSError: - pass - finally: - super().stop() - - def run(self): - try: - with self._sock: - self._sock.setblocking(False) - self._run() - finally: - self._s1.close() - self._s2.close() - - def _run(self): - while self._active: - if self._clients >= self._max_clients: - return - - r, w, x = select.select( - [self._sock, self._s1], [], [], self._timeout) - - if self._s1 in r: - return - - if self._sock in r: - try: - conn, addr = self._sock.accept() - except BlockingIOError: - continue - except socket.timeout: - if not self._active: - return - else: - raise - else: - self._clients += 1 - conn.settimeout(self._timeout) - try: - with conn: - self._handle_client(conn) - except Exception as ex: - self._active = False - try: - raise - finally: - self._test._abort_socket_test(ex) - - def _handle_client(self, sock): - self._prog(TestSocketWrapper(sock)) - - @property - def addr(self): - return self._sock.getsockname() diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py deleted file mode 100644 index 6c0f00d..0000000 --- a/Lib/test/test_asyncio/test_base_events.py +++ /dev/null @@ -1,2160 +0,0 @@ -"""Tests for base_events.py""" - -import concurrent.futures -import errno -import math -import os -import socket -import sys -import threading -import time -import unittest -from unittest import mock - -import asyncio -from asyncio import base_events -from asyncio import constants -from test.test_asyncio import utils as test_utils -from test import support -from test.support.script_helper import assert_python_ok - - -MOCK_ANY = mock.ANY -PY34 = sys.version_info >= (3, 4) - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -def mock_socket_module(): - m_socket = mock.MagicMock(spec=socket) - for name in ( - 'AF_INET', 'AF_INET6', 'AF_UNSPEC', 'IPPROTO_TCP', 'IPPROTO_UDP', - 'SOCK_STREAM', 'SOCK_DGRAM', 'SOL_SOCKET', 'SO_REUSEADDR', 'inet_pton' - ): - if hasattr(socket, name): - setattr(m_socket, name, getattr(socket, name)) - else: - delattr(m_socket, name) - - m_socket.socket = mock.MagicMock() - m_socket.socket.return_value = test_utils.mock_nonblocking_socket() - m_socket.getaddrinfo._is_coroutine = False - - return m_socket - - -def patch_socket(f): - return mock.patch('asyncio.base_events.socket', - new_callable=mock_socket_module)(f) - - -class BaseEventTests(test_utils.TestCase): - - def test_ipaddr_info(self): - UNSPEC = socket.AF_UNSPEC - INET = socket.AF_INET - INET6 = socket.AF_INET6 - STREAM = socket.SOCK_STREAM - DGRAM = socket.SOCK_DGRAM - TCP = socket.IPPROTO_TCP - UDP = socket.IPPROTO_UDP - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', 1, INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info(b'1.2.3.4', 1, INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, TCP)) - - self.assertEqual( - (INET, DGRAM, UDP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, UDP)) - - # Socket type STREAM implies TCP protocol. - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, 0)) - - # Socket type DGRAM implies UDP protocol. - self.assertEqual( - (INET, DGRAM, UDP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, 0)) - - # No socket type. - self.assertIsNone( - base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, 0, 0)) - - if support.IPV6_ENABLED: - # IPv4 address with family IPv6. - self.assertIsNone( - base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP)) - - self.assertEqual( - (INET6, STREAM, TCP, '', ('::3', 1, 0, 0)), - base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP)) - - self.assertEqual( - (INET6, STREAM, TCP, '', ('::3', 1, 0, 0)), - base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP)) - - # IPv6 address with family IPv4. - self.assertIsNone( - base_events._ipaddr_info('::3', 1, INET, STREAM, TCP)) - - # IPv6 address with zone index. - self.assertIsNone( - base_events._ipaddr_info('::3%lo0', 1, INET6, STREAM, TCP)) - - def test_port_parameter_types(self): - # Test obscure kinds of arguments for "port". - INET = socket.AF_INET - STREAM = socket.SOCK_STREAM - TCP = socket.IPPROTO_TCP - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 0)), - base_events._ipaddr_info('1.2.3.4', None, INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 0)), - base_events._ipaddr_info('1.2.3.4', b'', INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 0)), - base_events._ipaddr_info('1.2.3.4', '', INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', '1', INET, STREAM, TCP)) - - self.assertEqual( - (INET, STREAM, TCP, '', ('1.2.3.4', 1)), - base_events._ipaddr_info('1.2.3.4', b'1', INET, STREAM, TCP)) - - @patch_socket - def test_ipaddr_info_no_inet_pton(self, m_socket): - del m_socket.inet_pton - self.assertIsNone(base_events._ipaddr_info('1.2.3.4', 1, - socket.AF_INET, - socket.SOCK_STREAM, - socket.IPPROTO_TCP)) - - -class BaseEventLoopTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = base_events.BaseEventLoop() - self.loop._selector = mock.Mock() - self.loop._selector.select.return_value = () - self.set_event_loop(self.loop) - - def test_not_implemented(self): - m = mock.Mock() - self.assertRaises( - NotImplementedError, - self.loop._make_socket_transport, m, m) - self.assertRaises( - NotImplementedError, - self.loop._make_ssl_transport, m, m, m, m) - self.assertRaises( - NotImplementedError, - self.loop._make_datagram_transport, m, m) - self.assertRaises( - NotImplementedError, self.loop._process_events, []) - self.assertRaises( - NotImplementedError, self.loop._write_to_self) - self.assertRaises( - NotImplementedError, - self.loop._make_read_pipe_transport, m, m) - self.assertRaises( - NotImplementedError, - self.loop._make_write_pipe_transport, m, m) - gen = self.loop._make_subprocess_transport(m, m, m, m, m, m, m) - with self.assertRaises(NotImplementedError): - gen.send(None) - - def test_close(self): - self.assertFalse(self.loop.is_closed()) - self.loop.close() - self.assertTrue(self.loop.is_closed()) - - # it should be possible to call close() more than once - self.loop.close() - self.loop.close() - - # operation blocked when the loop is closed - f = self.loop.create_future() - self.assertRaises(RuntimeError, self.loop.run_forever) - self.assertRaises(RuntimeError, self.loop.run_until_complete, f) - - def test__add_callback_handle(self): - h = asyncio.Handle(lambda: False, (), self.loop, None) - - self.loop._add_callback(h) - self.assertFalse(self.loop._scheduled) - self.assertIn(h, self.loop._ready) - - def test__add_callback_cancelled_handle(self): - h = asyncio.Handle(lambda: False, (), self.loop, None) - h.cancel() - - self.loop._add_callback(h) - self.assertFalse(self.loop._scheduled) - self.assertFalse(self.loop._ready) - - def test_set_default_executor(self): - class DummyExecutor(concurrent.futures.ThreadPoolExecutor): - def submit(self, fn, *args, **kwargs): - raise NotImplementedError( - 'cannot submit into a dummy executor') - - self.loop._process_events = mock.Mock() - self.loop._write_to_self = mock.Mock() - - executor = DummyExecutor() - self.loop.set_default_executor(executor) - self.assertIs(executor, self.loop._default_executor) - - def test_set_default_executor_deprecation_warnings(self): - executor = mock.Mock() - - with self.assertWarns(DeprecationWarning): - self.loop.set_default_executor(executor) - - # Avoid cleaning up the executor mock - self.loop._default_executor = None - - def test_call_soon(self): - def cb(): - pass - - h = self.loop.call_soon(cb) - self.assertEqual(h._callback, cb) - self.assertIsInstance(h, asyncio.Handle) - self.assertIn(h, self.loop._ready) - - def test_call_soon_non_callable(self): - self.loop.set_debug(True) - with self.assertRaisesRegex(TypeError, 'a callable object'): - self.loop.call_soon(1) - - def test_call_later(self): - def cb(): - pass - - h = self.loop.call_later(10.0, cb) - self.assertIsInstance(h, asyncio.TimerHandle) - self.assertIn(h, self.loop._scheduled) - self.assertNotIn(h, self.loop._ready) - - def test_call_later_negative_delays(self): - calls = [] - - def cb(arg): - calls.append(arg) - - self.loop._process_events = mock.Mock() - self.loop.call_later(-1, cb, 'a') - self.loop.call_later(-2, cb, 'b') - test_utils.run_briefly(self.loop) - self.assertEqual(calls, ['b', 'a']) - - def test_time_and_call_at(self): - def cb(): - self.loop.stop() - - self.loop._process_events = mock.Mock() - delay = 0.1 - - when = self.loop.time() + delay - self.loop.call_at(when, cb) - t0 = self.loop.time() - self.loop.run_forever() - dt = self.loop.time() - t0 - - # 50 ms: maximum granularity of the event loop - self.assertGreaterEqual(dt, delay - 0.050, dt) - # tolerate a difference of +800 ms because some Python buildbots - # are really slow - self.assertLessEqual(dt, 0.9, dt) - - def check_thread(self, loop, debug): - def cb(): - pass - - loop.set_debug(debug) - if debug: - msg = ("Non-thread-safe operation invoked on an event loop other " - "than the current one") - with self.assertRaisesRegex(RuntimeError, msg): - loop.call_soon(cb) - with self.assertRaisesRegex(RuntimeError, msg): - loop.call_later(60, cb) - with self.assertRaisesRegex(RuntimeError, msg): - loop.call_at(loop.time() + 60, cb) - else: - loop.call_soon(cb) - loop.call_later(60, cb) - loop.call_at(loop.time() + 60, cb) - - def test_check_thread(self): - def check_in_thread(loop, event, debug, create_loop, fut): - # wait until the event loop is running - event.wait() - - try: - if create_loop: - loop2 = base_events.BaseEventLoop() - try: - asyncio.set_event_loop(loop2) - self.check_thread(loop, debug) - finally: - asyncio.set_event_loop(None) - loop2.close() - else: - self.check_thread(loop, debug) - except Exception as exc: - loop.call_soon_threadsafe(fut.set_exception, exc) - else: - loop.call_soon_threadsafe(fut.set_result, None) - - def test_thread(loop, debug, create_loop=False): - event = threading.Event() - fut = loop.create_future() - loop.call_soon(event.set) - args = (loop, event, debug, create_loop, fut) - thread = threading.Thread(target=check_in_thread, args=args) - thread.start() - loop.run_until_complete(fut) - thread.join() - - self.loop._process_events = mock.Mock() - self.loop._write_to_self = mock.Mock() - - # raise RuntimeError if the thread has no event loop - test_thread(self.loop, True) - - # check disabled if debug mode is disabled - test_thread(self.loop, False) - - # raise RuntimeError if the event loop of the thread is not the called - # event loop - test_thread(self.loop, True, create_loop=True) - - # check disabled if debug mode is disabled - test_thread(self.loop, False, create_loop=True) - - def test__run_once(self): - h1 = asyncio.TimerHandle(time.monotonic() + 5.0, lambda: True, (), - self.loop, None) - h2 = asyncio.TimerHandle(time.monotonic() + 10.0, lambda: True, (), - self.loop, None) - - h1.cancel() - - self.loop._process_events = mock.Mock() - self.loop._scheduled.append(h1) - self.loop._scheduled.append(h2) - self.loop._run_once() - - t = self.loop._selector.select.call_args[0][0] - self.assertTrue(9.5 < t < 10.5, t) - self.assertEqual([h2], self.loop._scheduled) - self.assertTrue(self.loop._process_events.called) - - def test_set_debug(self): - self.loop.set_debug(True) - self.assertTrue(self.loop.get_debug()) - self.loop.set_debug(False) - self.assertFalse(self.loop.get_debug()) - - def test__run_once_schedule_handle(self): - handle = None - processed = False - - def cb(loop): - nonlocal processed, handle - processed = True - handle = loop.call_soon(lambda: True) - - h = asyncio.TimerHandle(time.monotonic() - 1, cb, (self.loop,), - self.loop, None) - - self.loop._process_events = mock.Mock() - self.loop._scheduled.append(h) - self.loop._run_once() - - self.assertTrue(processed) - self.assertEqual([handle], list(self.loop._ready)) - - def test__run_once_cancelled_event_cleanup(self): - self.loop._process_events = mock.Mock() - - self.assertTrue( - 0 < base_events._MIN_CANCELLED_TIMER_HANDLES_FRACTION < 1.0) - - def cb(): - pass - - # Set up one "blocking" event that will not be cancelled to - # ensure later cancelled events do not make it to the head - # of the queue and get cleaned. - not_cancelled_count = 1 - self.loop.call_later(3000, cb) - - # Add less than threshold (base_events._MIN_SCHEDULED_TIMER_HANDLES) - # cancelled handles, ensure they aren't removed - - cancelled_count = 2 - for x in range(2): - h = self.loop.call_later(3600, cb) - h.cancel() - - # Add some cancelled events that will be at head and removed - cancelled_count += 2 - for x in range(2): - h = self.loop.call_later(100, cb) - h.cancel() - - # This test is invalid if _MIN_SCHEDULED_TIMER_HANDLES is too low - self.assertLessEqual(cancelled_count + not_cancelled_count, - base_events._MIN_SCHEDULED_TIMER_HANDLES) - - self.assertEqual(self.loop._timer_cancelled_count, cancelled_count) - - self.loop._run_once() - - cancelled_count -= 2 - - self.assertEqual(self.loop._timer_cancelled_count, cancelled_count) - - self.assertEqual(len(self.loop._scheduled), - cancelled_count + not_cancelled_count) - - # Need enough events to pass _MIN_CANCELLED_TIMER_HANDLES_FRACTION - # so that deletion of cancelled events will occur on next _run_once - add_cancel_count = int(math.ceil( - base_events._MIN_SCHEDULED_TIMER_HANDLES * - base_events._MIN_CANCELLED_TIMER_HANDLES_FRACTION)) + 1 - - add_not_cancel_count = max(base_events._MIN_SCHEDULED_TIMER_HANDLES - - add_cancel_count, 0) - - # Add some events that will not be cancelled - not_cancelled_count += add_not_cancel_count - for x in range(add_not_cancel_count): - self.loop.call_later(3600, cb) - - # Add enough cancelled events - cancelled_count += add_cancel_count - for x in range(add_cancel_count): - h = self.loop.call_later(3600, cb) - h.cancel() - - # Ensure all handles are still scheduled - self.assertEqual(len(self.loop._scheduled), - cancelled_count + not_cancelled_count) - - self.loop._run_once() - - # Ensure cancelled events were removed - self.assertEqual(len(self.loop._scheduled), not_cancelled_count) - - # Ensure only uncancelled events remain scheduled - self.assertTrue(all([not x._cancelled for x in self.loop._scheduled])) - - def test_run_until_complete_type_error(self): - self.assertRaises(TypeError, - self.loop.run_until_complete, 'blah') - - def test_run_until_complete_loop(self): - task = self.loop.create_future() - other_loop = self.new_test_loop() - self.addCleanup(other_loop.close) - self.assertRaises(ValueError, - other_loop.run_until_complete, task) - - def test_run_until_complete_loop_orphan_future_close_loop(self): - class ShowStopper(SystemExit): - pass - - async def foo(delay): - await asyncio.sleep(delay) - - def throw(): - raise ShowStopper - - self.loop._process_events = mock.Mock() - self.loop.call_soon(throw) - with self.assertRaises(ShowStopper): - self.loop.run_until_complete(foo(0.1)) - - # This call fails if run_until_complete does not clean up - # done-callback for the previous future. - self.loop.run_until_complete(foo(0.2)) - - def test_subprocess_exec_invalid_args(self): - args = [sys.executable, '-c', 'pass'] - - # missing program parameter (empty args) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol) - - # expected multiple arguments, not a list - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol, args) - - # program arguments must be strings, not int - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol, sys.executable, 123) - - # universal_newlines, shell, bufsize must not be set - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol, *args, universal_newlines=True) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol, *args, shell=True) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_exec, - asyncio.SubprocessProtocol, *args, bufsize=4096) - - def test_subprocess_shell_invalid_args(self): - # expected a string, not an int or a list - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_shell, - asyncio.SubprocessProtocol, 123) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_shell, - asyncio.SubprocessProtocol, [sys.executable, '-c', 'pass']) - - # universal_newlines, shell, bufsize must not be set - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_shell, - asyncio.SubprocessProtocol, 'exit 0', universal_newlines=True) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_shell, - asyncio.SubprocessProtocol, 'exit 0', shell=True) - self.assertRaises(TypeError, - self.loop.run_until_complete, self.loop.subprocess_shell, - asyncio.SubprocessProtocol, 'exit 0', bufsize=4096) - - def test_default_exc_handler_callback(self): - self.loop._process_events = mock.Mock() - - def zero_error(fut): - fut.set_result(True) - 1/0 - - # Test call_soon (events.Handle) - with mock.patch('asyncio.base_events.logger') as log: - fut = self.loop.create_future() - self.loop.call_soon(zero_error, fut) - fut.add_done_callback(lambda fut: self.loop.stop()) - self.loop.run_forever() - log.error.assert_called_with( - test_utils.MockPattern('Exception in callback.*zero'), - exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - - # Test call_later (events.TimerHandle) - with mock.patch('asyncio.base_events.logger') as log: - fut = self.loop.create_future() - self.loop.call_later(0.01, zero_error, fut) - fut.add_done_callback(lambda fut: self.loop.stop()) - self.loop.run_forever() - log.error.assert_called_with( - test_utils.MockPattern('Exception in callback.*zero'), - exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - - def test_default_exc_handler_coro(self): - self.loop._process_events = mock.Mock() - - async def zero_error_coro(): - await asyncio.sleep(0.01) - 1/0 - - # Test Future.__del__ - with mock.patch('asyncio.base_events.logger') as log: - fut = asyncio.ensure_future(zero_error_coro(), loop=self.loop) - fut.add_done_callback(lambda *args: self.loop.stop()) - self.loop.run_forever() - fut = None # Trigger Future.__del__ or futures._TracebackLogger - support.gc_collect() - if PY34: - # Future.__del__ in Python 3.4 logs error with - # an actual exception context - log.error.assert_called_with( - test_utils.MockPattern('.*exception was never retrieved'), - exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - else: - # futures._TracebackLogger logs only textual traceback - log.error.assert_called_with( - test_utils.MockPattern( - '.*exception was never retrieved.*ZeroDiv'), - exc_info=False) - - def test_set_exc_handler_invalid(self): - with self.assertRaisesRegex(TypeError, 'A callable object or None'): - self.loop.set_exception_handler('spam') - - def test_set_exc_handler_custom(self): - def zero_error(): - 1/0 - - def run_loop(): - handle = self.loop.call_soon(zero_error) - self.loop._run_once() - return handle - - self.loop.set_debug(True) - self.loop._process_events = mock.Mock() - - self.assertIsNone(self.loop.get_exception_handler()) - mock_handler = mock.Mock() - self.loop.set_exception_handler(mock_handler) - self.assertIs(self.loop.get_exception_handler(), mock_handler) - handle = run_loop() - mock_handler.assert_called_with(self.loop, { - 'exception': MOCK_ANY, - 'message': test_utils.MockPattern( - 'Exception in callback.*zero_error'), - 'handle': handle, - 'source_traceback': handle._source_traceback, - }) - mock_handler.reset_mock() - - self.loop.set_exception_handler(None) - with mock.patch('asyncio.base_events.logger') as log: - run_loop() - log.error.assert_called_with( - test_utils.MockPattern( - 'Exception in callback.*zero'), - exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - - assert not mock_handler.called - - def test_set_exc_handler_broken(self): - def run_loop(): - def zero_error(): - 1/0 - self.loop.call_soon(zero_error) - self.loop._run_once() - - def handler(loop, context): - raise AttributeError('spam') - - self.loop._process_events = mock.Mock() - - self.loop.set_exception_handler(handler) - - with mock.patch('asyncio.base_events.logger') as log: - run_loop() - log.error.assert_called_with( - test_utils.MockPattern( - 'Unhandled error in exception handler'), - exc_info=(AttributeError, MOCK_ANY, MOCK_ANY)) - - def test_default_exc_handler_broken(self): - _context = None - - class Loop(base_events.BaseEventLoop): - - _selector = mock.Mock() - _process_events = mock.Mock() - - def default_exception_handler(self, context): - nonlocal _context - _context = context - # Simulates custom buggy "default_exception_handler" - raise ValueError('spam') - - loop = Loop() - self.addCleanup(loop.close) - asyncio.set_event_loop(loop) - - def run_loop(): - def zero_error(): - 1/0 - loop.call_soon(zero_error) - loop._run_once() - - with mock.patch('asyncio.base_events.logger') as log: - run_loop() - log.error.assert_called_with( - 'Exception in default exception handler', - exc_info=True) - - def custom_handler(loop, context): - raise ValueError('ham') - - _context = None - loop.set_exception_handler(custom_handler) - with mock.patch('asyncio.base_events.logger') as log: - run_loop() - log.error.assert_called_with( - test_utils.MockPattern('Exception in default exception.*' - 'while handling.*in custom'), - exc_info=True) - - # Check that original context was passed to default - # exception handler. - self.assertIn('context', _context) - self.assertIs(type(_context['context']['exception']), - ZeroDivisionError) - - def test_set_task_factory_invalid(self): - with self.assertRaisesRegex( - TypeError, 'task factory must be a callable or None'): - - self.loop.set_task_factory(1) - - self.assertIsNone(self.loop.get_task_factory()) - - def test_set_task_factory(self): - self.loop._process_events = mock.Mock() - - class MyTask(asyncio.Task): - pass - - async def coro(): - pass - - factory = lambda loop, coro: MyTask(coro, loop=loop) - - self.assertIsNone(self.loop.get_task_factory()) - self.loop.set_task_factory(factory) - self.assertIs(self.loop.get_task_factory(), factory) - - task = self.loop.create_task(coro()) - self.assertTrue(isinstance(task, MyTask)) - self.loop.run_until_complete(task) - - self.loop.set_task_factory(None) - self.assertIsNone(self.loop.get_task_factory()) - - task = self.loop.create_task(coro()) - self.assertTrue(isinstance(task, asyncio.Task)) - self.assertFalse(isinstance(task, MyTask)) - self.loop.run_until_complete(task) - - def test_env_var_debug(self): - code = '\n'.join(( - 'import asyncio', - 'loop = asyncio.get_event_loop()', - 'print(loop.get_debug())')) - - # Test with -E to not fail if the unit test was run with - # PYTHONASYNCIODEBUG set to a non-empty string - sts, stdout, stderr = assert_python_ok('-E', '-c', code) - self.assertEqual(stdout.rstrip(), b'False') - - sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='', - PYTHONDEVMODE='') - self.assertEqual(stdout.rstrip(), b'False') - - sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='1', - PYTHONDEVMODE='') - self.assertEqual(stdout.rstrip(), b'True') - - sts, stdout, stderr = assert_python_ok('-E', '-c', code, - PYTHONASYNCIODEBUG='1') - self.assertEqual(stdout.rstrip(), b'False') - - # -X dev - sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev', - '-c', code) - self.assertEqual(stdout.rstrip(), b'True') - - def test_create_task(self): - class MyTask(asyncio.Task): - pass - - async def test(): - pass - - class EventLoop(base_events.BaseEventLoop): - def create_task(self, coro): - return MyTask(coro, loop=loop) - - loop = EventLoop() - self.set_event_loop(loop) - - coro = test() - task = asyncio.ensure_future(coro, loop=loop) - self.assertIsInstance(task, MyTask) - - # make warnings quiet - task._log_destroy_pending = False - coro.close() - - def test_create_named_task_with_default_factory(self): - async def test(): - pass - - loop = asyncio.new_event_loop() - task = loop.create_task(test(), name='test_task') - try: - self.assertEqual(task.get_name(), 'test_task') - finally: - loop.run_until_complete(task) - loop.close() - - def test_create_named_task_with_custom_factory(self): - def task_factory(loop, coro): - return asyncio.Task(coro, loop=loop) - - async def test(): - pass - - loop = asyncio.new_event_loop() - loop.set_task_factory(task_factory) - task = loop.create_task(test(), name='test_task') - try: - self.assertEqual(task.get_name(), 'test_task') - finally: - loop.run_until_complete(task) - loop.close() - - def test_run_forever_keyboard_interrupt(self): - # Python issue #22601: ensure that the temporary task created by - # run_forever() consumes the KeyboardInterrupt and so don't log - # a warning - async def raise_keyboard_interrupt(): - raise KeyboardInterrupt - - self.loop._process_events = mock.Mock() - self.loop.call_exception_handler = mock.Mock() - - try: - self.loop.run_until_complete(raise_keyboard_interrupt()) - except KeyboardInterrupt: - pass - self.loop.close() - support.gc_collect() - - self.assertFalse(self.loop.call_exception_handler.called) - - def test_run_until_complete_baseexception(self): - # Python issue #22429: run_until_complete() must not schedule a pending - # call to stop() if the future raised a BaseException - async def raise_keyboard_interrupt(): - raise KeyboardInterrupt - - self.loop._process_events = mock.Mock() - - try: - self.loop.run_until_complete(raise_keyboard_interrupt()) - except KeyboardInterrupt: - pass - - def func(): - self.loop.stop() - func.called = True - func.called = False - try: - self.loop.call_soon(func) - self.loop.run_forever() - except KeyboardInterrupt: - pass - self.assertTrue(func.called) - - def test_single_selecter_event_callback_after_stopping(self): - # Python issue #25593: A stopped event loop may cause event callbacks - # to run more than once. - event_sentinel = object() - callcount = 0 - doer = None - - def proc_events(event_list): - nonlocal doer - if event_sentinel in event_list: - doer = self.loop.call_soon(do_event) - - def do_event(): - nonlocal callcount - callcount += 1 - self.loop.call_soon(clear_selector) - - def clear_selector(): - doer.cancel() - self.loop._selector.select.return_value = () - - self.loop._process_events = proc_events - self.loop._selector.select.return_value = (event_sentinel,) - - for i in range(1, 3): - with self.subTest('Loop %d/2' % i): - self.loop.call_soon(self.loop.stop) - self.loop.run_forever() - self.assertEqual(callcount, 1) - - def test_run_once(self): - # Simple test for test_utils.run_once(). It may seem strange - # to have a test for this (the function isn't even used!) but - # it's a de-factor standard API for library tests. This tests - # the idiom: loop.call_soon(loop.stop); loop.run_forever(). - count = 0 - - def callback(): - nonlocal count - count += 1 - - self.loop._process_events = mock.Mock() - self.loop.call_soon(callback) - test_utils.run_once(self.loop) - self.assertEqual(count, 1) - - def test_run_forever_pre_stopped(self): - # Test that the old idiom for pre-stopping the loop works. - self.loop._process_events = mock.Mock() - self.loop.stop() - self.loop.run_forever() - self.loop._selector.select.assert_called_once_with(0) - - async def leave_unfinalized_asyncgen(self): - # Create an async generator, iterate it partially, and leave it - # to be garbage collected. - # Used in async generator finalization tests. - # Depends on implementation details of garbage collector. Changes - # in gc may break this function. - status = {'started': False, - 'stopped': False, - 'finalized': False} - - async def agen(): - status['started'] = True - try: - for item in ['ZERO', 'ONE', 'TWO', 'THREE', 'FOUR']: - yield item - finally: - status['finalized'] = True - - ag = agen() - ai = ag.__aiter__() - - async def iter_one(): - try: - item = await ai.__anext__() - except StopAsyncIteration: - return - if item == 'THREE': - status['stopped'] = True - return - asyncio.create_task(iter_one()) - - asyncio.create_task(iter_one()) - return status - - def test_asyncgen_finalization_by_gc(self): - # Async generators should be finalized when garbage collected. - self.loop._process_events = mock.Mock() - self.loop._write_to_self = mock.Mock() - with support.disable_gc(): - status = self.loop.run_until_complete(self.leave_unfinalized_asyncgen()) - while not status['stopped']: - test_utils.run_briefly(self.loop) - self.assertTrue(status['started']) - self.assertTrue(status['stopped']) - self.assertFalse(status['finalized']) - support.gc_collect() - test_utils.run_briefly(self.loop) - self.assertTrue(status['finalized']) - - def test_asyncgen_finalization_by_gc_in_other_thread(self): - # Python issue 34769: If garbage collector runs in another - # thread, async generators will not finalize in debug - # mode. - self.loop._process_events = mock.Mock() - self.loop._write_to_self = mock.Mock() - self.loop.set_debug(True) - with support.disable_gc(): - status = self.loop.run_until_complete(self.leave_unfinalized_asyncgen()) - while not status['stopped']: - test_utils.run_briefly(self.loop) - self.assertTrue(status['started']) - self.assertTrue(status['stopped']) - self.assertFalse(status['finalized']) - self.loop.run_until_complete( - self.loop.run_in_executor(None, support.gc_collect)) - test_utils.run_briefly(self.loop) - self.assertTrue(status['finalized']) - - -class MyProto(asyncio.Protocol): - done = None - - def __init__(self, create_future=False): - self.state = 'INITIAL' - self.nbytes = 0 - if create_future: - self.done = asyncio.get_running_loop().create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') - - def data_received(self, data): - assert self.state == 'CONNECTED', self.state - self.nbytes += len(data) - - def eof_received(self): - assert self.state == 'CONNECTED', self.state - self.state = 'EOF' - - def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class MyDatagramProto(asyncio.DatagramProtocol): - done = None - - def __init__(self, create_future=False, loop=None): - self.state = 'INITIAL' - self.nbytes = 0 - if create_future: - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'INITIALIZED' - - def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state - self.nbytes += len(data) - - def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state - - def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class BaseEventLoopWithSelectorTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.SelectorEventLoop() - self.set_event_loop(self.loop) - - @mock.patch('socket.getnameinfo') - def test_getnameinfo(self, m_gai): - m_gai.side_effect = lambda *args: 42 - r = self.loop.run_until_complete(self.loop.getnameinfo(('abc', 123))) - self.assertEqual(r, 42) - - @patch_socket - def test_create_connection_multiple_errors(self, m_socket): - - class MyProto(asyncio.Protocol): - pass - - async def getaddrinfo(*args, **kw): - return [(2, 1, 6, '', ('107.6.106.82', 80)), - (2, 1, 6, '', ('107.6.106.82', 80))] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - idx = -1 - errors = ['err1', 'err2'] - - def _socket(*args, **kw): - nonlocal idx, errors - idx += 1 - raise OSError(errors[idx]) - - m_socket.socket = _socket - - self.loop.getaddrinfo = getaddrinfo_task - - coro = self.loop.create_connection(MyProto, 'example.com', 80) - with self.assertRaises(OSError) as cm: - self.loop.run_until_complete(coro) - - self.assertEqual(str(cm.exception), 'Multiple exceptions: err1, err2') - - @patch_socket - def test_create_connection_timeout(self, m_socket): - # Ensure that the socket is closed on timeout - sock = mock.Mock() - m_socket.socket.return_value = sock - - def getaddrinfo(*args, **kw): - fut = self.loop.create_future() - addr = (socket.AF_INET, socket.SOCK_STREAM, 0, '', - ('127.0.0.1', 80)) - fut.set_result([addr]) - return fut - self.loop.getaddrinfo = getaddrinfo - - with mock.patch.object(self.loop, 'sock_connect', - side_effect=asyncio.TimeoutError): - coro = self.loop.create_connection(MyProto, '127.0.0.1', 80) - with self.assertRaises(asyncio.TimeoutError): - self.loop.run_until_complete(coro) - self.assertTrue(sock.close.called) - - def test_create_connection_host_port_sock(self): - coro = self.loop.create_connection( - MyProto, 'example.com', 80, sock=object()) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - def test_create_connection_wrong_sock(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with sock: - coro = self.loop.create_connection(MyProto, sock=sock) - with self.assertRaisesRegex(ValueError, - 'A Stream Socket was expected'): - self.loop.run_until_complete(coro) - - def test_create_server_wrong_sock(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with sock: - coro = self.loop.create_server(MyProto, sock=sock) - with self.assertRaisesRegex(ValueError, - 'A Stream Socket was expected'): - self.loop.run_until_complete(coro) - - def test_create_server_ssl_timeout_for_plain_socket(self): - coro = self.loop.create_server( - MyProto, 'example.com', 80, ssl_handshake_timeout=1) - with self.assertRaisesRegex( - ValueError, - 'ssl_handshake_timeout is only meaningful with ssl'): - self.loop.run_until_complete(coro) - - @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), - 'no socket.SOCK_NONBLOCK (linux only)') - def test_create_server_stream_bittype(self): - sock = socket.socket( - socket.AF_INET, socket.SOCK_STREAM | socket.SOCK_NONBLOCK) - with sock: - coro = self.loop.create_server(lambda: None, sock=sock) - srv = self.loop.run_until_complete(coro) - srv.close() - self.loop.run_until_complete(srv.wait_closed()) - - @unittest.skipUnless(support.IPV6_ENABLED, 'no IPv6 support') - def test_create_server_ipv6(self): - async def main(): - with self.assertWarns(DeprecationWarning): - srv = await asyncio.start_server( - lambda: None, '::1', 0, loop=self.loop) - try: - self.assertGreater(len(srv.sockets), 0) - finally: - srv.close() - await srv.wait_closed() - - try: - self.loop.run_until_complete(main()) - except OSError as ex: - if (hasattr(errno, 'EADDRNOTAVAIL') and - ex.errno == errno.EADDRNOTAVAIL): - self.skipTest('failed to bind to ::1') - else: - raise - - def test_create_datagram_endpoint_wrong_sock(self): - sock = socket.socket(socket.AF_INET) - with sock: - coro = self.loop.create_datagram_endpoint(MyProto, sock=sock) - with self.assertRaisesRegex(ValueError, - 'A UDP Socket was expected'): - self.loop.run_until_complete(coro) - - def test_create_connection_no_host_port_sock(self): - coro = self.loop.create_connection(MyProto) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - def test_create_connection_no_getaddrinfo(self): - async def getaddrinfo(*args, **kw): - return [] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - self.loop.getaddrinfo = getaddrinfo_task - coro = self.loop.create_connection(MyProto, 'example.com', 80) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - def test_create_connection_connect_err(self): - async def getaddrinfo(*args, **kw): - return [(2, 1, 6, '', ('107.6.106.82', 80))] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.side_effect = OSError - - coro = self.loop.create_connection(MyProto, 'example.com', 80) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - def test_create_connection_multiple(self): - async def getaddrinfo(*args, **kw): - return [(2, 1, 6, '', ('0.0.0.1', 80)), - (2, 1, 6, '', ('0.0.0.2', 80))] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.side_effect = OSError - - coro = self.loop.create_connection( - MyProto, 'example.com', 80, family=socket.AF_INET) - with self.assertRaises(OSError): - self.loop.run_until_complete(coro) - - @patch_socket - def test_create_connection_multiple_errors_local_addr(self, m_socket): - - def bind(addr): - if addr[0] == '0.0.0.1': - err = OSError('Err') - err.strerror = 'Err' - raise err - - m_socket.socket.return_value.bind = bind - - async def getaddrinfo(*args, **kw): - return [(2, 1, 6, '', ('0.0.0.1', 80)), - (2, 1, 6, '', ('0.0.0.2', 80))] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.side_effect = OSError('Err2') - - coro = self.loop.create_connection( - MyProto, 'example.com', 80, family=socket.AF_INET, - local_addr=(None, 8080)) - with self.assertRaises(OSError) as cm: - self.loop.run_until_complete(coro) - - self.assertTrue(str(cm.exception).startswith('Multiple exceptions: ')) - self.assertTrue(m_socket.socket.return_value.close.called) - - def _test_create_connection_ip_addr(self, m_socket, allow_inet_pton): - # Test the fallback code, even if this system has inet_pton. - if not allow_inet_pton: - del m_socket.inet_pton - - m_socket.getaddrinfo = socket.getaddrinfo - sock = m_socket.socket.return_value - - self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False - self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False - - coro = self.loop.create_connection(asyncio.Protocol, '1.2.3.4', 80) - t, p = self.loop.run_until_complete(coro) - try: - sock.connect.assert_called_with(('1.2.3.4', 80)) - _, kwargs = m_socket.socket.call_args - self.assertEqual(kwargs['family'], m_socket.AF_INET) - self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) - finally: - t.close() - test_utils.run_briefly(self.loop) # allow transport to close - - if support.IPV6_ENABLED: - sock.family = socket.AF_INET6 - coro = self.loop.create_connection(asyncio.Protocol, '::1', 80) - t, p = self.loop.run_until_complete(coro) - try: - # Without inet_pton we use getaddrinfo, which transforms - # ('::1', 80) to ('::1', 80, 0, 0). The last 0s are flow info, - # scope id. - [address] = sock.connect.call_args[0] - host, port = address[:2] - self.assertRegex(host, r'::(0\.)*1') - self.assertEqual(port, 80) - _, kwargs = m_socket.socket.call_args - self.assertEqual(kwargs['family'], m_socket.AF_INET6) - self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) - finally: - t.close() - test_utils.run_briefly(self.loop) # allow transport to close - - @unittest.skipUnless(support.IPV6_ENABLED, 'no IPv6 support') - @unittest.skipIf(sys.platform.startswith('aix'), - "bpo-25545: IPv6 scope id and getaddrinfo() behave differently on AIX") - @patch_socket - def test_create_connection_ipv6_scope(self, m_socket): - m_socket.getaddrinfo = socket.getaddrinfo - sock = m_socket.socket.return_value - sock.family = socket.AF_INET6 - - self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False - self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False - - coro = self.loop.create_connection(asyncio.Protocol, 'fe80::1%1', 80) - t, p = self.loop.run_until_complete(coro) - try: - sock.connect.assert_called_with(('fe80::1', 80, 0, 1)) - _, kwargs = m_socket.socket.call_args - self.assertEqual(kwargs['family'], m_socket.AF_INET6) - self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) - finally: - t.close() - test_utils.run_briefly(self.loop) # allow transport to close - - @patch_socket - def test_create_connection_ip_addr(self, m_socket): - self._test_create_connection_ip_addr(m_socket, True) - - @patch_socket - def test_create_connection_no_inet_pton(self, m_socket): - self._test_create_connection_ip_addr(m_socket, False) - - @patch_socket - def test_create_connection_service_name(self, m_socket): - m_socket.getaddrinfo = socket.getaddrinfo - sock = m_socket.socket.return_value - - self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False - self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False - - for service, port in ('http', 80), (b'http', 80): - coro = self.loop.create_connection(asyncio.Protocol, - '127.0.0.1', service) - - t, p = self.loop.run_until_complete(coro) - try: - sock.connect.assert_called_with(('127.0.0.1', port)) - _, kwargs = m_socket.socket.call_args - self.assertEqual(kwargs['family'], m_socket.AF_INET) - self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM) - finally: - t.close() - test_utils.run_briefly(self.loop) # allow transport to close - - for service in 'nonsense', b'nonsense': - coro = self.loop.create_connection(asyncio.Protocol, - '127.0.0.1', service) - - with self.assertRaises(OSError): - self.loop.run_until_complete(coro) - - def test_create_connection_no_local_addr(self): - async def getaddrinfo(host, *args, **kw): - if host == 'example.com': - return [(2, 1, 6, '', ('107.6.106.82', 80)), - (2, 1, 6, '', ('107.6.106.82', 80))] - else: - return [] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - self.loop.getaddrinfo = getaddrinfo_task - - coro = self.loop.create_connection( - MyProto, 'example.com', 80, family=socket.AF_INET, - local_addr=(None, 8080)) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - @patch_socket - def test_create_connection_bluetooth(self, m_socket): - # See http://bugs.python.org/issue27136, fallback to getaddrinfo when - # we can't recognize an address is resolved, e.g. a Bluetooth address. - addr = ('00:01:02:03:04:05', 1) - - def getaddrinfo(host, port, *args, **kw): - assert (host, port) == addr - return [(999, 1, 999, '', (addr, 1))] - - m_socket.getaddrinfo = getaddrinfo - sock = m_socket.socket() - coro = self.loop.sock_connect(sock, addr) - self.loop.run_until_complete(coro) - - def test_create_connection_ssl_server_hostname_default(self): - self.loop.getaddrinfo = mock.Mock() - - def mock_getaddrinfo(*args, **kwds): - f = self.loop.create_future() - f.set_result([(socket.AF_INET, socket.SOCK_STREAM, - socket.SOL_TCP, '', ('1.2.3.4', 80))]) - return f - - self.loop.getaddrinfo.side_effect = mock_getaddrinfo - self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.return_value = self.loop.create_future() - self.loop.sock_connect.return_value.set_result(None) - self.loop._make_ssl_transport = mock.Mock() - - class _SelectorTransportMock: - _sock = None - - def get_extra_info(self, key): - return mock.Mock() - - def close(self): - self._sock.close() - - def mock_make_ssl_transport(sock, protocol, sslcontext, waiter, - **kwds): - waiter.set_result(None) - transport = _SelectorTransportMock() - transport._sock = sock - return transport - - self.loop._make_ssl_transport.side_effect = mock_make_ssl_transport - ANY = mock.ANY - handshake_timeout = object() - # First try the default server_hostname. - self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection( - MyProto, 'python.org', 80, ssl=True, - ssl_handshake_timeout=handshake_timeout) - transport, _ = self.loop.run_until_complete(coro) - transport.close() - self.loop._make_ssl_transport.assert_called_with( - ANY, ANY, ANY, ANY, - server_side=False, - server_hostname='python.org', - ssl_handshake_timeout=handshake_timeout) - # Next try an explicit server_hostname. - self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection( - MyProto, 'python.org', 80, ssl=True, - server_hostname='perl.com', - ssl_handshake_timeout=handshake_timeout) - transport, _ = self.loop.run_until_complete(coro) - transport.close() - self.loop._make_ssl_transport.assert_called_with( - ANY, ANY, ANY, ANY, - server_side=False, - server_hostname='perl.com', - ssl_handshake_timeout=handshake_timeout) - # Finally try an explicit empty server_hostname. - self.loop._make_ssl_transport.reset_mock() - coro = self.loop.create_connection( - MyProto, 'python.org', 80, ssl=True, - server_hostname='', - ssl_handshake_timeout=handshake_timeout) - transport, _ = self.loop.run_until_complete(coro) - transport.close() - self.loop._make_ssl_transport.assert_called_with( - ANY, ANY, ANY, ANY, - server_side=False, - server_hostname='', - ssl_handshake_timeout=handshake_timeout) - - def test_create_connection_no_ssl_server_hostname_errors(self): - # When not using ssl, server_hostname must be None. - coro = self.loop.create_connection(MyProto, 'python.org', 80, - server_hostname='') - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - coro = self.loop.create_connection(MyProto, 'python.org', 80, - server_hostname='python.org') - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - def test_create_connection_ssl_server_hostname_errors(self): - # When using ssl, server_hostname may be None if host is non-empty. - coro = self.loop.create_connection(MyProto, '', 80, ssl=True) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - coro = self.loop.create_connection(MyProto, None, 80, ssl=True) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - sock = socket.socket() - coro = self.loop.create_connection(MyProto, None, None, - ssl=True, sock=sock) - self.addCleanup(sock.close) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - def test_create_connection_ssl_timeout_for_plain_socket(self): - coro = self.loop.create_connection( - MyProto, 'example.com', 80, ssl_handshake_timeout=1) - with self.assertRaisesRegex( - ValueError, - 'ssl_handshake_timeout is only meaningful with ssl'): - self.loop.run_until_complete(coro) - - def test_create_server_empty_host(self): - # if host is empty string use None instead - host = object() - - async def getaddrinfo(*args, **kw): - nonlocal host - host = args[0] - return [] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - self.loop.getaddrinfo = getaddrinfo_task - fut = self.loop.create_server(MyProto, '', 0) - self.assertRaises(OSError, self.loop.run_until_complete, fut) - self.assertIsNone(host) - - def test_create_server_host_port_sock(self): - fut = self.loop.create_server( - MyProto, '0.0.0.0', 0, sock=object()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - def test_create_server_no_host_port_sock(self): - fut = self.loop.create_server(MyProto) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - def test_create_server_no_getaddrinfo(self): - getaddrinfo = self.loop.getaddrinfo = mock.Mock() - getaddrinfo.return_value = self.loop.create_future() - getaddrinfo.return_value.set_result(None) - - f = self.loop.create_server(MyProto, 'python.org', 0) - self.assertRaises(OSError, self.loop.run_until_complete, f) - - @patch_socket - def test_create_server_nosoreuseport(self, m_socket): - m_socket.getaddrinfo = socket.getaddrinfo - del m_socket.SO_REUSEPORT - m_socket.socket.return_value = mock.Mock() - - f = self.loop.create_server( - MyProto, '0.0.0.0', 0, reuse_port=True) - - self.assertRaises(ValueError, self.loop.run_until_complete, f) - - @patch_socket - def test_create_server_soreuseport_only_defined(self, m_socket): - m_socket.getaddrinfo = socket.getaddrinfo - m_socket.socket.return_value = mock.Mock() - m_socket.SO_REUSEPORT = -1 - - f = self.loop.create_server( - MyProto, '0.0.0.0', 0, reuse_port=True) - - self.assertRaises(ValueError, self.loop.run_until_complete, f) - - @patch_socket - def test_create_server_cant_bind(self, m_socket): - - class Err(OSError): - strerror = 'error' - - m_socket.getaddrinfo.return_value = [ - (2, 1, 6, '', ('127.0.0.1', 10100))] - m_socket.getaddrinfo._is_coroutine = False - m_sock = m_socket.socket.return_value = mock.Mock() - m_sock.bind.side_effect = Err - - fut = self.loop.create_server(MyProto, '0.0.0.0', 0) - self.assertRaises(OSError, self.loop.run_until_complete, fut) - self.assertTrue(m_sock.close.called) - - @patch_socket - def test_create_datagram_endpoint_no_addrinfo(self, m_socket): - m_socket.getaddrinfo.return_value = [] - m_socket.getaddrinfo._is_coroutine = False - - coro = self.loop.create_datagram_endpoint( - MyDatagramProto, local_addr=('localhost', 0)) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - def test_create_datagram_endpoint_addr_error(self): - coro = self.loop.create_datagram_endpoint( - MyDatagramProto, local_addr='localhost') - self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) - coro = self.loop.create_datagram_endpoint( - MyDatagramProto, local_addr=('localhost', 1, 2, 3)) - self.assertRaises( - AssertionError, self.loop.run_until_complete, coro) - - def test_create_datagram_endpoint_connect_err(self): - self.loop.sock_connect = mock.Mock() - self.loop.sock_connect.side_effect = OSError - - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, remote_addr=('127.0.0.1', 0)) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - def test_create_datagram_endpoint_allow_broadcast(self): - protocol = MyDatagramProto(create_future=True, loop=self.loop) - self.loop.sock_connect = sock_connect = mock.Mock() - sock_connect.return_value = [] - - coro = self.loop.create_datagram_endpoint( - lambda: protocol, - remote_addr=('127.0.0.1', 0), - allow_broadcast=True) - - transport, _ = self.loop.run_until_complete(coro) - self.assertFalse(sock_connect.called) - - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - - @patch_socket - def test_create_datagram_endpoint_socket_err(self, m_socket): - m_socket.getaddrinfo = socket.getaddrinfo - m_socket.socket.side_effect = OSError - - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, family=socket.AF_INET) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, local_addr=('127.0.0.1', 0)) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - - @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 not supported or enabled') - def test_create_datagram_endpoint_no_matching_family(self): - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, - remote_addr=('127.0.0.1', 0), local_addr=('::1', 0)) - self.assertRaises( - ValueError, self.loop.run_until_complete, coro) - - @patch_socket - def test_create_datagram_endpoint_setblk_err(self, m_socket): - m_socket.socket.return_value.setblocking.side_effect = OSError - - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, family=socket.AF_INET) - self.assertRaises( - OSError, self.loop.run_until_complete, coro) - self.assertTrue( - m_socket.socket.return_value.close.called) - - def test_create_datagram_endpoint_noaddr_nofamily(self): - coro = self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol) - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - @patch_socket - def test_create_datagram_endpoint_cant_bind(self, m_socket): - class Err(OSError): - pass - - m_socket.getaddrinfo = socket.getaddrinfo - m_sock = m_socket.socket.return_value = mock.Mock() - m_sock.bind.side_effect = Err - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, - local_addr=('127.0.0.1', 0), family=socket.AF_INET) - self.assertRaises(Err, self.loop.run_until_complete, fut) - self.assertTrue(m_sock.close.called) - - def test_create_datagram_endpoint_sock(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.bind(('127.0.0.1', 0)) - fut = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - sock=sock) - transport, protocol = self.loop.run_until_complete(fut) - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - def test_create_datagram_endpoint_sock_unix(self): - fut = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - family=socket.AF_UNIX) - transport, protocol = self.loop.run_until_complete(fut) - assert transport._sock.family == socket.AF_UNIX - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - - @support.skip_unless_bind_unix_socket - def test_create_datagram_endpoint_existing_sock_unix(self): - with test_utils.unix_socket_path() as path: - sock = socket.socket(socket.AF_UNIX, type=socket.SOCK_DGRAM) - sock.bind(path) - sock.close() - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - path, family=socket.AF_UNIX) - transport, protocol = self.loop.run_until_complete(coro) - transport.close() - self.loop.run_until_complete(protocol.done) - - def test_create_datagram_endpoint_sock_sockopts(self): - class FakeSock: - type = socket.SOCK_DGRAM - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, local_addr=('127.0.0.1', 0), sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, remote_addr=('127.0.0.1', 0), sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, family=1, sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, proto=1, sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, flags=1, sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, reuse_port=True, sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - fut = self.loop.create_datagram_endpoint( - MyDatagramProto, allow_broadcast=True, sock=FakeSock()) - self.assertRaises(ValueError, self.loop.run_until_complete, fut) - - def test_create_datagram_endpoint_sockopts(self): - # Socket options should not be applied unless asked for. - # SO_REUSEPORT is not available on all platforms. - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0)) - transport, protocol = self.loop.run_until_complete(coro) - sock = transport.get_extra_info('socket') - - reuseport_supported = hasattr(socket, 'SO_REUSEPORT') - - if reuseport_supported: - self.assertFalse( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_REUSEPORT)) - self.assertFalse( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_BROADCAST)) - - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_port=reuseport_supported, - allow_broadcast=True) - transport, protocol = self.loop.run_until_complete(coro) - sock = transport.get_extra_info('socket') - - self.assertFalse( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_REUSEADDR)) - if reuseport_supported: - self.assertTrue( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_REUSEPORT)) - self.assertTrue( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_BROADCAST)) - - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - - def test_create_datagram_endpoint_reuse_address_error(self): - # bpo-37228: Ensure that explicit passing of `reuse_address=True` - # raises an error, as it is not safe to use SO_REUSEADDR when using UDP - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_address=True) - - with self.assertRaises(ValueError): - self.loop.run_until_complete(coro) - - def test_create_datagram_endpoint_reuse_address_warning(self): - # bpo-37228: Deprecate *reuse_address* parameter - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_address=False) - - with self.assertWarns(DeprecationWarning): - self.loop.run_until_complete(coro) - - @patch_socket - def test_create_datagram_endpoint_nosoreuseport(self, m_socket): - del m_socket.SO_REUSEPORT - m_socket.socket.return_value = mock.Mock() - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_address=False, - reuse_port=True) - - self.assertRaises(ValueError, self.loop.run_until_complete, coro) - - @patch_socket - def test_create_datagram_endpoint_ip_addr(self, m_socket): - def getaddrinfo(*args, **kw): - self.fail('should not have called getaddrinfo') - - m_socket.getaddrinfo = getaddrinfo - m_socket.socket.return_value.bind = bind = mock.Mock() - self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False - - reuseport_supported = hasattr(socket, 'SO_REUSEPORT') - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(loop=self.loop), - local_addr=('1.2.3.4', 0), - reuse_address=False, - reuse_port=reuseport_supported) - - t, p = self.loop.run_until_complete(coro) - try: - bind.assert_called_with(('1.2.3.4', 0)) - m_socket.socket.assert_called_with(family=m_socket.AF_INET, - proto=m_socket.IPPROTO_UDP, - type=m_socket.SOCK_DGRAM) - finally: - t.close() - test_utils.run_briefly(self.loop) # allow transport to close - - def test_accept_connection_retry(self): - sock = mock.Mock() - sock.accept.side_effect = BlockingIOError() - - self.loop._accept_connection(MyProto, sock) - self.assertFalse(sock.close.called) - - @mock.patch('asyncio.base_events.logger') - def test_accept_connection_exception(self, m_log): - sock = mock.Mock() - sock.fileno.return_value = 10 - sock.accept.side_effect = OSError(errno.EMFILE, 'Too many open files') - self.loop._remove_reader = mock.Mock() - self.loop.call_later = mock.Mock() - - self.loop._accept_connection(MyProto, sock) - self.assertTrue(m_log.error.called) - self.assertFalse(sock.close.called) - self.loop._remove_reader.assert_called_with(10) - self.loop.call_later.assert_called_with( - constants.ACCEPT_RETRY_DELAY, - # self.loop._start_serving - mock.ANY, - MyProto, sock, None, None, mock.ANY, mock.ANY) - - def test_call_coroutine(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def simple_coroutine(): - pass - - self.loop.set_debug(True) - coro_func = simple_coroutine - coro_obj = coro_func() - self.addCleanup(coro_obj.close) - for func in (coro_func, coro_obj): - with self.assertRaises(TypeError): - self.loop.call_soon(func) - with self.assertRaises(TypeError): - self.loop.call_soon_threadsafe(func) - with self.assertRaises(TypeError): - self.loop.call_later(60, func) - with self.assertRaises(TypeError): - self.loop.call_at(self.loop.time() + 60, func) - with self.assertRaises(TypeError): - self.loop.run_until_complete( - self.loop.run_in_executor(None, func)) - - @mock.patch('asyncio.base_events.logger') - def test_log_slow_callbacks(self, m_logger): - def stop_loop_cb(loop): - loop.stop() - - async def stop_loop_coro(loop): - loop.stop() - - asyncio.set_event_loop(self.loop) - self.loop.set_debug(True) - self.loop.slow_callback_duration = 0.0 - - # slow callback - self.loop.call_soon(stop_loop_cb, self.loop) - self.loop.run_forever() - fmt, *args = m_logger.warning.call_args[0] - self.assertRegex(fmt % tuple(args), - "^Executing <Handle.*stop_loop_cb.*> " - "took .* seconds$") - - # slow task - asyncio.ensure_future(stop_loop_coro(self.loop), loop=self.loop) - self.loop.run_forever() - fmt, *args = m_logger.warning.call_args[0] - self.assertRegex(fmt % tuple(args), - "^Executing <Task.*stop_loop_coro.*> " - "took .* seconds$") - - -class RunningLoopTests(unittest.TestCase): - - def test_running_loop_within_a_loop(self): - async def runner(loop): - loop.run_forever() - - loop = asyncio.new_event_loop() - outer_loop = asyncio.new_event_loop() - try: - with self.assertRaisesRegex(RuntimeError, - 'while another loop is running'): - outer_loop.run_until_complete(runner(loop)) - finally: - loop.close() - outer_loop.close() - - -class BaseLoopSockSendfileTests(test_utils.TestCase): - - DATA = b"12345abcde" * 16 * 1024 # 160 KiB - - class MyProto(asyncio.Protocol): - - def __init__(self, loop): - self.started = False - self.closed = False - self.data = bytearray() - self.fut = loop.create_future() - self.transport = None - - def connection_made(self, transport): - self.started = True - self.transport = transport - - def data_received(self, data): - self.data.extend(data) - - def connection_lost(self, exc): - self.closed = True - self.fut.set_result(None) - self.transport = None - - async def wait_closed(self): - await self.fut - - @classmethod - def setUpClass(cls): - cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE - constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 - with open(support.TESTFN, 'wb') as fp: - fp.write(cls.DATA) - super().setUpClass() - - @classmethod - def tearDownClass(cls): - constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize - support.unlink(support.TESTFN) - super().tearDownClass() - - def setUp(self): - from asyncio.selector_events import BaseSelectorEventLoop - # BaseSelectorEventLoop() has no native implementation - self.loop = BaseSelectorEventLoop() - self.set_event_loop(self.loop) - self.file = open(support.TESTFN, 'rb') - self.addCleanup(self.file.close) - super().setUp() - - def make_socket(self, blocking=False): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(blocking) - self.addCleanup(sock.close) - return sock - - def run_loop(self, coro): - return self.loop.run_until_complete(coro) - - def prepare(self): - sock = self.make_socket() - proto = self.MyProto(self.loop) - server = self.run_loop(self.loop.create_server( - lambda: proto, support.HOST, 0, family=socket.AF_INET)) - addr = server.sockets[0].getsockname() - - for _ in range(10): - try: - self.run_loop(self.loop.sock_connect(sock, addr)) - except OSError: - self.run_loop(asyncio.sleep(0.5)) - continue - else: - break - else: - # One last try, so we get the exception - self.run_loop(self.loop.sock_connect(sock, addr)) - - def cleanup(): - server.close() - self.run_loop(server.wait_closed()) - sock.close() - if proto.transport is not None: - proto.transport.close() - self.run_loop(proto.wait_closed()) - - self.addCleanup(cleanup) - - return sock, proto - - def test__sock_sendfile_native_failure(self): - sock, proto = self.prepare() - - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "sendfile is not available"): - self.run_loop(self.loop._sock_sendfile_native(sock, self.file, - 0, None)) - - self.assertEqual(proto.data, b'') - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_no_fallback(self): - sock, proto = self.prepare() - - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "sendfile is not available"): - self.run_loop(self.loop.sock_sendfile(sock, self.file, - fallback=False)) - - self.assertEqual(self.file.tell(), 0) - self.assertEqual(proto.data, b'') - - def test_sock_sendfile_fallback(self): - sock, proto = self.prepare() - - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(self.file.tell(), len(self.DATA)) - self.assertEqual(proto.data, self.DATA) - - def test_sock_sendfile_fallback_offset_and_count(self): - sock, proto = self.prepare() - - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file, - 1000, 2000)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, 2000) - self.assertEqual(self.file.tell(), 3000) - self.assertEqual(proto.data, self.DATA[1000:3000]) - - def test_blocking_socket(self): - self.loop.set_debug(True) - sock = self.make_socket(blocking=True) - with self.assertRaisesRegex(ValueError, "must be non-blocking"): - self.run_loop(self.loop.sock_sendfile(sock, self.file)) - - def test_nonbinary_file(self): - sock = self.make_socket() - with open(support.TESTFN, 'r') as f: - with self.assertRaisesRegex(ValueError, "binary mode"): - self.run_loop(self.loop.sock_sendfile(sock, f)) - - def test_nonstream_socket(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.setblocking(False) - self.addCleanup(sock.close) - with self.assertRaisesRegex(ValueError, "only SOCK_STREAM type"): - self.run_loop(self.loop.sock_sendfile(sock, self.file)) - - def test_notint_count(self): - sock = self.make_socket() - with self.assertRaisesRegex(TypeError, - "count must be a positive integer"): - self.run_loop(self.loop.sock_sendfile(sock, self.file, 0, 'count')) - - def test_negative_count(self): - sock = self.make_socket() - with self.assertRaisesRegex(ValueError, - "count must be a positive integer"): - self.run_loop(self.loop.sock_sendfile(sock, self.file, 0, -1)) - - def test_notint_offset(self): - sock = self.make_socket() - with self.assertRaisesRegex(TypeError, - "offset must be a non-negative integer"): - self.run_loop(self.loop.sock_sendfile(sock, self.file, 'offset')) - - def test_negative_offset(self): - sock = self.make_socket() - with self.assertRaisesRegex(ValueError, - "offset must be a non-negative integer"): - self.run_loop(self.loop.sock_sendfile(sock, self.file, -1)) - - -class TestSelectorUtils(test_utils.TestCase): - def check_set_nodelay(self, sock): - opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) - self.assertFalse(opt) - - base_events._set_nodelay(sock) - - opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) - self.assertTrue(opt) - - @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'), - 'need socket.TCP_NODELAY') - def test_set_nodelay(self): - sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, - proto=socket.IPPROTO_TCP) - with sock: - self.check_set_nodelay(sock) - - sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, - proto=socket.IPPROTO_TCP) - with sock: - sock.setblocking(False) - self.check_set_nodelay(sock) - - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_buffered_proto.py b/Lib/test/test_asyncio/test_buffered_proto.py deleted file mode 100644 index f24e363..0000000 --- a/Lib/test/test_asyncio/test_buffered_proto.py +++ /dev/null @@ -1,89 +0,0 @@ -import asyncio -import unittest - -from test.test_asyncio import functional as func_tests - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class ReceiveStuffProto(asyncio.BufferedProtocol): - def __init__(self, cb, con_lost_fut): - self.cb = cb - self.con_lost_fut = con_lost_fut - - def get_buffer(self, sizehint): - self.buffer = bytearray(100) - return self.buffer - - def buffer_updated(self, nbytes): - self.cb(self.buffer[:nbytes]) - - def connection_lost(self, exc): - if exc is None: - self.con_lost_fut.set_result(None) - else: - self.con_lost_fut.set_exception(exc) - - -class BaseTestBufferedProtocol(func_tests.FunctionalTestCaseMixin): - - def new_loop(self): - raise NotImplementedError - - def test_buffered_proto_create_connection(self): - - NOISE = b'12345678+' * 1024 - - async def client(addr): - data = b'' - - def on_buf(buf): - nonlocal data - data += buf - if data == NOISE: - tr.write(b'1') - - conn_lost_fut = self.loop.create_future() - - tr, pr = await self.loop.create_connection( - lambda: ReceiveStuffProto(on_buf, conn_lost_fut), *addr) - - await conn_lost_fut - - async def on_server_client(reader, writer): - writer.write(NOISE) - await reader.readexactly(1) - writer.close() - await writer.wait_closed() - - srv = self.loop.run_until_complete( - asyncio.start_server( - on_server_client, '127.0.0.1', 0)) - - addr = srv.sockets[0].getsockname() - self.loop.run_until_complete( - asyncio.wait_for(client(addr), 5)) - - srv.close() - self.loop.run_until_complete(srv.wait_closed()) - - -class BufferedProtocolSelectorTests(BaseTestBufferedProtocol, - unittest.TestCase): - - def new_loop(self): - return asyncio.SelectorEventLoop() - - -@unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') -class BufferedProtocolProactorTests(BaseTestBufferedProtocol, - unittest.TestCase): - - def new_loop(self): - return asyncio.ProactorEventLoop() - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_context.py b/Lib/test/test_asyncio/test_context.py deleted file mode 100644 index c309faa..0000000 --- a/Lib/test/test_asyncio/test_context.py +++ /dev/null @@ -1,33 +0,0 @@ -import asyncio -import decimal -import unittest - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class DecimalContextTest(unittest.TestCase): - - def test_asyncio_task_decimal_context(self): - async def fractions(t, precision, x, y): - with decimal.localcontext() as ctx: - ctx.prec = precision - a = decimal.Decimal(x) / decimal.Decimal(y) - await asyncio.sleep(t) - b = decimal.Decimal(x) / decimal.Decimal(y ** 2) - return a, b - - async def main(): - r1, r2 = await asyncio.gather( - fractions(0.1, 3, 1, 3), fractions(0.2, 6, 1, 3)) - - return r1, r2 - - r1, r2 = asyncio.run(main()) - - self.assertEqual(str(r1[0]), '0.333') - self.assertEqual(str(r1[1]), '0.111') - - self.assertEqual(str(r2[0]), '0.333333') - self.assertEqual(str(r2[1]), '0.111111') diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py deleted file mode 100644 index 4cbd1ed..0000000 --- a/Lib/test/test_asyncio/test_events.py +++ /dev/null @@ -1,2777 +0,0 @@ -"""Tests for events.py.""" - -import collections.abc -import concurrent.futures -import functools -import io -import os -import platform -import re -import signal -import socket -try: - import ssl -except ImportError: - ssl = None -import subprocess -import sys -import threading -import time -import errno -import unittest -from unittest import mock -import weakref - -if sys.platform != 'win32': - import tty - -import asyncio -from asyncio import coroutines -from asyncio import events -from asyncio import proactor_events -from asyncio import selector_events -from test.test_asyncio import utils as test_utils -from test import support -from test.support import ALWAYS_EQ, LARGEST, SMALLEST - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -def broken_unix_getsockname(): - """Return True if the platform is Mac OS 10.4 or older.""" - if sys.platform.startswith("aix"): - return True - elif sys.platform != 'darwin': - return False - version = platform.mac_ver()[0] - version = tuple(map(int, version.split('.'))) - return version < (10, 5) - - -def _test_get_event_loop_new_process__sub_proc(): - async def doit(): - return 'hello' - - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - return loop.run_until_complete(doit()) - - -class CoroLike: - def send(self, v): - pass - - def throw(self, *exc): - pass - - def close(self): - pass - - def __await__(self): - pass - - -class MyBaseProto(asyncio.Protocol): - connected = None - done = None - - def __init__(self, loop=None): - self.transport = None - self.state = 'INITIAL' - self.nbytes = 0 - if loop is not None: - self.connected = loop.create_future() - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - if self.connected: - self.connected.set_result(None) - - def data_received(self, data): - assert self.state == 'CONNECTED', self.state - self.nbytes += len(data) - - def eof_received(self): - assert self.state == 'CONNECTED', self.state - self.state = 'EOF' - - def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class MyProto(MyBaseProto): - def connection_made(self, transport): - super().connection_made(transport) - transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') - - -class MyDatagramProto(asyncio.DatagramProtocol): - done = None - - def __init__(self, loop=None): - self.state = 'INITIAL' - self.nbytes = 0 - if loop is not None: - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'INITIALIZED' - - def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state - self.nbytes += len(data) - - def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state - - def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class MyReadPipeProto(asyncio.Protocol): - done = None - - def __init__(self, loop=None): - self.state = ['INITIAL'] - self.nbytes = 0 - self.transport = None - if loop is not None: - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == ['INITIAL'], self.state - self.state.append('CONNECTED') - - def data_received(self, data): - assert self.state == ['INITIAL', 'CONNECTED'], self.state - self.nbytes += len(data) - - def eof_received(self): - assert self.state == ['INITIAL', 'CONNECTED'], self.state - self.state.append('EOF') - - def connection_lost(self, exc): - if 'EOF' not in self.state: - self.state.append('EOF') # It is okay if EOF is missed. - assert self.state == ['INITIAL', 'CONNECTED', 'EOF'], self.state - self.state.append('CLOSED') - if self.done: - self.done.set_result(None) - - -class MyWritePipeProto(asyncio.BaseProtocol): - done = None - - def __init__(self, loop=None): - self.state = 'INITIAL' - self.transport = None - if loop is not None: - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - - def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class MySubprocessProtocol(asyncio.SubprocessProtocol): - - def __init__(self, loop): - self.state = 'INITIAL' - self.transport = None - self.connected = loop.create_future() - self.completed = loop.create_future() - self.disconnects = {fd: loop.create_future() for fd in range(3)} - self.data = {1: b'', 2: b''} - self.returncode = None - self.got_data = {1: asyncio.Event(loop=loop), - 2: asyncio.Event(loop=loop)} - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - self.connected.set_result(None) - - def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state - self.state = 'CLOSED' - self.completed.set_result(None) - - def pipe_data_received(self, fd, data): - assert self.state == 'CONNECTED', self.state - self.data[fd] += data - self.got_data[fd].set() - - def pipe_connection_lost(self, fd, exc): - assert self.state == 'CONNECTED', self.state - if exc: - self.disconnects[fd].set_exception(exc) - else: - self.disconnects[fd].set_result(exc) - - def process_exited(self): - assert self.state == 'CONNECTED', self.state - self.returncode = self.transport.get_returncode() - - -class EventLoopTestsMixin: - - def setUp(self): - super().setUp() - self.loop = self.create_event_loop() - self.set_event_loop(self.loop) - - def tearDown(self): - # just in case if we have transport close callbacks - if not self.loop.is_closed(): - test_utils.run_briefly(self.loop) - - self.doCleanups() - support.gc_collect() - super().tearDown() - - def test_run_until_complete_nesting(self): - async def coro1(): - await asyncio.sleep(0) - - async def coro2(): - self.assertTrue(self.loop.is_running()) - self.loop.run_until_complete(coro1()) - - self.assertRaises( - RuntimeError, self.loop.run_until_complete, coro2()) - - # Note: because of the default Windows timing granularity of - # 15.6 msec, we use fairly long sleep times here (~100 msec). - - def test_run_until_complete(self): - t0 = self.loop.time() - self.loop.run_until_complete(asyncio.sleep(0.1)) - t1 = self.loop.time() - self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0) - - def test_run_until_complete_stopped(self): - - async def cb(): - self.loop.stop() - await asyncio.sleep(0.1) - task = cb() - self.assertRaises(RuntimeError, - self.loop.run_until_complete, task) - - def test_call_later(self): - results = [] - - def callback(arg): - results.append(arg) - self.loop.stop() - - self.loop.call_later(0.1, callback, 'hello world') - t0 = time.monotonic() - self.loop.run_forever() - t1 = time.monotonic() - self.assertEqual(results, ['hello world']) - self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0) - - def test_call_soon(self): - results = [] - - def callback(arg1, arg2): - results.append((arg1, arg2)) - self.loop.stop() - - self.loop.call_soon(callback, 'hello', 'world') - self.loop.run_forever() - self.assertEqual(results, [('hello', 'world')]) - - def test_call_soon_threadsafe(self): - results = [] - lock = threading.Lock() - - def callback(arg): - results.append(arg) - if len(results) >= 2: - self.loop.stop() - - def run_in_thread(): - self.loop.call_soon_threadsafe(callback, 'hello') - lock.release() - - lock.acquire() - t = threading.Thread(target=run_in_thread) - t.start() - - with lock: - self.loop.call_soon(callback, 'world') - self.loop.run_forever() - t.join() - self.assertEqual(results, ['hello', 'world']) - - def test_call_soon_threadsafe_same_thread(self): - results = [] - - def callback(arg): - results.append(arg) - if len(results) >= 2: - self.loop.stop() - - self.loop.call_soon_threadsafe(callback, 'hello') - self.loop.call_soon(callback, 'world') - self.loop.run_forever() - self.assertEqual(results, ['hello', 'world']) - - def test_run_in_executor(self): - def run(arg): - return (arg, threading.get_ident()) - f2 = self.loop.run_in_executor(None, run, 'yo') - res, thread_id = self.loop.run_until_complete(f2) - self.assertEqual(res, 'yo') - self.assertNotEqual(thread_id, threading.get_ident()) - - def test_run_in_executor_cancel(self): - called = False - - def patched_call_soon(*args): - nonlocal called - called = True - - def run(): - time.sleep(0.05) - - f2 = self.loop.run_in_executor(None, run) - f2.cancel() - self.loop.close() - self.loop.call_soon = patched_call_soon - self.loop.call_soon_threadsafe = patched_call_soon - time.sleep(0.4) - self.assertFalse(called) - - def test_reader_callback(self): - r, w = socket.socketpair() - r.setblocking(False) - bytes_read = bytearray() - - def reader(): - try: - data = r.recv(1024) - except BlockingIOError: - # Spurious readiness notifications are possible - # at least on Linux -- see man select. - return - if data: - bytes_read.extend(data) - else: - self.assertTrue(self.loop.remove_reader(r.fileno())) - r.close() - - self.loop.add_reader(r.fileno(), reader) - self.loop.call_soon(w.send, b'abc') - test_utils.run_until(self.loop, lambda: len(bytes_read) >= 3) - self.loop.call_soon(w.send, b'def') - test_utils.run_until(self.loop, lambda: len(bytes_read) >= 6) - self.loop.call_soon(w.close) - self.loop.call_soon(self.loop.stop) - self.loop.run_forever() - self.assertEqual(bytes_read, b'abcdef') - - def test_writer_callback(self): - r, w = socket.socketpair() - w.setblocking(False) - - def writer(data): - w.send(data) - self.loop.stop() - - data = b'x' * 1024 - self.loop.add_writer(w.fileno(), writer, data) - self.loop.run_forever() - - self.assertTrue(self.loop.remove_writer(w.fileno())) - self.assertFalse(self.loop.remove_writer(w.fileno())) - - w.close() - read = r.recv(len(data) * 2) - r.close() - self.assertEqual(read, data) - - @unittest.skipUnless(hasattr(signal, 'SIGKILL'), 'No SIGKILL') - def test_add_signal_handler(self): - caught = 0 - - def my_handler(): - nonlocal caught - caught += 1 - - # Check error behavior first. - self.assertRaises( - TypeError, self.loop.add_signal_handler, 'boom', my_handler) - self.assertRaises( - TypeError, self.loop.remove_signal_handler, 'boom') - self.assertRaises( - ValueError, self.loop.add_signal_handler, signal.NSIG+1, - my_handler) - self.assertRaises( - ValueError, self.loop.remove_signal_handler, signal.NSIG+1) - self.assertRaises( - ValueError, self.loop.add_signal_handler, 0, my_handler) - self.assertRaises( - ValueError, self.loop.remove_signal_handler, 0) - self.assertRaises( - ValueError, self.loop.add_signal_handler, -1, my_handler) - self.assertRaises( - ValueError, self.loop.remove_signal_handler, -1) - self.assertRaises( - RuntimeError, self.loop.add_signal_handler, signal.SIGKILL, - my_handler) - # Removing SIGKILL doesn't raise, since we don't call signal(). - self.assertFalse(self.loop.remove_signal_handler(signal.SIGKILL)) - # Now set a handler and handle it. - self.loop.add_signal_handler(signal.SIGINT, my_handler) - - os.kill(os.getpid(), signal.SIGINT) - test_utils.run_until(self.loop, lambda: caught) - - # Removing it should restore the default handler. - self.assertTrue(self.loop.remove_signal_handler(signal.SIGINT)) - self.assertEqual(signal.getsignal(signal.SIGINT), - signal.default_int_handler) - # Removing again returns False. - self.assertFalse(self.loop.remove_signal_handler(signal.SIGINT)) - - @unittest.skipUnless(hasattr(signal, 'SIGALRM'), 'No SIGALRM') - def test_signal_handling_while_selecting(self): - # Test with a signal actually arriving during a select() call. - caught = 0 - - def my_handler(): - nonlocal caught - caught += 1 - self.loop.stop() - - self.loop.add_signal_handler(signal.SIGALRM, my_handler) - - signal.setitimer(signal.ITIMER_REAL, 0.01, 0) # Send SIGALRM once. - self.loop.call_later(60, self.loop.stop) - self.loop.run_forever() - self.assertEqual(caught, 1) - - @unittest.skipUnless(hasattr(signal, 'SIGALRM'), 'No SIGALRM') - def test_signal_handling_args(self): - some_args = (42,) - caught = 0 - - def my_handler(*args): - nonlocal caught - caught += 1 - self.assertEqual(args, some_args) - self.loop.stop() - - self.loop.add_signal_handler(signal.SIGALRM, my_handler, *some_args) - - signal.setitimer(signal.ITIMER_REAL, 0.1, 0) # Send SIGALRM once. - self.loop.call_later(60, self.loop.stop) - self.loop.run_forever() - self.assertEqual(caught, 1) - - def _basetest_create_connection(self, connection_fut, check_sockname=True): - tr, pr = self.loop.run_until_complete(connection_fut) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, asyncio.Protocol) - self.assertIs(pr.transport, tr) - if check_sockname: - self.assertIsNotNone(tr.get_extra_info('sockname')) - self.loop.run_until_complete(pr.done) - self.assertGreater(pr.nbytes, 0) - tr.close() - - def test_create_connection(self): - with test_utils.run_test_server() as httpd: - conn_fut = self.loop.create_connection( - lambda: MyProto(loop=self.loop), *httpd.address) - self._basetest_create_connection(conn_fut) - - @support.skip_unless_bind_unix_socket - def test_create_unix_connection(self): - # Issue #20682: On Mac OS X Tiger, getsockname() returns a - # zero-length address for UNIX socket. - check_sockname = not broken_unix_getsockname() - - with test_utils.run_test_unix_server() as httpd: - conn_fut = self.loop.create_unix_connection( - lambda: MyProto(loop=self.loop), httpd.address) - self._basetest_create_connection(conn_fut, check_sockname) - - def check_ssl_extra_info(self, client, check_sockname=True, - peername=None, peercert={}): - if check_sockname: - self.assertIsNotNone(client.get_extra_info('sockname')) - if peername: - self.assertEqual(peername, - client.get_extra_info('peername')) - else: - self.assertIsNotNone(client.get_extra_info('peername')) - self.assertEqual(peercert, - client.get_extra_info('peercert')) - - # test SSL cipher - cipher = client.get_extra_info('cipher') - self.assertIsInstance(cipher, tuple) - self.assertEqual(len(cipher), 3, cipher) - self.assertIsInstance(cipher[0], str) - self.assertIsInstance(cipher[1], str) - self.assertIsInstance(cipher[2], int) - - # test SSL object - sslobj = client.get_extra_info('ssl_object') - self.assertIsNotNone(sslobj) - self.assertEqual(sslobj.compression(), - client.get_extra_info('compression')) - self.assertEqual(sslobj.cipher(), - client.get_extra_info('cipher')) - self.assertEqual(sslobj.getpeercert(), - client.get_extra_info('peercert')) - self.assertEqual(sslobj.compression(), - client.get_extra_info('compression')) - - def _basetest_create_ssl_connection(self, connection_fut, - check_sockname=True, - peername=None): - tr, pr = self.loop.run_until_complete(connection_fut) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, asyncio.Protocol) - self.assertTrue('ssl' in tr.__class__.__name__.lower()) - self.check_ssl_extra_info(tr, check_sockname, peername) - self.loop.run_until_complete(pr.done) - self.assertGreater(pr.nbytes, 0) - tr.close() - - def _test_create_ssl_connection(self, httpd, create_connection, - check_sockname=True, peername=None): - conn_fut = create_connection(ssl=test_utils.dummy_ssl_context()) - self._basetest_create_ssl_connection(conn_fut, check_sockname, - peername) - - # ssl.Purpose was introduced in Python 3.4 - if hasattr(ssl, 'Purpose'): - def _dummy_ssl_create_context(purpose=ssl.Purpose.SERVER_AUTH, *, - cafile=None, capath=None, - cadata=None): - """ - A ssl.create_default_context() replacement that doesn't enable - cert validation. - """ - self.assertEqual(purpose, ssl.Purpose.SERVER_AUTH) - return test_utils.dummy_ssl_context() - - # With ssl=True, ssl.create_default_context() should be called - with mock.patch('ssl.create_default_context', - side_effect=_dummy_ssl_create_context) as m: - conn_fut = create_connection(ssl=True) - self._basetest_create_ssl_connection(conn_fut, check_sockname, - peername) - self.assertEqual(m.call_count, 1) - - # With the real ssl.create_default_context(), certificate - # validation will fail - with self.assertRaises(ssl.SSLError) as cm: - conn_fut = create_connection(ssl=True) - # Ignore the "SSL handshake failed" log in debug mode - with test_utils.disable_logger(): - self._basetest_create_ssl_connection(conn_fut, check_sockname, - peername) - - self.assertEqual(cm.exception.reason, 'CERTIFICATE_VERIFY_FAILED') - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_ssl_connection(self): - with test_utils.run_test_server(use_ssl=True) as httpd: - create_connection = functools.partial( - self.loop.create_connection, - lambda: MyProto(loop=self.loop), - *httpd.address) - self._test_create_ssl_connection(httpd, create_connection, - peername=httpd.address) - - @support.skip_unless_bind_unix_socket - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_ssl_unix_connection(self): - # Issue #20682: On Mac OS X Tiger, getsockname() returns a - # zero-length address for UNIX socket. - check_sockname = not broken_unix_getsockname() - - with test_utils.run_test_unix_server(use_ssl=True) as httpd: - create_connection = functools.partial( - self.loop.create_unix_connection, - lambda: MyProto(loop=self.loop), httpd.address, - server_hostname='127.0.0.1') - - self._test_create_ssl_connection(httpd, create_connection, - check_sockname, - peername=httpd.address) - - def test_create_connection_local_addr(self): - with test_utils.run_test_server() as httpd: - port = support.find_unused_port() - f = self.loop.create_connection( - lambda: MyProto(loop=self.loop), - *httpd.address, local_addr=(httpd.address[0], port)) - tr, pr = self.loop.run_until_complete(f) - expected = pr.transport.get_extra_info('sockname')[1] - self.assertEqual(port, expected) - tr.close() - - def test_create_connection_local_addr_in_use(self): - with test_utils.run_test_server() as httpd: - f = self.loop.create_connection( - lambda: MyProto(loop=self.loop), - *httpd.address, local_addr=httpd.address) - with self.assertRaises(OSError) as cm: - self.loop.run_until_complete(f) - self.assertEqual(cm.exception.errno, errno.EADDRINUSE) - self.assertIn(str(httpd.address), cm.exception.strerror) - - def test_connect_accepted_socket(self, server_ssl=None, client_ssl=None): - loop = self.loop - - class MyProto(MyBaseProto): - - def connection_lost(self, exc): - super().connection_lost(exc) - loop.call_soon(loop.stop) - - def data_received(self, data): - super().data_received(data) - self.transport.write(expected_response) - - lsock = socket.create_server(('127.0.0.1', 0), backlog=1) - addr = lsock.getsockname() - - message = b'test data' - response = None - expected_response = b'roger' - - def client(): - nonlocal response - try: - csock = socket.socket() - if client_ssl is not None: - csock = client_ssl.wrap_socket(csock) - csock.connect(addr) - csock.sendall(message) - response = csock.recv(99) - csock.close() - except Exception as exc: - print( - "Failure in client thread in test_connect_accepted_socket", - exc) - - thread = threading.Thread(target=client, daemon=True) - thread.start() - - conn, _ = lsock.accept() - proto = MyProto(loop=loop) - proto.loop = loop - loop.run_until_complete( - loop.connect_accepted_socket( - (lambda: proto), conn, ssl=server_ssl)) - loop.run_forever() - proto.transport.close() - lsock.close() - - support.join_thread(thread) - self.assertFalse(thread.is_alive()) - self.assertEqual(proto.state, 'CLOSED') - self.assertEqual(proto.nbytes, len(message)) - self.assertEqual(response, expected_response) - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_ssl_connect_accepted_socket(self): - if (sys.platform == 'win32' and - sys.version_info < (3, 5) and - isinstance(self.loop, proactor_events.BaseProactorEventLoop) - ): - raise unittest.SkipTest( - 'SSL not supported with proactor event loops before Python 3.5' - ) - - server_context = test_utils.simple_server_sslcontext() - client_context = test_utils.simple_client_sslcontext() - - self.test_connect_accepted_socket(server_context, client_context) - - def test_connect_accepted_socket_ssl_timeout_for_plain_socket(self): - sock = socket.socket() - self.addCleanup(sock.close) - coro = self.loop.connect_accepted_socket( - MyProto, sock, ssl_handshake_timeout=support.LOOPBACK_TIMEOUT) - with self.assertRaisesRegex( - ValueError, - 'ssl_handshake_timeout is only meaningful with ssl'): - self.loop.run_until_complete(coro) - - @mock.patch('asyncio.base_events.socket') - def create_server_multiple_hosts(self, family, hosts, mock_sock): - async def getaddrinfo(host, port, *args, **kw): - if family == socket.AF_INET: - return [(family, socket.SOCK_STREAM, 6, '', (host, port))] - else: - return [(family, socket.SOCK_STREAM, 6, '', (host, port, 0, 0))] - - def getaddrinfo_task(*args, **kwds): - return self.loop.create_task(getaddrinfo(*args, **kwds)) - - unique_hosts = set(hosts) - - if family == socket.AF_INET: - mock_sock.socket().getsockbyname.side_effect = [ - (host, 80) for host in unique_hosts] - else: - mock_sock.socket().getsockbyname.side_effect = [ - (host, 80, 0, 0) for host in unique_hosts] - self.loop.getaddrinfo = getaddrinfo_task - self.loop._start_serving = mock.Mock() - self.loop._stop_serving = mock.Mock() - f = self.loop.create_server(lambda: MyProto(self.loop), hosts, 80) - server = self.loop.run_until_complete(f) - self.addCleanup(server.close) - server_hosts = {sock.getsockbyname()[0] for sock in server.sockets} - self.assertEqual(server_hosts, unique_hosts) - - def test_create_server_multiple_hosts_ipv4(self): - self.create_server_multiple_hosts(socket.AF_INET, - ['1.2.3.4', '5.6.7.8', '1.2.3.4']) - - def test_create_server_multiple_hosts_ipv6(self): - self.create_server_multiple_hosts(socket.AF_INET6, - ['::1', '::2', '::1']) - - def test_create_server(self): - proto = MyProto(self.loop) - f = self.loop.create_server(lambda: proto, '0.0.0.0', 0) - server = self.loop.run_until_complete(f) - self.assertEqual(len(server.sockets), 1) - sock = server.sockets[0] - host, port = sock.getsockname() - self.assertEqual(host, '0.0.0.0') - client = socket.socket() - client.connect(('127.0.0.1', port)) - client.sendall(b'xxx') - - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - - test_utils.run_until(self.loop, lambda: proto.nbytes > 0) - self.assertEqual(3, proto.nbytes) - - # extra info is available - self.assertIsNotNone(proto.transport.get_extra_info('sockname')) - self.assertEqual('127.0.0.1', - proto.transport.get_extra_info('peername')[0]) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - - self.assertEqual('CLOSED', proto.state) - - # the client socket must be closed after to avoid ECONNRESET upon - # recv()/send() on the serving socket - client.close() - - # close server - server.close() - - @unittest.skipUnless(hasattr(socket, 'SO_REUSEPORT'), 'No SO_REUSEPORT') - def test_create_server_reuse_port(self): - proto = MyProto(self.loop) - f = self.loop.create_server( - lambda: proto, '0.0.0.0', 0) - server = self.loop.run_until_complete(f) - self.assertEqual(len(server.sockets), 1) - sock = server.sockets[0] - self.assertFalse( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_REUSEPORT)) - server.close() - - test_utils.run_briefly(self.loop) - - proto = MyProto(self.loop) - f = self.loop.create_server( - lambda: proto, '0.0.0.0', 0, reuse_port=True) - server = self.loop.run_until_complete(f) - self.assertEqual(len(server.sockets), 1) - sock = server.sockets[0] - self.assertTrue( - sock.getsockopt( - socket.SOL_SOCKET, socket.SO_REUSEPORT)) - server.close() - - def _make_unix_server(self, factory, **kwargs): - path = test_utils.gen_unix_socket_path() - self.addCleanup(lambda: os.path.exists(path) and os.unlink(path)) - - f = self.loop.create_unix_server(factory, path, **kwargs) - server = self.loop.run_until_complete(f) - - return server, path - - @support.skip_unless_bind_unix_socket - def test_create_unix_server(self): - proto = MyProto(loop=self.loop) - server, path = self._make_unix_server(lambda: proto) - self.assertEqual(len(server.sockets), 1) - - client = socket.socket(socket.AF_UNIX) - client.connect(path) - client.sendall(b'xxx') - - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - test_utils.run_until(self.loop, lambda: proto.nbytes > 0) - self.assertEqual(3, proto.nbytes) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - - self.assertEqual('CLOSED', proto.state) - - # the client socket must be closed after to avoid ECONNRESET upon - # recv()/send() on the serving socket - client.close() - - # close server - server.close() - - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') - def test_create_unix_server_path_socket_error(self): - proto = MyProto(loop=self.loop) - sock = socket.socket() - with sock: - f = self.loop.create_unix_server(lambda: proto, '/test', sock=sock) - with self.assertRaisesRegex(ValueError, - 'path and sock can not be specified ' - 'at the same time'): - self.loop.run_until_complete(f) - - def _create_ssl_context(self, certfile, keyfile=None): - sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - sslcontext.options |= ssl.OP_NO_SSLv2 - sslcontext.load_cert_chain(certfile, keyfile) - return sslcontext - - def _make_ssl_server(self, factory, certfile, keyfile=None): - sslcontext = self._create_ssl_context(certfile, keyfile) - - f = self.loop.create_server(factory, '127.0.0.1', 0, ssl=sslcontext) - server = self.loop.run_until_complete(f) - - sock = server.sockets[0] - host, port = sock.getsockname() - self.assertEqual(host, '127.0.0.1') - return server, host, port - - def _make_ssl_unix_server(self, factory, certfile, keyfile=None): - sslcontext = self._create_ssl_context(certfile, keyfile) - return self._make_unix_server(factory, ssl=sslcontext) - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_server_ssl(self): - proto = MyProto(loop=self.loop) - server, host, port = self._make_ssl_server( - lambda: proto, test_utils.ONLYCERT, test_utils.ONLYKEY) - - f_c = self.loop.create_connection(MyBaseProto, host, port, - ssl=test_utils.dummy_ssl_context()) - client, pr = self.loop.run_until_complete(f_c) - - client.write(b'xxx') - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - - test_utils.run_until(self.loop, lambda: proto.nbytes > 0) - self.assertEqual(3, proto.nbytes) - - # extra info is available - self.check_ssl_extra_info(client, peername=(host, port)) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - self.assertEqual('CLOSED', proto.state) - - # the client socket must be closed after to avoid ECONNRESET upon - # recv()/send() on the serving socket - client.close() - - # stop serving - server.close() - - @support.skip_unless_bind_unix_socket - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_unix_server_ssl(self): - proto = MyProto(loop=self.loop) - server, path = self._make_ssl_unix_server( - lambda: proto, test_utils.ONLYCERT, test_utils.ONLYKEY) - - f_c = self.loop.create_unix_connection( - MyBaseProto, path, ssl=test_utils.dummy_ssl_context(), - server_hostname='') - - client, pr = self.loop.run_until_complete(f_c) - - client.write(b'xxx') - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - test_utils.run_until(self.loop, lambda: proto.nbytes > 0) - self.assertEqual(3, proto.nbytes) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - self.assertEqual('CLOSED', proto.state) - - # the client socket must be closed after to avoid ECONNRESET upon - # recv()/send() on the serving socket - client.close() - - # stop serving - server.close() - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_server_ssl_verify_failed(self): - proto = MyProto(loop=self.loop) - server, host, port = self._make_ssl_server( - lambda: proto, test_utils.SIGNED_CERTFILE) - - sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext_client.options |= ssl.OP_NO_SSLv2 - sslcontext_client.verify_mode = ssl.CERT_REQUIRED - if hasattr(sslcontext_client, 'check_hostname'): - sslcontext_client.check_hostname = True - - - # no CA loaded - f_c = self.loop.create_connection(MyProto, host, port, - ssl=sslcontext_client) - with mock.patch.object(self.loop, 'call_exception_handler'): - with test_utils.disable_logger(): - with self.assertRaisesRegex(ssl.SSLError, - '(?i)certificate.verify.failed'): - self.loop.run_until_complete(f_c) - - # execute the loop to log the connection error - test_utils.run_briefly(self.loop) - - # close connection - self.assertIsNone(proto.transport) - server.close() - - @support.skip_unless_bind_unix_socket - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_unix_server_ssl_verify_failed(self): - proto = MyProto(loop=self.loop) - server, path = self._make_ssl_unix_server( - lambda: proto, test_utils.SIGNED_CERTFILE) - - sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext_client.options |= ssl.OP_NO_SSLv2 - sslcontext_client.verify_mode = ssl.CERT_REQUIRED - if hasattr(sslcontext_client, 'check_hostname'): - sslcontext_client.check_hostname = True - - # no CA loaded - f_c = self.loop.create_unix_connection(MyProto, path, - ssl=sslcontext_client, - server_hostname='invalid') - with mock.patch.object(self.loop, 'call_exception_handler'): - with test_utils.disable_logger(): - with self.assertRaisesRegex(ssl.SSLError, - '(?i)certificate.verify.failed'): - self.loop.run_until_complete(f_c) - - # execute the loop to log the connection error - test_utils.run_briefly(self.loop) - - # close connection - self.assertIsNone(proto.transport) - server.close() - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_server_ssl_match_failed(self): - proto = MyProto(loop=self.loop) - server, host, port = self._make_ssl_server( - lambda: proto, test_utils.SIGNED_CERTFILE) - - sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext_client.options |= ssl.OP_NO_SSLv2 - sslcontext_client.verify_mode = ssl.CERT_REQUIRED - sslcontext_client.load_verify_locations( - cafile=test_utils.SIGNING_CA) - if hasattr(sslcontext_client, 'check_hostname'): - sslcontext_client.check_hostname = True - - # incorrect server_hostname - f_c = self.loop.create_connection(MyProto, host, port, - ssl=sslcontext_client) - with mock.patch.object(self.loop, 'call_exception_handler'): - with test_utils.disable_logger(): - with self.assertRaisesRegex( - ssl.CertificateError, - "IP address mismatch, certificate is not valid for " - "'127.0.0.1'"): - self.loop.run_until_complete(f_c) - - # close connection - # transport is None because TLS ALERT aborted the handshake - self.assertIsNone(proto.transport) - server.close() - - @support.skip_unless_bind_unix_socket - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_unix_server_ssl_verified(self): - proto = MyProto(loop=self.loop) - server, path = self._make_ssl_unix_server( - lambda: proto, test_utils.SIGNED_CERTFILE) - - sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext_client.options |= ssl.OP_NO_SSLv2 - sslcontext_client.verify_mode = ssl.CERT_REQUIRED - sslcontext_client.load_verify_locations(cafile=test_utils.SIGNING_CA) - if hasattr(sslcontext_client, 'check_hostname'): - sslcontext_client.check_hostname = True - - # Connection succeeds with correct CA and server hostname. - f_c = self.loop.create_unix_connection(MyProto, path, - ssl=sslcontext_client, - server_hostname='localhost') - client, pr = self.loop.run_until_complete(f_c) - - # close connection - proto.transport.close() - client.close() - server.close() - self.loop.run_until_complete(proto.done) - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_create_server_ssl_verified(self): - proto = MyProto(loop=self.loop) - server, host, port = self._make_ssl_server( - lambda: proto, test_utils.SIGNED_CERTFILE) - - sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext_client.options |= ssl.OP_NO_SSLv2 - sslcontext_client.verify_mode = ssl.CERT_REQUIRED - sslcontext_client.load_verify_locations(cafile=test_utils.SIGNING_CA) - if hasattr(sslcontext_client, 'check_hostname'): - sslcontext_client.check_hostname = True - - # Connection succeeds with correct CA and server hostname. - f_c = self.loop.create_connection(MyProto, host, port, - ssl=sslcontext_client, - server_hostname='localhost') - client, pr = self.loop.run_until_complete(f_c) - - # extra info is available - self.check_ssl_extra_info(client, peername=(host, port), - peercert=test_utils.PEERCERT) - - # close connection - proto.transport.close() - client.close() - server.close() - self.loop.run_until_complete(proto.done) - - def test_create_server_sock(self): - proto = self.loop.create_future() - - class TestMyProto(MyProto): - def connection_made(self, transport): - super().connection_made(transport) - proto.set_result(self) - - sock_ob = socket.create_server(('0.0.0.0', 0)) - - f = self.loop.create_server(TestMyProto, sock=sock_ob) - server = self.loop.run_until_complete(f) - sock = server.sockets[0] - self.assertEqual(sock.fileno(), sock_ob.fileno()) - - host, port = sock.getsockname() - self.assertEqual(host, '0.0.0.0') - client = socket.socket() - client.connect(('127.0.0.1', port)) - client.send(b'xxx') - client.close() - server.close() - - def test_create_server_addr_in_use(self): - sock_ob = socket.create_server(('0.0.0.0', 0)) - - f = self.loop.create_server(MyProto, sock=sock_ob) - server = self.loop.run_until_complete(f) - sock = server.sockets[0] - host, port = sock.getsockname() - - f = self.loop.create_server(MyProto, host=host, port=port) - with self.assertRaises(OSError) as cm: - self.loop.run_until_complete(f) - self.assertEqual(cm.exception.errno, errno.EADDRINUSE) - - server.close() - - @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 not supported or enabled') - def test_create_server_dual_stack(self): - f_proto = self.loop.create_future() - - class TestMyProto(MyProto): - def connection_made(self, transport): - super().connection_made(transport) - f_proto.set_result(self) - - try_count = 0 - while True: - try: - port = support.find_unused_port() - f = self.loop.create_server(TestMyProto, host=None, port=port) - server = self.loop.run_until_complete(f) - except OSError as ex: - if ex.errno == errno.EADDRINUSE: - try_count += 1 - self.assertGreaterEqual(5, try_count) - continue - else: - raise - else: - break - client = socket.socket() - client.connect(('127.0.0.1', port)) - client.send(b'xxx') - proto = self.loop.run_until_complete(f_proto) - proto.transport.close() - client.close() - - f_proto = self.loop.create_future() - client = socket.socket(socket.AF_INET6) - client.connect(('::1', port)) - client.send(b'xxx') - proto = self.loop.run_until_complete(f_proto) - proto.transport.close() - client.close() - - server.close() - - def test_server_close(self): - f = self.loop.create_server(MyProto, '0.0.0.0', 0) - server = self.loop.run_until_complete(f) - sock = server.sockets[0] - host, port = sock.getsockname() - - client = socket.socket() - client.connect(('127.0.0.1', port)) - client.send(b'xxx') - client.close() - - server.close() - - client = socket.socket() - self.assertRaises( - ConnectionRefusedError, client.connect, ('127.0.0.1', port)) - client.close() - - def test_create_datagram_endpoint(self): - class TestMyDatagramProto(MyDatagramProto): - def __init__(inner_self): - super().__init__(loop=self.loop) - - def datagram_received(self, data, addr): - super().datagram_received(data, addr) - self.transport.sendto(b'resp:'+data, addr) - - coro = self.loop.create_datagram_endpoint( - TestMyDatagramProto, local_addr=('127.0.0.1', 0)) - s_transport, server = self.loop.run_until_complete(coro) - host, port = s_transport.get_extra_info('sockname') - - self.assertIsInstance(s_transport, asyncio.Transport) - self.assertIsInstance(server, TestMyDatagramProto) - self.assertEqual('INITIALIZED', server.state) - self.assertIs(server.transport, s_transport) - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(loop=self.loop), - remote_addr=(host, port)) - transport, client = self.loop.run_until_complete(coro) - - self.assertIsInstance(transport, asyncio.Transport) - self.assertIsInstance(client, MyDatagramProto) - self.assertEqual('INITIALIZED', client.state) - self.assertIs(client.transport, transport) - - transport.sendto(b'xxx') - test_utils.run_until(self.loop, lambda: server.nbytes) - self.assertEqual(3, server.nbytes) - test_utils.run_until(self.loop, lambda: client.nbytes) - - # received - self.assertEqual(8, client.nbytes) - - # extra info is available - self.assertIsNotNone(transport.get_extra_info('sockname')) - - # close connection - transport.close() - self.loop.run_until_complete(client.done) - self.assertEqual('CLOSED', client.state) - server.transport.close() - - def test_create_datagram_endpoint_sock(self): - sock = None - local_address = ('127.0.0.1', 0) - infos = self.loop.run_until_complete( - self.loop.getaddrinfo( - *local_address, type=socket.SOCK_DGRAM)) - for family, type, proto, cname, address in infos: - try: - sock = socket.socket(family=family, type=type, proto=proto) - sock.setblocking(False) - sock.bind(address) - except: - pass - else: - break - else: - assert False, 'Can not create socket.' - - f = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(loop=self.loop), sock=sock) - tr, pr = self.loop.run_until_complete(f) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, MyDatagramProto) - tr.close() - self.loop.run_until_complete(pr.done) - - def test_internal_fds(self): - loop = self.create_event_loop() - if not isinstance(loop, selector_events.BaseSelectorEventLoop): - loop.close() - self.skipTest('loop is not a BaseSelectorEventLoop') - - self.assertEqual(1, loop._internal_fds) - loop.close() - self.assertEqual(0, loop._internal_fds) - self.assertIsNone(loop._csock) - self.assertIsNone(loop._ssock) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - def test_read_pipe(self): - proto = MyReadPipeProto(loop=self.loop) - - rpipe, wpipe = os.pipe() - pipeobj = io.open(rpipe, 'rb', 1024) - - async def connect(): - t, p = await self.loop.connect_read_pipe( - lambda: proto, pipeobj) - self.assertIs(p, proto) - self.assertIs(t, proto.transport) - self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) - self.assertEqual(0, proto.nbytes) - - self.loop.run_until_complete(connect()) - - os.write(wpipe, b'1') - test_utils.run_until(self.loop, lambda: proto.nbytes >= 1) - self.assertEqual(1, proto.nbytes) - - os.write(wpipe, b'2345') - test_utils.run_until(self.loop, lambda: proto.nbytes >= 5) - self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) - self.assertEqual(5, proto.nbytes) - - os.close(wpipe) - self.loop.run_until_complete(proto.done) - self.assertEqual( - ['INITIAL', 'CONNECTED', 'EOF', 'CLOSED'], proto.state) - # extra info is available - self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - def test_unclosed_pipe_transport(self): - # This test reproduces the issue #314 on GitHub - loop = self.create_event_loop() - read_proto = MyReadPipeProto(loop=loop) - write_proto = MyWritePipeProto(loop=loop) - - rpipe, wpipe = os.pipe() - rpipeobj = io.open(rpipe, 'rb', 1024) - wpipeobj = io.open(wpipe, 'w', 1024) - - async def connect(): - read_transport, _ = await loop.connect_read_pipe( - lambda: read_proto, rpipeobj) - write_transport, _ = await loop.connect_write_pipe( - lambda: write_proto, wpipeobj) - return read_transport, write_transport - - # Run and close the loop without closing the transports - read_transport, write_transport = loop.run_until_complete(connect()) - loop.close() - - # These 'repr' calls used to raise an AttributeError - # See Issue #314 on GitHub - self.assertIn('open', repr(read_transport)) - self.assertIn('open', repr(write_transport)) - - # Clean up (avoid ResourceWarning) - rpipeobj.close() - wpipeobj.close() - read_transport._pipe = None - write_transport._pipe = None - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - def test_read_pty_output(self): - proto = MyReadPipeProto(loop=self.loop) - - master, slave = os.openpty() - master_read_obj = io.open(master, 'rb', 0) - - async def connect(): - t, p = await self.loop.connect_read_pipe(lambda: proto, - master_read_obj) - self.assertIs(p, proto) - self.assertIs(t, proto.transport) - self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) - self.assertEqual(0, proto.nbytes) - - self.loop.run_until_complete(connect()) - - os.write(slave, b'1') - test_utils.run_until(self.loop, lambda: proto.nbytes) - self.assertEqual(1, proto.nbytes) - - os.write(slave, b'2345') - test_utils.run_until(self.loop, lambda: proto.nbytes >= 5) - self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) - self.assertEqual(5, proto.nbytes) - - os.close(slave) - proto.transport.close() - self.loop.run_until_complete(proto.done) - self.assertEqual( - ['INITIAL', 'CONNECTED', 'EOF', 'CLOSED'], proto.state) - # extra info is available - self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - def test_write_pipe(self): - rpipe, wpipe = os.pipe() - pipeobj = io.open(wpipe, 'wb', 1024) - - proto = MyWritePipeProto(loop=self.loop) - connect = self.loop.connect_write_pipe(lambda: proto, pipeobj) - transport, p = self.loop.run_until_complete(connect) - self.assertIs(p, proto) - self.assertIs(transport, proto.transport) - self.assertEqual('CONNECTED', proto.state) - - transport.write(b'1') - - data = bytearray() - def reader(data): - chunk = os.read(rpipe, 1024) - data += chunk - return len(data) - - test_utils.run_until(self.loop, lambda: reader(data) >= 1) - self.assertEqual(b'1', data) - - transport.write(b'2345') - test_utils.run_until(self.loop, lambda: reader(data) >= 5) - self.assertEqual(b'12345', data) - self.assertEqual('CONNECTED', proto.state) - - os.close(rpipe) - - # extra info is available - self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - self.assertEqual('CLOSED', proto.state) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - def test_write_pipe_disconnect_on_close(self): - rsock, wsock = socket.socketpair() - rsock.setblocking(False) - pipeobj = io.open(wsock.detach(), 'wb', 1024) - - proto = MyWritePipeProto(loop=self.loop) - connect = self.loop.connect_write_pipe(lambda: proto, pipeobj) - transport, p = self.loop.run_until_complete(connect) - self.assertIs(p, proto) - self.assertIs(transport, proto.transport) - self.assertEqual('CONNECTED', proto.state) - - transport.write(b'1') - data = self.loop.run_until_complete(self.loop.sock_recv(rsock, 1024)) - self.assertEqual(b'1', data) - - rsock.close() - - self.loop.run_until_complete(proto.done) - self.assertEqual('CLOSED', proto.state) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - # select, poll and kqueue don't support character devices (PTY) on Mac OS X - # older than 10.6 (Snow Leopard) - @support.requires_mac_ver(10, 6) - def test_write_pty(self): - master, slave = os.openpty() - slave_write_obj = io.open(slave, 'wb', 0) - - proto = MyWritePipeProto(loop=self.loop) - connect = self.loop.connect_write_pipe(lambda: proto, slave_write_obj) - transport, p = self.loop.run_until_complete(connect) - self.assertIs(p, proto) - self.assertIs(transport, proto.transport) - self.assertEqual('CONNECTED', proto.state) - - transport.write(b'1') - - data = bytearray() - def reader(data): - chunk = os.read(master, 1024) - data += chunk - return len(data) - - test_utils.run_until(self.loop, lambda: reader(data) >= 1, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(b'1', data) - - transport.write(b'2345') - test_utils.run_until(self.loop, lambda: reader(data) >= 5, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(b'12345', data) - self.assertEqual('CONNECTED', proto.state) - - os.close(master) - - # extra info is available - self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - - # close connection - proto.transport.close() - self.loop.run_until_complete(proto.done) - self.assertEqual('CLOSED', proto.state) - - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") - # select, poll and kqueue don't support character devices (PTY) on Mac OS X - # older than 10.6 (Snow Leopard) - @support.requires_mac_ver(10, 6) - def test_bidirectional_pty(self): - master, read_slave = os.openpty() - write_slave = os.dup(read_slave) - tty.setraw(read_slave) - - slave_read_obj = io.open(read_slave, 'rb', 0) - read_proto = MyReadPipeProto(loop=self.loop) - read_connect = self.loop.connect_read_pipe(lambda: read_proto, - slave_read_obj) - read_transport, p = self.loop.run_until_complete(read_connect) - self.assertIs(p, read_proto) - self.assertIs(read_transport, read_proto.transport) - self.assertEqual(['INITIAL', 'CONNECTED'], read_proto.state) - self.assertEqual(0, read_proto.nbytes) - - - slave_write_obj = io.open(write_slave, 'wb', 0) - write_proto = MyWritePipeProto(loop=self.loop) - write_connect = self.loop.connect_write_pipe(lambda: write_proto, - slave_write_obj) - write_transport, p = self.loop.run_until_complete(write_connect) - self.assertIs(p, write_proto) - self.assertIs(write_transport, write_proto.transport) - self.assertEqual('CONNECTED', write_proto.state) - - data = bytearray() - def reader(data): - chunk = os.read(master, 1024) - data += chunk - return len(data) - - write_transport.write(b'1') - test_utils.run_until(self.loop, lambda: reader(data) >= 1, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(b'1', data) - self.assertEqual(['INITIAL', 'CONNECTED'], read_proto.state) - self.assertEqual('CONNECTED', write_proto.state) - - os.write(master, b'a') - test_utils.run_until(self.loop, lambda: read_proto.nbytes >= 1, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(['INITIAL', 'CONNECTED'], read_proto.state) - self.assertEqual(1, read_proto.nbytes) - self.assertEqual('CONNECTED', write_proto.state) - - write_transport.write(b'2345') - test_utils.run_until(self.loop, lambda: reader(data) >= 5, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(b'12345', data) - self.assertEqual(['INITIAL', 'CONNECTED'], read_proto.state) - self.assertEqual('CONNECTED', write_proto.state) - - os.write(master, b'bcde') - test_utils.run_until(self.loop, lambda: read_proto.nbytes >= 5, - timeout=support.SHORT_TIMEOUT) - self.assertEqual(['INITIAL', 'CONNECTED'], read_proto.state) - self.assertEqual(5, read_proto.nbytes) - self.assertEqual('CONNECTED', write_proto.state) - - os.close(master) - - read_transport.close() - self.loop.run_until_complete(read_proto.done) - self.assertEqual( - ['INITIAL', 'CONNECTED', 'EOF', 'CLOSED'], read_proto.state) - - write_transport.close() - self.loop.run_until_complete(write_proto.done) - self.assertEqual('CLOSED', write_proto.state) - - def test_prompt_cancellation(self): - r, w = socket.socketpair() - r.setblocking(False) - f = self.loop.create_task(self.loop.sock_recv(r, 1)) - ov = getattr(f, 'ov', None) - if ov is not None: - self.assertTrue(ov.pending) - - async def main(): - try: - self.loop.call_soon(f.cancel) - await f - except asyncio.CancelledError: - res = 'cancelled' - else: - res = None - finally: - self.loop.stop() - return res - - start = time.monotonic() - t = self.loop.create_task(main()) - self.loop.run_forever() - elapsed = time.monotonic() - start - - self.assertLess(elapsed, 0.1) - self.assertEqual(t.result(), 'cancelled') - self.assertRaises(asyncio.CancelledError, f.result) - if ov is not None: - self.assertFalse(ov.pending) - self.loop._stop_serving(r) - - r.close() - w.close() - - def test_timeout_rounding(self): - def _run_once(): - self.loop._run_once_counter += 1 - orig_run_once() - - orig_run_once = self.loop._run_once - self.loop._run_once_counter = 0 - self.loop._run_once = _run_once - - async def wait(): - loop = self.loop - await asyncio.sleep(1e-2) - await asyncio.sleep(1e-4) - await asyncio.sleep(1e-6) - await asyncio.sleep(1e-8) - await asyncio.sleep(1e-10) - - self.loop.run_until_complete(wait()) - # The ideal number of call is 12, but on some platforms, the selector - # may sleep at little bit less than timeout depending on the resolution - # of the clock used by the kernel. Tolerate a few useless calls on - # these platforms. - self.assertLessEqual(self.loop._run_once_counter, 20, - {'clock_resolution': self.loop._clock_resolution, - 'selector': self.loop._selector.__class__.__name__}) - - def test_remove_fds_after_closing(self): - loop = self.create_event_loop() - callback = lambda: None - r, w = socket.socketpair() - self.addCleanup(r.close) - self.addCleanup(w.close) - loop.add_reader(r, callback) - loop.add_writer(w, callback) - loop.close() - self.assertFalse(loop.remove_reader(r)) - self.assertFalse(loop.remove_writer(w)) - - def test_add_fds_after_closing(self): - loop = self.create_event_loop() - callback = lambda: None - r, w = socket.socketpair() - self.addCleanup(r.close) - self.addCleanup(w.close) - loop.close() - with self.assertRaises(RuntimeError): - loop.add_reader(r, callback) - with self.assertRaises(RuntimeError): - loop.add_writer(w, callback) - - def test_close_running_event_loop(self): - async def close_loop(loop): - self.loop.close() - - coro = close_loop(self.loop) - with self.assertRaises(RuntimeError): - self.loop.run_until_complete(coro) - - def test_close(self): - self.loop.close() - - async def test(): - pass - - func = lambda: False - coro = test() - self.addCleanup(coro.close) - - # operation blocked when the loop is closed - with self.assertRaises(RuntimeError): - self.loop.run_forever() - with self.assertRaises(RuntimeError): - fut = self.loop.create_future() - self.loop.run_until_complete(fut) - with self.assertRaises(RuntimeError): - self.loop.call_soon(func) - with self.assertRaises(RuntimeError): - self.loop.call_soon_threadsafe(func) - with self.assertRaises(RuntimeError): - self.loop.call_later(1.0, func) - with self.assertRaises(RuntimeError): - self.loop.call_at(self.loop.time() + .0, func) - with self.assertRaises(RuntimeError): - self.loop.create_task(coro) - with self.assertRaises(RuntimeError): - self.loop.add_signal_handler(signal.SIGTERM, func) - - # run_in_executor test is tricky: the method is a coroutine, - # but run_until_complete cannot be called on closed loop. - # Thus iterate once explicitly. - with self.assertRaises(RuntimeError): - it = self.loop.run_in_executor(None, func).__await__() - next(it) - - -class SubprocessTestsMixin: - - def check_terminated(self, returncode): - if sys.platform == 'win32': - self.assertIsInstance(returncode, int) - # expect 1 but sometimes get 0 - else: - self.assertEqual(-signal.SIGTERM, returncode) - - def check_killed(self, returncode): - if sys.platform == 'win32': - self.assertIsInstance(returncode, int) - # expect 1 but sometimes get 0 - else: - self.assertEqual(-signal.SIGKILL, returncode) - - def test_subprocess_exec(self): - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - - stdin = transp.get_pipe_transport(0) - stdin.write(b'Python The Winner') - self.loop.run_until_complete(proto.got_data[1].wait()) - with test_utils.disable_logger(): - transp.close() - self.loop.run_until_complete(proto.completed) - self.check_killed(proto.returncode) - self.assertEqual(b'Python The Winner', proto.data[1]) - - def test_subprocess_interactive(self): - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - self.assertEqual('CONNECTED', proto.state) - - stdin = transp.get_pipe_transport(0) - stdin.write(b'Python ') - self.loop.run_until_complete(proto.got_data[1].wait()) - proto.got_data[1].clear() - self.assertEqual(b'Python ', proto.data[1]) - - stdin.write(b'The Winner') - self.loop.run_until_complete(proto.got_data[1].wait()) - self.assertEqual(b'Python The Winner', proto.data[1]) - - with test_utils.disable_logger(): - transp.close() - self.loop.run_until_complete(proto.completed) - self.check_killed(proto.returncode) - - def test_subprocess_shell(self): - with self.assertWarns(DeprecationWarning): - connect = self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'echo Python') - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - transp.get_pipe_transport(0).close() - self.loop.run_until_complete(proto.completed) - self.assertEqual(0, proto.returncode) - self.assertTrue(all(f.done() for f in proto.disconnects.values())) - self.assertEqual(proto.data[1].rstrip(b'\r\n'), b'Python') - self.assertEqual(proto.data[2], b'') - transp.close() - - def test_subprocess_exitcode(self): - connect = self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) - transp.close() - - def test_subprocess_close_after_finish(self): - connect = self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None) - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.assertIsNone(transp.get_pipe_transport(0)) - self.assertIsNone(transp.get_pipe_transport(1)) - self.assertIsNone(transp.get_pipe_transport(2)) - self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) - self.assertIsNone(transp.close()) - - def test_subprocess_kill(self): - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - transp.kill() - self.loop.run_until_complete(proto.completed) - self.check_killed(proto.returncode) - transp.close() - - def test_subprocess_terminate(self): - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - transp.terminate() - self.loop.run_until_complete(proto.completed) - self.check_terminated(proto.returncode) - transp.close() - - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") - def test_subprocess_send_signal(self): - # bpo-31034: Make sure that we get the default signal handler (killing - # the process). The parent process may have decided to ignore SIGHUP, - # and signal handlers are inherited. - old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL) - try: - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - transp.send_signal(signal.SIGHUP) - self.loop.run_until_complete(proto.completed) - self.assertEqual(-signal.SIGHUP, proto.returncode) - transp.close() - finally: - signal.signal(signal.SIGHUP, old_handler) - - def test_subprocess_stderr(self): - prog = os.path.join(os.path.dirname(__file__), 'echo2.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - stdin = transp.get_pipe_transport(0) - stdin.write(b'test') - - self.loop.run_until_complete(proto.completed) - - transp.close() - self.assertEqual(b'OUT:test', proto.data[1]) - self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2]) - self.assertEqual(0, proto.returncode) - - def test_subprocess_stderr_redirect_to_stdout(self): - prog = os.path.join(os.path.dirname(__file__), 'echo2.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog, stderr=subprocess.STDOUT) - - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - stdin = transp.get_pipe_transport(0) - self.assertIsNotNone(transp.get_pipe_transport(1)) - self.assertIsNone(transp.get_pipe_transport(2)) - - stdin.write(b'test') - self.loop.run_until_complete(proto.completed) - self.assertTrue(proto.data[1].startswith(b'OUT:testERR:test'), - proto.data[1]) - self.assertEqual(b'', proto.data[2]) - - transp.close() - self.assertEqual(0, proto.returncode) - - def test_subprocess_close_client_stream(self): - prog = os.path.join(os.path.dirname(__file__), 'echo3.py') - - connect = self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - with self.assertWarns(DeprecationWarning): - transp, proto = self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.connected) - - stdin = transp.get_pipe_transport(0) - stdout = transp.get_pipe_transport(1) - stdin.write(b'test') - self.loop.run_until_complete(proto.got_data[1].wait()) - self.assertEqual(b'OUT:test', proto.data[1]) - - stdout.close() - self.loop.run_until_complete(proto.disconnects[1]) - stdin.write(b'xxx') - self.loop.run_until_complete(proto.got_data[2].wait()) - if sys.platform != 'win32': - self.assertEqual(b'ERR:BrokenPipeError', proto.data[2]) - else: - # After closing the read-end of a pipe, writing to the - # write-end using os.write() fails with errno==EINVAL and - # GetLastError()==ERROR_INVALID_NAME on Windows!?! (Using - # WriteFile() we get ERROR_BROKEN_PIPE as expected.) - self.assertEqual(b'ERR:OSError', proto.data[2]) - with test_utils.disable_logger(): - transp.close() - self.loop.run_until_complete(proto.completed) - self.check_killed(proto.returncode) - - def test_subprocess_wait_no_same_group(self): - # start the new process in a new session - connect = self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None, - start_new_session=True) - _, proto = yield self.loop.run_until_complete(connect) - self.assertIsInstance(proto, MySubprocessProtocol) - self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) - - def test_subprocess_exec_invalid_args(self): - async def connect(**kwds): - await self.loop.subprocess_exec( - asyncio.SubprocessProtocol, - 'pwd', **kwds) - - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(universal_newlines=True)) - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(bufsize=4096)) - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(shell=True)) - - def test_subprocess_shell_invalid_args(self): - - async def connect(cmd=None, **kwds): - if not cmd: - cmd = 'pwd' - await self.loop.subprocess_shell( - asyncio.SubprocessProtocol, - cmd, **kwds) - - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(['ls', '-l'])) - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(universal_newlines=True)) - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(bufsize=4096)) - with self.assertRaises(ValueError): - self.loop.run_until_complete(connect(shell=False)) - - -if sys.platform == 'win32': - - class SelectEventLoopTests(EventLoopTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop() - - class ProactorEventLoopTests(EventLoopTestsMixin, - SubprocessTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.ProactorEventLoop() - - def test_reader_callback(self): - raise unittest.SkipTest("IocpEventLoop does not have add_reader()") - - def test_reader_callback_cancel(self): - raise unittest.SkipTest("IocpEventLoop does not have add_reader()") - - def test_writer_callback(self): - raise unittest.SkipTest("IocpEventLoop does not have add_writer()") - - def test_writer_callback_cancel(self): - raise unittest.SkipTest("IocpEventLoop does not have add_writer()") - - def test_remove_fds_after_closing(self): - raise unittest.SkipTest("IocpEventLoop does not have add_reader()") -else: - import selectors - - class UnixEventLoopTestsMixin(EventLoopTestsMixin): - def setUp(self): - super().setUp() - watcher = asyncio.SafeChildWatcher() - watcher.attach_loop(self.loop) - asyncio.set_child_watcher(watcher) - - def tearDown(self): - asyncio.set_child_watcher(None) - super().tearDown() - - - if hasattr(selectors, 'KqueueSelector'): - class KqueueEventLoopTests(UnixEventLoopTestsMixin, - SubprocessTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop( - selectors.KqueueSelector()) - - # kqueue doesn't support character devices (PTY) on Mac OS X older - # than 10.9 (Maverick) - @support.requires_mac_ver(10, 9) - # Issue #20667: KqueueEventLoopTests.test_read_pty_output() - # hangs on OpenBSD 5.5 - @unittest.skipIf(sys.platform.startswith('openbsd'), - 'test hangs on OpenBSD') - def test_read_pty_output(self): - super().test_read_pty_output() - - # kqueue doesn't support character devices (PTY) on Mac OS X older - # than 10.9 (Maverick) - @support.requires_mac_ver(10, 9) - def test_write_pty(self): - super().test_write_pty() - - if hasattr(selectors, 'EpollSelector'): - class EPollEventLoopTests(UnixEventLoopTestsMixin, - SubprocessTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.EpollSelector()) - - if hasattr(selectors, 'PollSelector'): - class PollEventLoopTests(UnixEventLoopTestsMixin, - SubprocessTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.PollSelector()) - - # Should always exist. - class SelectEventLoopTests(UnixEventLoopTestsMixin, - SubprocessTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.SelectSelector()) - - -def noop(*args, **kwargs): - pass - - -class HandleTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = mock.Mock() - self.loop.get_debug.return_value = True - - def test_handle(self): - def callback(*args): - return args - - args = () - h = asyncio.Handle(callback, args, self.loop) - self.assertIs(h._callback, callback) - self.assertIs(h._args, args) - self.assertFalse(h.cancelled()) - - h.cancel() - self.assertTrue(h.cancelled()) - - def test_callback_with_exception(self): - def callback(): - raise ValueError() - - self.loop = mock.Mock() - self.loop.call_exception_handler = mock.Mock() - - h = asyncio.Handle(callback, (), self.loop) - h._run() - - self.loop.call_exception_handler.assert_called_with({ - 'message': test_utils.MockPattern('Exception in callback.*'), - 'exception': mock.ANY, - 'handle': h, - 'source_traceback': h._source_traceback, - }) - - def test_handle_weakref(self): - wd = weakref.WeakValueDictionary() - h = asyncio.Handle(lambda: None, (), self.loop) - wd['h'] = h # Would fail without __weakref__ slot. - - def test_handle_repr(self): - self.loop.get_debug.return_value = False - - # simple function - h = asyncio.Handle(noop, (1, 2), self.loop) - filename, lineno = test_utils.get_function_source(noop) - self.assertEqual(repr(h), - '<Handle noop(1, 2) at %s:%s>' - % (filename, lineno)) - - # cancelled handle - h.cancel() - self.assertEqual(repr(h), - '<Handle cancelled>') - - # decorated function - with self.assertWarns(DeprecationWarning): - cb = asyncio.coroutine(noop) - h = asyncio.Handle(cb, (), self.loop) - self.assertEqual(repr(h), - '<Handle noop() at %s:%s>' - % (filename, lineno)) - - # partial function - cb = functools.partial(noop, 1, 2) - h = asyncio.Handle(cb, (3,), self.loop) - regex = (r'^<Handle noop\(1, 2\)\(3\) at %s:%s>$' - % (re.escape(filename), lineno)) - self.assertRegex(repr(h), regex) - - # partial function with keyword args - cb = functools.partial(noop, x=1) - h = asyncio.Handle(cb, (2, 3), self.loop) - regex = (r'^<Handle noop\(x=1\)\(2, 3\) at %s:%s>$' - % (re.escape(filename), lineno)) - self.assertRegex(repr(h), regex) - - # partial method - if sys.version_info >= (3, 4): - method = HandleTests.test_handle_repr - cb = functools.partialmethod(method) - filename, lineno = test_utils.get_function_source(method) - h = asyncio.Handle(cb, (), self.loop) - - cb_regex = r'<function HandleTests.test_handle_repr .*>' - cb_regex = (r'functools.partialmethod\(%s, , \)\(\)' % cb_regex) - regex = (r'^<Handle %s at %s:%s>$' - % (cb_regex, re.escape(filename), lineno)) - self.assertRegex(repr(h), regex) - - def test_handle_repr_debug(self): - self.loop.get_debug.return_value = True - - # simple function - create_filename = __file__ - create_lineno = sys._getframe().f_lineno + 1 - h = asyncio.Handle(noop, (1, 2), self.loop) - filename, lineno = test_utils.get_function_source(noop) - self.assertEqual(repr(h), - '<Handle noop(1, 2) at %s:%s created at %s:%s>' - % (filename, lineno, create_filename, create_lineno)) - - # cancelled handle - h.cancel() - self.assertEqual( - repr(h), - '<Handle cancelled noop(1, 2) at %s:%s created at %s:%s>' - % (filename, lineno, create_filename, create_lineno)) - - # double cancellation won't overwrite _repr - h.cancel() - self.assertEqual( - repr(h), - '<Handle cancelled noop(1, 2) at %s:%s created at %s:%s>' - % (filename, lineno, create_filename, create_lineno)) - - def test_handle_source_traceback(self): - loop = asyncio.get_event_loop_policy().new_event_loop() - loop.set_debug(True) - self.set_event_loop(loop) - - def check_source_traceback(h): - lineno = sys._getframe(1).f_lineno - 1 - self.assertIsInstance(h._source_traceback, list) - self.assertEqual(h._source_traceback[-1][:3], - (__file__, - lineno, - 'test_handle_source_traceback')) - - # call_soon - h = loop.call_soon(noop) - check_source_traceback(h) - - # call_soon_threadsafe - h = loop.call_soon_threadsafe(noop) - check_source_traceback(h) - - # call_later - h = loop.call_later(0, noop) - check_source_traceback(h) - - # call_at - h = loop.call_later(0, noop) - check_source_traceback(h) - - @unittest.skipUnless(hasattr(collections.abc, 'Coroutine'), - 'No collections.abc.Coroutine') - def test_coroutine_like_object_debug_formatting(self): - # Test that asyncio can format coroutines that are instances of - # collections.abc.Coroutine, but lack cr_core or gi_code attributes - # (such as ones compiled with Cython). - - coro = CoroLike() - coro.__name__ = 'AAA' - self.assertTrue(asyncio.iscoroutine(coro)) - self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') - - coro.__qualname__ = 'BBB' - self.assertEqual(coroutines._format_coroutine(coro), 'BBB()') - - coro.cr_running = True - self.assertEqual(coroutines._format_coroutine(coro), 'BBB() running') - - coro.__name__ = coro.__qualname__ = None - self.assertEqual(coroutines._format_coroutine(coro), - '<CoroLike without __name__>() running') - - coro = CoroLike() - coro.__qualname__ = 'CoroLike' - # Some coroutines might not have '__name__', such as - # built-in async_gen.asend(). - self.assertEqual(coroutines._format_coroutine(coro), 'CoroLike()') - - coro = CoroLike() - coro.__qualname__ = 'AAA' - coro.cr_code = None - self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') - - -class TimerTests(unittest.TestCase): - - def setUp(self): - super().setUp() - self.loop = mock.Mock() - - def test_hash(self): - when = time.monotonic() - h = asyncio.TimerHandle(when, lambda: False, (), - mock.Mock()) - self.assertEqual(hash(h), hash(when)) - - def test_when(self): - when = time.monotonic() - h = asyncio.TimerHandle(when, lambda: False, (), - mock.Mock()) - self.assertEqual(when, h.when()) - - def test_timer(self): - def callback(*args): - return args - - args = (1, 2, 3) - when = time.monotonic() - h = asyncio.TimerHandle(when, callback, args, mock.Mock()) - self.assertIs(h._callback, callback) - self.assertIs(h._args, args) - self.assertFalse(h.cancelled()) - - # cancel - h.cancel() - self.assertTrue(h.cancelled()) - self.assertIsNone(h._callback) - self.assertIsNone(h._args) - - # when cannot be None - self.assertRaises(AssertionError, - asyncio.TimerHandle, None, callback, args, - self.loop) - - def test_timer_repr(self): - self.loop.get_debug.return_value = False - - # simple function - h = asyncio.TimerHandle(123, noop, (), self.loop) - src = test_utils.get_function_source(noop) - self.assertEqual(repr(h), - '<TimerHandle when=123 noop() at %s:%s>' % src) - - # cancelled handle - h.cancel() - self.assertEqual(repr(h), - '<TimerHandle cancelled when=123>') - - def test_timer_repr_debug(self): - self.loop.get_debug.return_value = True - - # simple function - create_filename = __file__ - create_lineno = sys._getframe().f_lineno + 1 - h = asyncio.TimerHandle(123, noop, (), self.loop) - filename, lineno = test_utils.get_function_source(noop) - self.assertEqual(repr(h), - '<TimerHandle when=123 noop() ' - 'at %s:%s created at %s:%s>' - % (filename, lineno, create_filename, create_lineno)) - - # cancelled handle - h.cancel() - self.assertEqual(repr(h), - '<TimerHandle cancelled when=123 noop() ' - 'at %s:%s created at %s:%s>' - % (filename, lineno, create_filename, create_lineno)) - - - def test_timer_comparison(self): - def callback(*args): - return args - - when = time.monotonic() - - h1 = asyncio.TimerHandle(when, callback, (), self.loop) - h2 = asyncio.TimerHandle(when, callback, (), self.loop) - # TODO: Use assertLess etc. - self.assertFalse(h1 < h2) - self.assertFalse(h2 < h1) - self.assertTrue(h1 <= h2) - self.assertTrue(h2 <= h1) - self.assertFalse(h1 > h2) - self.assertFalse(h2 > h1) - self.assertTrue(h1 >= h2) - self.assertTrue(h2 >= h1) - self.assertTrue(h1 == h2) - self.assertFalse(h1 != h2) - - h2.cancel() - self.assertFalse(h1 == h2) - - h1 = asyncio.TimerHandle(when, callback, (), self.loop) - h2 = asyncio.TimerHandle(when + 10.0, callback, (), self.loop) - self.assertTrue(h1 < h2) - self.assertFalse(h2 < h1) - self.assertTrue(h1 <= h2) - self.assertFalse(h2 <= h1) - self.assertFalse(h1 > h2) - self.assertTrue(h2 > h1) - self.assertFalse(h1 >= h2) - self.assertTrue(h2 >= h1) - self.assertFalse(h1 == h2) - self.assertTrue(h1 != h2) - - h3 = asyncio.Handle(callback, (), self.loop) - self.assertIs(NotImplemented, h1.__eq__(h3)) - self.assertIs(NotImplemented, h1.__ne__(h3)) - - with self.assertRaises(TypeError): - h1 < () - with self.assertRaises(TypeError): - h1 > () - with self.assertRaises(TypeError): - h1 <= () - with self.assertRaises(TypeError): - h1 >= () - self.assertFalse(h1 == ()) - self.assertTrue(h1 != ()) - - self.assertTrue(h1 == ALWAYS_EQ) - self.assertFalse(h1 != ALWAYS_EQ) - self.assertTrue(h1 < LARGEST) - self.assertFalse(h1 > LARGEST) - self.assertTrue(h1 <= LARGEST) - self.assertFalse(h1 >= LARGEST) - self.assertFalse(h1 < SMALLEST) - self.assertTrue(h1 > SMALLEST) - self.assertFalse(h1 <= SMALLEST) - self.assertTrue(h1 >= SMALLEST) - - -class AbstractEventLoopTests(unittest.TestCase): - - def test_not_implemented(self): - f = mock.Mock() - loop = asyncio.AbstractEventLoop() - self.assertRaises( - NotImplementedError, loop.run_forever) - self.assertRaises( - NotImplementedError, loop.run_until_complete, None) - self.assertRaises( - NotImplementedError, loop.stop) - self.assertRaises( - NotImplementedError, loop.is_running) - self.assertRaises( - NotImplementedError, loop.is_closed) - self.assertRaises( - NotImplementedError, loop.close) - self.assertRaises( - NotImplementedError, loop.create_task, None) - self.assertRaises( - NotImplementedError, loop.call_later, None, None) - self.assertRaises( - NotImplementedError, loop.call_at, f, f) - self.assertRaises( - NotImplementedError, loop.call_soon, None) - self.assertRaises( - NotImplementedError, loop.time) - self.assertRaises( - NotImplementedError, loop.call_soon_threadsafe, None) - self.assertRaises( - NotImplementedError, loop.set_default_executor, f) - self.assertRaises( - NotImplementedError, loop.add_reader, 1, f) - self.assertRaises( - NotImplementedError, loop.remove_reader, 1) - self.assertRaises( - NotImplementedError, loop.add_writer, 1, f) - self.assertRaises( - NotImplementedError, loop.remove_writer, 1) - self.assertRaises( - NotImplementedError, loop.add_signal_handler, 1, f) - self.assertRaises( - NotImplementedError, loop.remove_signal_handler, 1) - self.assertRaises( - NotImplementedError, loop.remove_signal_handler, 1) - self.assertRaises( - NotImplementedError, loop.set_exception_handler, f) - self.assertRaises( - NotImplementedError, loop.default_exception_handler, f) - self.assertRaises( - NotImplementedError, loop.call_exception_handler, f) - self.assertRaises( - NotImplementedError, loop.get_debug) - self.assertRaises( - NotImplementedError, loop.set_debug, f) - - def test_not_implemented_async(self): - - async def inner(): - f = mock.Mock() - loop = asyncio.AbstractEventLoop() - - with self.assertRaises(NotImplementedError): - await loop.run_in_executor(f, f) - with self.assertRaises(NotImplementedError): - await loop.getaddrinfo('localhost', 8080) - with self.assertRaises(NotImplementedError): - await loop.getnameinfo(('localhost', 8080)) - with self.assertRaises(NotImplementedError): - await loop.create_connection(f) - with self.assertRaises(NotImplementedError): - await loop.create_server(f) - with self.assertRaises(NotImplementedError): - await loop.create_datagram_endpoint(f) - with self.assertRaises(NotImplementedError): - await loop.sock_recv(f, 10) - with self.assertRaises(NotImplementedError): - await loop.sock_recv_into(f, 10) - with self.assertRaises(NotImplementedError): - await loop.sock_sendall(f, 10) - with self.assertRaises(NotImplementedError): - await loop.sock_connect(f, f) - with self.assertRaises(NotImplementedError): - await loop.sock_accept(f) - with self.assertRaises(NotImplementedError): - await loop.sock_sendfile(f, f) - with self.assertRaises(NotImplementedError): - await loop.sendfile(f, f) - with self.assertRaises(NotImplementedError): - await loop.connect_read_pipe(f, mock.sentinel.pipe) - with self.assertRaises(NotImplementedError): - await loop.connect_write_pipe(f, mock.sentinel.pipe) - with self.assertRaises(NotImplementedError): - await loop.subprocess_shell(f, mock.sentinel) - with self.assertRaises(NotImplementedError): - await loop.subprocess_exec(f) - - loop = asyncio.new_event_loop() - loop.run_until_complete(inner()) - loop.close() - - -class PolicyTests(unittest.TestCase): - - def test_event_loop_policy(self): - policy = asyncio.AbstractEventLoopPolicy() - self.assertRaises(NotImplementedError, policy.get_event_loop) - self.assertRaises(NotImplementedError, policy.set_event_loop, object()) - self.assertRaises(NotImplementedError, policy.new_event_loop) - self.assertRaises(NotImplementedError, policy.get_child_watcher) - self.assertRaises(NotImplementedError, policy.set_child_watcher, - object()) - - def test_get_event_loop(self): - policy = asyncio.DefaultEventLoopPolicy() - self.assertIsNone(policy._local._loop) - - loop = policy.get_event_loop() - self.assertIsInstance(loop, asyncio.AbstractEventLoop) - - self.assertIs(policy._local._loop, loop) - self.assertIs(loop, policy.get_event_loop()) - loop.close() - - def test_get_event_loop_calls_set_event_loop(self): - policy = asyncio.DefaultEventLoopPolicy() - - with mock.patch.object( - policy, "set_event_loop", - wraps=policy.set_event_loop) as m_set_event_loop: - - loop = policy.get_event_loop() - - # policy._local._loop must be set through .set_event_loop() - # (the unix DefaultEventLoopPolicy needs this call to attach - # the child watcher correctly) - m_set_event_loop.assert_called_with(loop) - - loop.close() - - def test_get_event_loop_after_set_none(self): - policy = asyncio.DefaultEventLoopPolicy() - policy.set_event_loop(None) - self.assertRaises(RuntimeError, policy.get_event_loop) - - @mock.patch('asyncio.events.threading.current_thread') - def test_get_event_loop_thread(self, m_current_thread): - - def f(): - policy = asyncio.DefaultEventLoopPolicy() - self.assertRaises(RuntimeError, policy.get_event_loop) - - th = threading.Thread(target=f) - th.start() - th.join() - - def test_new_event_loop(self): - policy = asyncio.DefaultEventLoopPolicy() - - loop = policy.new_event_loop() - self.assertIsInstance(loop, asyncio.AbstractEventLoop) - loop.close() - - def test_set_event_loop(self): - policy = asyncio.DefaultEventLoopPolicy() - old_loop = policy.get_event_loop() - - self.assertRaises(AssertionError, policy.set_event_loop, object()) - - loop = policy.new_event_loop() - policy.set_event_loop(loop) - self.assertIs(loop, policy.get_event_loop()) - self.assertIsNot(old_loop, policy.get_event_loop()) - loop.close() - old_loop.close() - - def test_get_event_loop_policy(self): - policy = asyncio.get_event_loop_policy() - self.assertIsInstance(policy, asyncio.AbstractEventLoopPolicy) - self.assertIs(policy, asyncio.get_event_loop_policy()) - - def test_set_event_loop_policy(self): - self.assertRaises( - AssertionError, asyncio.set_event_loop_policy, object()) - - old_policy = asyncio.get_event_loop_policy() - - policy = asyncio.DefaultEventLoopPolicy() - asyncio.set_event_loop_policy(policy) - self.assertIs(policy, asyncio.get_event_loop_policy()) - self.assertIsNot(policy, old_policy) - - -class GetEventLoopTestsMixin: - - _get_running_loop_impl = None - _set_running_loop_impl = None - get_running_loop_impl = None - get_event_loop_impl = None - - def setUp(self): - self._get_running_loop_saved = events._get_running_loop - self._set_running_loop_saved = events._set_running_loop - self.get_running_loop_saved = events.get_running_loop - self.get_event_loop_saved = events.get_event_loop - - events._get_running_loop = type(self)._get_running_loop_impl - events._set_running_loop = type(self)._set_running_loop_impl - events.get_running_loop = type(self).get_running_loop_impl - events.get_event_loop = type(self).get_event_loop_impl - - asyncio._get_running_loop = type(self)._get_running_loop_impl - asyncio._set_running_loop = type(self)._set_running_loop_impl - asyncio.get_running_loop = type(self).get_running_loop_impl - asyncio.get_event_loop = type(self).get_event_loop_impl - - super().setUp() - - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.loop) - - if sys.platform != 'win32': - watcher = asyncio.SafeChildWatcher() - watcher.attach_loop(self.loop) - asyncio.set_child_watcher(watcher) - - def tearDown(self): - try: - if sys.platform != 'win32': - asyncio.set_child_watcher(None) - - super().tearDown() - finally: - self.loop.close() - asyncio.set_event_loop(None) - - events._get_running_loop = self._get_running_loop_saved - events._set_running_loop = self._set_running_loop_saved - events.get_running_loop = self.get_running_loop_saved - events.get_event_loop = self.get_event_loop_saved - - asyncio._get_running_loop = self._get_running_loop_saved - asyncio._set_running_loop = self._set_running_loop_saved - asyncio.get_running_loop = self.get_running_loop_saved - asyncio.get_event_loop = self.get_event_loop_saved - - if sys.platform != 'win32': - - def test_get_event_loop_new_process(self): - # Issue bpo-32126: The multiprocessing module used by - # ProcessPoolExecutor is not functional when the - # multiprocessing.synchronize module cannot be imported. - support.import_module('multiprocessing.synchronize') - - async def main(): - pool = concurrent.futures.ProcessPoolExecutor() - result = await self.loop.run_in_executor( - pool, _test_get_event_loop_new_process__sub_proc) - pool.shutdown() - return result - - self.assertEqual( - self.loop.run_until_complete(main()), - 'hello') - - def test_get_event_loop_returns_running_loop(self): - class TestError(Exception): - pass - - class Policy(asyncio.DefaultEventLoopPolicy): - def get_event_loop(self): - raise TestError - - old_policy = asyncio.get_event_loop_policy() - try: - asyncio.set_event_loop_policy(Policy()) - loop = asyncio.new_event_loop() - - with self.assertRaises(TestError): - asyncio.get_event_loop() - asyncio.set_event_loop(None) - with self.assertRaises(TestError): - asyncio.get_event_loop() - - with self.assertRaisesRegex(RuntimeError, 'no running'): - self.assertIs(asyncio.get_running_loop(), None) - self.assertIs(asyncio._get_running_loop(), None) - - async def func(): - self.assertIs(asyncio.get_event_loop(), loop) - self.assertIs(asyncio.get_running_loop(), loop) - self.assertIs(asyncio._get_running_loop(), loop) - - loop.run_until_complete(func()) - - asyncio.set_event_loop(loop) - with self.assertRaises(TestError): - asyncio.get_event_loop() - - asyncio.set_event_loop(None) - with self.assertRaises(TestError): - asyncio.get_event_loop() - - finally: - asyncio.set_event_loop_policy(old_policy) - if loop is not None: - loop.close() - - with self.assertRaisesRegex(RuntimeError, 'no running'): - self.assertIs(asyncio.get_running_loop(), None) - - self.assertIs(asyncio._get_running_loop(), None) - - -class TestPyGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): - - _get_running_loop_impl = events._py__get_running_loop - _set_running_loop_impl = events._py__set_running_loop - get_running_loop_impl = events._py_get_running_loop - get_event_loop_impl = events._py_get_event_loop - - -try: - import _asyncio # NoQA -except ImportError: - pass -else: - - class TestCGetEventLoop(GetEventLoopTestsMixin, unittest.TestCase): - - _get_running_loop_impl = events._c__get_running_loop - _set_running_loop_impl = events._c__set_running_loop - get_running_loop_impl = events._c_get_running_loop - get_event_loop_impl = events._c_get_event_loop - - -class TestServer(unittest.TestCase): - - def test_get_loop(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - proto = MyProto(loop) - server = loop.run_until_complete(loop.create_server(lambda: proto, '0.0.0.0', 0)) - self.assertEqual(server.get_loop(), loop) - server.close() - loop.run_until_complete(server.wait_closed()) - - -class TestAbstractServer(unittest.TestCase): - - def test_close(self): - with self.assertRaises(NotImplementedError): - events.AbstractServer().close() - - def test_wait_closed(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - with self.assertRaises(NotImplementedError): - loop.run_until_complete(events.AbstractServer().wait_closed()) - - def test_get_loop(self): - with self.assertRaises(NotImplementedError): - events.AbstractServer().get_loop() - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py deleted file mode 100644 index ee5edd5..0000000 --- a/Lib/test/test_asyncio/test_futures.py +++ /dev/null @@ -1,865 +0,0 @@ -"""Tests for futures.py.""" - -import concurrent.futures -import gc -import re -import sys -import threading -import unittest -from unittest import mock - -import asyncio -from asyncio import futures -from test.test_asyncio import utils as test_utils -from test import support - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -def _fakefunc(f): - return f - - -def first_cb(): - pass - - -def last_cb(): - pass - - -class DuckFuture: - # Class that does not inherit from Future but aims to be duck-type - # compatible with it. - - _asyncio_future_blocking = False - __cancelled = False - __result = None - __exception = None - - def cancel(self): - if self.done(): - return False - self.__cancelled = True - return True - - def cancelled(self): - return self.__cancelled - - def done(self): - return (self.__cancelled - or self.__result is not None - or self.__exception is not None) - - def result(self): - assert not self.cancelled() - if self.__exception is not None: - raise self.__exception - return self.__result - - def exception(self): - assert not self.cancelled() - return self.__exception - - def set_result(self, result): - assert not self.done() - assert result is not None - self.__result = result - - def set_exception(self, exception): - assert not self.done() - assert exception is not None - self.__exception = exception - - def __iter__(self): - if not self.done(): - self._asyncio_future_blocking = True - yield self - assert self.done() - return self.result() - - -class DuckTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.addCleanup(self.loop.close) - - def test_wrap_future(self): - f = DuckFuture() - g = asyncio.wrap_future(f) - assert g is f - - def test_ensure_future(self): - f = DuckFuture() - g = asyncio.ensure_future(f) - assert g is f - - -class BaseFutureTests: - - def _new_future(self, *args, **kwargs): - return self.cls(*args, **kwargs) - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.addCleanup(self.loop.close) - - def test_isfuture(self): - class MyFuture: - _asyncio_future_blocking = None - - def __init__(self): - self._asyncio_future_blocking = False - - self.assertFalse(asyncio.isfuture(MyFuture)) - self.assertTrue(asyncio.isfuture(MyFuture())) - self.assertFalse(asyncio.isfuture(1)) - - # As `isinstance(Mock(), Future)` returns `False` - self.assertFalse(asyncio.isfuture(mock.Mock())) - - f = self._new_future(loop=self.loop) - self.assertTrue(asyncio.isfuture(f)) - self.assertFalse(asyncio.isfuture(type(f))) - - # As `isinstance(Mock(Future), Future)` returns `True` - self.assertTrue(asyncio.isfuture(mock.Mock(type(f)))) - - f.cancel() - - def test_initial_state(self): - f = self._new_future(loop=self.loop) - self.assertFalse(f.cancelled()) - self.assertFalse(f.done()) - f.cancel() - self.assertTrue(f.cancelled()) - - def test_init_constructor_default_loop(self): - asyncio.set_event_loop(self.loop) - f = self._new_future() - self.assertIs(f._loop, self.loop) - self.assertIs(f.get_loop(), self.loop) - - def test_constructor_positional(self): - # Make sure Future doesn't accept a positional argument - self.assertRaises(TypeError, self._new_future, 42) - - def test_uninitialized(self): - # Test that C Future doesn't crash when Future.__init__() - # call was skipped. - - fut = self.cls.__new__(self.cls, loop=self.loop) - self.assertRaises(asyncio.InvalidStateError, fut.result) - - fut = self.cls.__new__(self.cls, loop=self.loop) - self.assertRaises(asyncio.InvalidStateError, fut.exception) - - fut = self.cls.__new__(self.cls, loop=self.loop) - with self.assertRaises((RuntimeError, AttributeError)): - fut.set_result(None) - - fut = self.cls.__new__(self.cls, loop=self.loop) - with self.assertRaises((RuntimeError, AttributeError)): - fut.set_exception(Exception) - - fut = self.cls.__new__(self.cls, loop=self.loop) - with self.assertRaises((RuntimeError, AttributeError)): - fut.cancel() - - fut = self.cls.__new__(self.cls, loop=self.loop) - with self.assertRaises((RuntimeError, AttributeError)): - fut.add_done_callback(lambda f: None) - - fut = self.cls.__new__(self.cls, loop=self.loop) - with self.assertRaises((RuntimeError, AttributeError)): - fut.remove_done_callback(lambda f: None) - - fut = self.cls.__new__(self.cls, loop=self.loop) - try: - repr(fut) - except (RuntimeError, AttributeError): - pass - - fut = self.cls.__new__(self.cls, loop=self.loop) - try: - fut.__await__() - except RuntimeError: - pass - - fut = self.cls.__new__(self.cls, loop=self.loop) - try: - iter(fut) - except RuntimeError: - pass - - fut = self.cls.__new__(self.cls, loop=self.loop) - self.assertFalse(fut.cancelled()) - self.assertFalse(fut.done()) - - def test_cancel(self): - f = self._new_future(loop=self.loop) - self.assertTrue(f.cancel()) - self.assertTrue(f.cancelled()) - self.assertTrue(f.done()) - self.assertRaises(asyncio.CancelledError, f.result) - self.assertRaises(asyncio.CancelledError, f.exception) - self.assertRaises(asyncio.InvalidStateError, f.set_result, None) - self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) - self.assertFalse(f.cancel()) - - def test_result(self): - f = self._new_future(loop=self.loop) - self.assertRaises(asyncio.InvalidStateError, f.result) - - f.set_result(42) - self.assertFalse(f.cancelled()) - self.assertTrue(f.done()) - self.assertEqual(f.result(), 42) - self.assertEqual(f.exception(), None) - self.assertRaises(asyncio.InvalidStateError, f.set_result, None) - self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) - self.assertFalse(f.cancel()) - - def test_exception(self): - exc = RuntimeError() - f = self._new_future(loop=self.loop) - self.assertRaises(asyncio.InvalidStateError, f.exception) - - # StopIteration cannot be raised into a Future - CPython issue26221 - self.assertRaisesRegex(TypeError, "StopIteration .* cannot be raised", - f.set_exception, StopIteration) - - f.set_exception(exc) - self.assertFalse(f.cancelled()) - self.assertTrue(f.done()) - self.assertRaises(RuntimeError, f.result) - self.assertEqual(f.exception(), exc) - self.assertRaises(asyncio.InvalidStateError, f.set_result, None) - self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) - self.assertFalse(f.cancel()) - - def test_exception_class(self): - f = self._new_future(loop=self.loop) - f.set_exception(RuntimeError) - self.assertIsInstance(f.exception(), RuntimeError) - - def test_yield_from_twice(self): - f = self._new_future(loop=self.loop) - - def fixture(): - yield 'A' - x = yield from f - yield 'B', x - y = yield from f - yield 'C', y - - g = fixture() - self.assertEqual(next(g), 'A') # yield 'A'. - self.assertEqual(next(g), f) # First yield from f. - f.set_result(42) - self.assertEqual(next(g), ('B', 42)) # yield 'B', x. - # The second "yield from f" does not yield f. - self.assertEqual(next(g), ('C', 42)) # yield 'C', y. - - def test_future_repr(self): - self.loop.set_debug(True) - f_pending_debug = self._new_future(loop=self.loop) - frame = f_pending_debug._source_traceback[-1] - self.assertEqual( - repr(f_pending_debug), - f'<{self.cls.__name__} pending created at {frame[0]}:{frame[1]}>') - f_pending_debug.cancel() - - self.loop.set_debug(False) - f_pending = self._new_future(loop=self.loop) - self.assertEqual(repr(f_pending), f'<{self.cls.__name__} pending>') - f_pending.cancel() - - f_cancelled = self._new_future(loop=self.loop) - f_cancelled.cancel() - self.assertEqual(repr(f_cancelled), f'<{self.cls.__name__} cancelled>') - - f_result = self._new_future(loop=self.loop) - f_result.set_result(4) - self.assertEqual( - repr(f_result), f'<{self.cls.__name__} finished result=4>') - self.assertEqual(f_result.result(), 4) - - exc = RuntimeError() - f_exception = self._new_future(loop=self.loop) - f_exception.set_exception(exc) - self.assertEqual( - repr(f_exception), - f'<{self.cls.__name__} finished exception=RuntimeError()>') - self.assertIs(f_exception.exception(), exc) - - def func_repr(func): - filename, lineno = test_utils.get_function_source(func) - text = '%s() at %s:%s' % (func.__qualname__, filename, lineno) - return re.escape(text) - - f_one_callbacks = self._new_future(loop=self.loop) - f_one_callbacks.add_done_callback(_fakefunc) - fake_repr = func_repr(_fakefunc) - self.assertRegex( - repr(f_one_callbacks), - r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % fake_repr) - f_one_callbacks.cancel() - self.assertEqual(repr(f_one_callbacks), - f'<{self.cls.__name__} cancelled>') - - f_two_callbacks = self._new_future(loop=self.loop) - f_two_callbacks.add_done_callback(first_cb) - f_two_callbacks.add_done_callback(last_cb) - first_repr = func_repr(first_cb) - last_repr = func_repr(last_cb) - self.assertRegex(repr(f_two_callbacks), - r'<' + self.cls.__name__ + r' pending cb=\[%s, %s\]>' - % (first_repr, last_repr)) - - f_many_callbacks = self._new_future(loop=self.loop) - f_many_callbacks.add_done_callback(first_cb) - for i in range(8): - f_many_callbacks.add_done_callback(_fakefunc) - f_many_callbacks.add_done_callback(last_cb) - cb_regex = r'%s, <8 more>, %s' % (first_repr, last_repr) - self.assertRegex( - repr(f_many_callbacks), - r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % cb_regex) - f_many_callbacks.cancel() - self.assertEqual(repr(f_many_callbacks), - f'<{self.cls.__name__} cancelled>') - - def test_copy_state(self): - from asyncio.futures import _copy_future_state - - f = self._new_future(loop=self.loop) - f.set_result(10) - - newf = self._new_future(loop=self.loop) - _copy_future_state(f, newf) - self.assertTrue(newf.done()) - self.assertEqual(newf.result(), 10) - - f_exception = self._new_future(loop=self.loop) - f_exception.set_exception(RuntimeError()) - - newf_exception = self._new_future(loop=self.loop) - _copy_future_state(f_exception, newf_exception) - self.assertTrue(newf_exception.done()) - self.assertRaises(RuntimeError, newf_exception.result) - - f_cancelled = self._new_future(loop=self.loop) - f_cancelled.cancel() - - newf_cancelled = self._new_future(loop=self.loop) - _copy_future_state(f_cancelled, newf_cancelled) - self.assertTrue(newf_cancelled.cancelled()) - - def test_iter(self): - fut = self._new_future(loop=self.loop) - - def coro(): - yield from fut - - def test(): - arg1, arg2 = coro() - - with self.assertRaisesRegex(RuntimeError, "await wasn't used"): - test() - fut.cancel() - - def test_log_traceback(self): - fut = self._new_future(loop=self.loop) - with self.assertRaisesRegex(ValueError, 'can only be set to False'): - fut._log_traceback = True - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_abandoned(self, m_log): - fut = self._new_future(loop=self.loop) - del fut - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_not_called_after_cancel(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_exception(Exception()) - fut.cancel() - del fut - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_result_unretrieved(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_result(42) - del fut - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_result_retrieved(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_result(42) - fut.result() - del fut - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_exception_unretrieved(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_exception(RuntimeError('boom')) - del fut - test_utils.run_briefly(self.loop) - support.gc_collect() - self.assertTrue(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_exception_retrieved(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_exception(RuntimeError('boom')) - fut.exception() - del fut - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_exception_result_retrieved(self, m_log): - fut = self._new_future(loop=self.loop) - fut.set_exception(RuntimeError('boom')) - self.assertRaises(RuntimeError, fut.result) - del fut - self.assertFalse(m_log.error.called) - - def test_wrap_future(self): - - def run(arg): - return (arg, threading.get_ident()) - ex = concurrent.futures.ThreadPoolExecutor(1) - f1 = ex.submit(run, 'oi') - f2 = asyncio.wrap_future(f1, loop=self.loop) - res, ident = self.loop.run_until_complete(f2) - self.assertTrue(asyncio.isfuture(f2)) - self.assertEqual(res, 'oi') - self.assertNotEqual(ident, threading.get_ident()) - ex.shutdown(wait=True) - - def test_wrap_future_future(self): - f1 = self._new_future(loop=self.loop) - f2 = asyncio.wrap_future(f1) - self.assertIs(f1, f2) - - def test_wrap_future_use_global_loop(self): - with mock.patch('asyncio.futures.events') as events: - events.get_event_loop = lambda: self.loop - def run(arg): - return (arg, threading.get_ident()) - ex = concurrent.futures.ThreadPoolExecutor(1) - f1 = ex.submit(run, 'oi') - f2 = asyncio.wrap_future(f1) - self.assertIs(self.loop, f2._loop) - ex.shutdown(wait=True) - - def test_wrap_future_cancel(self): - f1 = concurrent.futures.Future() - f2 = asyncio.wrap_future(f1, loop=self.loop) - f2.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(f1.cancelled()) - self.assertTrue(f2.cancelled()) - - def test_wrap_future_cancel2(self): - f1 = concurrent.futures.Future() - f2 = asyncio.wrap_future(f1, loop=self.loop) - f1.set_result(42) - f2.cancel() - test_utils.run_briefly(self.loop) - self.assertFalse(f1.cancelled()) - self.assertEqual(f1.result(), 42) - self.assertTrue(f2.cancelled()) - - def test_future_source_traceback(self): - self.loop.set_debug(True) - - future = self._new_future(loop=self.loop) - lineno = sys._getframe().f_lineno - 1 - self.assertIsInstance(future._source_traceback, list) - self.assertEqual(future._source_traceback[-2][:3], - (__file__, - lineno, - 'test_future_source_traceback')) - - @mock.patch('asyncio.base_events.logger') - def check_future_exception_never_retrieved(self, debug, m_log): - self.loop.set_debug(debug) - - def memory_error(): - try: - raise MemoryError() - except BaseException as exc: - return exc - exc = memory_error() - - future = self._new_future(loop=self.loop) - future.set_exception(exc) - future = None - test_utils.run_briefly(self.loop) - support.gc_collect() - - if sys.version_info >= (3, 4): - regex = f'^{self.cls.__name__} exception was never retrieved\n' - exc_info = (type(exc), exc, exc.__traceback__) - m_log.error.assert_called_once_with(mock.ANY, exc_info=exc_info) - else: - regex = r'^Future/Task exception was never retrieved\n' - m_log.error.assert_called_once_with(mock.ANY, exc_info=False) - message = m_log.error.call_args[0][0] - self.assertRegex(message, re.compile(regex, re.DOTALL)) - - def test_future_exception_never_retrieved(self): - self.check_future_exception_never_retrieved(False) - - def test_future_exception_never_retrieved_debug(self): - self.check_future_exception_never_retrieved(True) - - def test_set_result_unless_cancelled(self): - fut = self._new_future(loop=self.loop) - fut.cancel() - futures._set_result_unless_cancelled(fut, 2) - self.assertTrue(fut.cancelled()) - - def test_future_stop_iteration_args(self): - fut = self._new_future(loop=self.loop) - fut.set_result((1, 2)) - fi = fut.__iter__() - result = None - try: - fi.send(None) - except StopIteration as ex: - result = ex.args[0] - else: - self.fail('StopIteration was expected') - self.assertEqual(result, (1, 2)) - - def test_future_iter_throw(self): - fut = self._new_future(loop=self.loop) - fi = iter(fut) - self.assertRaises(TypeError, fi.throw, - Exception, Exception("elephant"), 32) - self.assertRaises(TypeError, fi.throw, - Exception("elephant"), Exception("elephant")) - self.assertRaises(TypeError, fi.throw, list) - - def test_future_del_collect(self): - class Evil: - def __del__(self): - gc.collect() - - for i in range(100): - fut = self._new_future(loop=self.loop) - fut.set_result(Evil()) - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -class CFutureTests(BaseFutureTests, test_utils.TestCase): - try: - cls = futures._CFuture - except AttributeError: - cls = None - - def test_future_del_segfault(self): - fut = self._new_future(loop=self.loop) - with self.assertRaises(AttributeError): - del fut._asyncio_future_blocking - with self.assertRaises(AttributeError): - del fut._log_traceback - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -class CSubFutureTests(BaseFutureTests, test_utils.TestCase): - try: - class CSubFuture(futures._CFuture): - pass - - cls = CSubFuture - except AttributeError: - cls = None - - -class PyFutureTests(BaseFutureTests, test_utils.TestCase): - cls = futures._PyFuture - - -class BaseFutureDoneCallbackTests(): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def run_briefly(self): - test_utils.run_briefly(self.loop) - - def _make_callback(self, bag, thing): - # Create a callback function that appends thing to bag. - def bag_appender(future): - bag.append(thing) - return bag_appender - - def _new_future(self): - raise NotImplementedError - - def test_callbacks_remove_first_callback(self): - bag = [] - f = self._new_future() - - cb1 = self._make_callback(bag, 42) - cb2 = self._make_callback(bag, 17) - cb3 = self._make_callback(bag, 100) - - f.add_done_callback(cb1) - f.add_done_callback(cb2) - f.add_done_callback(cb3) - - f.remove_done_callback(cb1) - f.remove_done_callback(cb1) - - self.assertEqual(bag, []) - f.set_result('foo') - - self.run_briefly() - - self.assertEqual(bag, [17, 100]) - self.assertEqual(f.result(), 'foo') - - def test_callbacks_remove_first_and_second_callback(self): - bag = [] - f = self._new_future() - - cb1 = self._make_callback(bag, 42) - cb2 = self._make_callback(bag, 17) - cb3 = self._make_callback(bag, 100) - - f.add_done_callback(cb1) - f.add_done_callback(cb2) - f.add_done_callback(cb3) - - f.remove_done_callback(cb1) - f.remove_done_callback(cb2) - f.remove_done_callback(cb1) - - self.assertEqual(bag, []) - f.set_result('foo') - - self.run_briefly() - - self.assertEqual(bag, [100]) - self.assertEqual(f.result(), 'foo') - - def test_callbacks_remove_third_callback(self): - bag = [] - f = self._new_future() - - cb1 = self._make_callback(bag, 42) - cb2 = self._make_callback(bag, 17) - cb3 = self._make_callback(bag, 100) - - f.add_done_callback(cb1) - f.add_done_callback(cb2) - f.add_done_callback(cb3) - - f.remove_done_callback(cb3) - f.remove_done_callback(cb3) - - self.assertEqual(bag, []) - f.set_result('foo') - - self.run_briefly() - - self.assertEqual(bag, [42, 17]) - self.assertEqual(f.result(), 'foo') - - def test_callbacks_invoked_on_set_result(self): - bag = [] - f = self._new_future() - f.add_done_callback(self._make_callback(bag, 42)) - f.add_done_callback(self._make_callback(bag, 17)) - - self.assertEqual(bag, []) - f.set_result('foo') - - self.run_briefly() - - self.assertEqual(bag, [42, 17]) - self.assertEqual(f.result(), 'foo') - - def test_callbacks_invoked_on_set_exception(self): - bag = [] - f = self._new_future() - f.add_done_callback(self._make_callback(bag, 100)) - - self.assertEqual(bag, []) - exc = RuntimeError() - f.set_exception(exc) - - self.run_briefly() - - self.assertEqual(bag, [100]) - self.assertEqual(f.exception(), exc) - - def test_remove_done_callback(self): - bag = [] - f = self._new_future() - cb1 = self._make_callback(bag, 1) - cb2 = self._make_callback(bag, 2) - cb3 = self._make_callback(bag, 3) - - # Add one cb1 and one cb2. - f.add_done_callback(cb1) - f.add_done_callback(cb2) - - # One instance of cb2 removed. Now there's only one cb1. - self.assertEqual(f.remove_done_callback(cb2), 1) - - # Never had any cb3 in there. - self.assertEqual(f.remove_done_callback(cb3), 0) - - # After this there will be 6 instances of cb1 and one of cb2. - f.add_done_callback(cb2) - for i in range(5): - f.add_done_callback(cb1) - - # Remove all instances of cb1. One cb2 remains. - self.assertEqual(f.remove_done_callback(cb1), 6) - - self.assertEqual(bag, []) - f.set_result('foo') - - self.run_briefly() - - self.assertEqual(bag, [2]) - self.assertEqual(f.result(), 'foo') - - def test_remove_done_callbacks_list_mutation(self): - # see http://bugs.python.org/issue28963 for details - - fut = self._new_future() - fut.add_done_callback(str) - - for _ in range(63): - fut.add_done_callback(id) - - class evil: - def __eq__(self, other): - fut.remove_done_callback(id) - return False - - fut.remove_done_callback(evil()) - - def test_schedule_callbacks_list_mutation_1(self): - # see http://bugs.python.org/issue28963 for details - - def mut(f): - f.remove_done_callback(str) - - fut = self._new_future() - fut.add_done_callback(mut) - fut.add_done_callback(str) - fut.add_done_callback(str) - fut.set_result(1) - test_utils.run_briefly(self.loop) - - def test_schedule_callbacks_list_mutation_2(self): - # see http://bugs.python.org/issue30828 for details - - fut = self._new_future() - fut.add_done_callback(str) - - for _ in range(63): - fut.add_done_callback(id) - - max_extra_cbs = 100 - extra_cbs = 0 - - class evil: - def __eq__(self, other): - nonlocal extra_cbs - extra_cbs += 1 - if extra_cbs < max_extra_cbs: - fut.add_done_callback(id) - return False - - fut.remove_done_callback(evil()) - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -class CFutureDoneCallbackTests(BaseFutureDoneCallbackTests, - test_utils.TestCase): - - def _new_future(self): - return futures._CFuture(loop=self.loop) - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -class CSubFutureDoneCallbackTests(BaseFutureDoneCallbackTests, - test_utils.TestCase): - - def _new_future(self): - class CSubFuture(futures._CFuture): - pass - return CSubFuture(loop=self.loop) - - -class PyFutureDoneCallbackTests(BaseFutureDoneCallbackTests, - test_utils.TestCase): - - def _new_future(self): - return futures._PyFuture(loop=self.loop) - - -class BaseFutureInheritanceTests: - - def _get_future_cls(self): - raise NotImplementedError - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.addCleanup(self.loop.close) - - def test_inherit_without_calling_super_init(self): - # See https://bugs.python.org/issue38785 for the context - cls = self._get_future_cls() - - class MyFut(cls): - def __init__(self, *args, **kwargs): - # don't call super().__init__() - pass - - fut = MyFut(loop=self.loop) - with self.assertRaisesRegex( - RuntimeError, - "Future object is not initialized." - ): - fut.get_loop() - - -class PyFutureInheritanceTests(BaseFutureInheritanceTests, - test_utils.TestCase): - def _get_future_cls(self): - return futures._PyFuture - - -class CFutureInheritanceTests(BaseFutureInheritanceTests, - test_utils.TestCase): - def _get_future_cls(self): - return futures._CFuture - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py deleted file mode 100644 index 9468e74..0000000 --- a/Lib/test/test_asyncio/test_locks.py +++ /dev/null @@ -1,1101 +0,0 @@ -"""Tests for lock.py""" - -import unittest -from unittest import mock -import re - -import asyncio -from test.test_asyncio import utils as test_utils - -STR_RGX_REPR = ( - r'^<(?P<class>.*?) object at (?P<address>.*?)' - r'\[(?P<extras>' - r'(set|unset|locked|unlocked)(, value:\d)?(, waiters:\d+)?' - r')\]>\Z' -) -RGX_REPR = re.compile(STR_RGX_REPR) - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class LockTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): - loop = mock.Mock() - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=loop) - self.assertIs(lock._loop, loop) - - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.assertIs(lock._loop, self.loop) - - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) - lock = asyncio.Lock() - self.assertIs(lock._loop, self.loop) - - def test_repr(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.assertTrue(repr(lock).endswith('[unlocked]>')) - self.assertTrue(RGX_REPR.match(repr(lock))) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - yield from lock - - self.loop.run_until_complete(acquire_lock()) - self.assertTrue(repr(lock).endswith('[locked]>')) - self.assertTrue(RGX_REPR.match(repr(lock))) - - def test_lock(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - return (yield from lock) - - res = self.loop.run_until_complete(acquire_lock()) - - self.assertTrue(res) - self.assertTrue(lock.locked()) - - lock.release() - self.assertFalse(lock.locked()) - - def test_lock_by_with_statement(self): - loop = asyncio.new_event_loop() # don't use TestLoop quirks - self.set_event_loop(loop) - with self.assertWarns(DeprecationWarning): - primitives = [ - asyncio.Lock(loop=loop), - asyncio.Condition(loop=loop), - asyncio.Semaphore(loop=loop), - asyncio.BoundedSemaphore(loop=loop), - ] - - @asyncio.coroutine - def test(lock): - yield from asyncio.sleep(0.01) - self.assertFalse(lock.locked()) - with self.assertWarns(DeprecationWarning): - with (yield from lock) as _lock: - self.assertIs(_lock, None) - self.assertTrue(lock.locked()) - yield from asyncio.sleep(0.01) - self.assertTrue(lock.locked()) - self.assertFalse(lock.locked()) - - for primitive in primitives: - loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) - - def test_acquire(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - result = [] - - self.assertTrue(self.loop.run_until_complete(lock.acquire())) - - async def c1(result): - if await lock.acquire(): - result.append(1) - return True - - async def c2(result): - if await lock.acquire(): - result.append(2) - return True - - async def c3(result): - if await lock.acquire(): - result.append(3) - return True - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - lock.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - - t3 = self.loop.create_task(c3(result)) - - lock.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2], result) - - lock.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2, 3], result) - - self.assertTrue(t1.done()) - self.assertTrue(t1.result()) - self.assertTrue(t2.done()) - self.assertTrue(t2.result()) - self.assertTrue(t3.done()) - self.assertTrue(t3.result()) - - def test_acquire_cancel(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.assertTrue(self.loop.run_until_complete(lock.acquire())) - - task = self.loop.create_task(lock.acquire()) - self.loop.call_soon(task.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, task) - self.assertFalse(lock._waiters) - - def test_cancel_race(self): - # Several tasks: - # - A acquires the lock - # - B is blocked in acquire() - # - C is blocked in acquire() - # - # Now, concurrently: - # - B is cancelled - # - A releases the lock - # - # If B's waiter is marked cancelled but not yet removed from - # _waiters, A's release() call will crash when trying to set - # B's waiter; instead, it should move on to C's waiter. - - # Setup: A has the lock, b and c are waiting. - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - async def lockit(name, blocker): - await lock.acquire() - try: - if blocker is not None: - await blocker - finally: - lock.release() - - fa = self.loop.create_future() - ta = self.loop.create_task(lockit('A', fa)) - test_utils.run_briefly(self.loop) - self.assertTrue(lock.locked()) - tb = self.loop.create_task(lockit('B', None)) - test_utils.run_briefly(self.loop) - self.assertEqual(len(lock._waiters), 1) - tc = self.loop.create_task(lockit('C', None)) - test_utils.run_briefly(self.loop) - self.assertEqual(len(lock._waiters), 2) - - # Create the race and check. - # Without the fix this failed at the last assert. - fa.set_result(None) - tb.cancel() - self.assertTrue(lock._waiters[0].cancelled()) - test_utils.run_briefly(self.loop) - self.assertFalse(lock.locked()) - self.assertTrue(ta.done()) - self.assertTrue(tb.cancelled()) - self.assertTrue(tc.done()) - - def test_cancel_release_race(self): - # Issue 32734 - # Acquire 4 locks, cancel second, release first - # and 2 locks are taken at once. - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - lock_count = 0 - call_count = 0 - - async def lockit(): - nonlocal lock_count - nonlocal call_count - call_count += 1 - await lock.acquire() - lock_count += 1 - - async def lockandtrigger(): - await lock.acquire() - self.loop.call_soon(trigger) - - def trigger(): - t1.cancel() - lock.release() - - t0 = self.loop.create_task(lockandtrigger()) - t1 = self.loop.create_task(lockit()) - t2 = self.loop.create_task(lockit()) - t3 = self.loop.create_task(lockit()) - - # First loop acquires all - test_utils.run_briefly(self.loop) - self.assertTrue(t0.done()) - - # Second loop calls trigger - test_utils.run_briefly(self.loop) - # Third loop calls cancellation - test_utils.run_briefly(self.loop) - - # Make sure only one lock was taken - self.assertEqual(lock_count, 1) - # While 3 calls were made to lockit() - self.assertEqual(call_count, 3) - self.assertTrue(t1.cancelled() and t2.done()) - - # Cleanup the task that is stuck on acquire. - t3.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(t3.cancelled()) - - def test_finished_waiter_cancelled(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - ta = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) - self.assertTrue(lock.locked()) - - tb = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) - self.assertEqual(len(lock._waiters), 1) - - # Create a second waiter, wake up the first, and cancel it. - # Without the fix, the second was not woken up. - tc = self.loop.create_task(lock.acquire()) - lock.release() - tb.cancel() - test_utils.run_briefly(self.loop) - - self.assertTrue(lock.locked()) - self.assertTrue(ta.done()) - self.assertTrue(tb.cancelled()) - - def test_release_not_acquired(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - self.assertRaises(RuntimeError, lock.release) - - def test_release_no_waiters(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - self.loop.run_until_complete(lock.acquire()) - self.assertTrue(lock.locked()) - - lock.release() - self.assertFalse(lock.locked()) - - def test_context_manager(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - return (yield from lock) - - with self.loop.run_until_complete(acquire_lock()): - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) - - def test_context_manager_cant_reuse(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - return (yield from lock) - - # This spells "yield from lock" outside a generator. - cm = self.loop.run_until_complete(acquire_lock()) - with cm: - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) - - with self.assertRaises(AttributeError): - with cm: - pass - - def test_context_manager_no_yield(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - - try: - with lock: - self.fail('RuntimeError is not raised in with expression') - except RuntimeError as err: - self.assertEqual( - str(err), - '"yield from" should be used as context manager expression') - - self.assertFalse(lock.locked()) - - -class EventTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): - loop = mock.Mock() - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=loop) - self.assertIs(ev._loop, loop) - - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - self.assertIs(ev._loop, self.loop) - - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) - ev = asyncio.Event() - self.assertIs(ev._loop, self.loop) - - def test_repr(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - self.assertTrue(repr(ev).endswith('[unset]>')) - match = RGX_REPR.match(repr(ev)) - self.assertEqual(match.group('extras'), 'unset') - - ev.set() - self.assertTrue(repr(ev).endswith('[set]>')) - self.assertTrue(RGX_REPR.match(repr(ev))) - - ev._waiters.append(mock.Mock()) - self.assertTrue('waiters:1' in repr(ev)) - self.assertTrue(RGX_REPR.match(repr(ev))) - - def test_wait(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - self.assertFalse(ev.is_set()) - - result = [] - - async def c1(result): - if await ev.wait(): - result.append(1) - - async def c2(result): - if await ev.wait(): - result.append(2) - - async def c3(result): - if await ev.wait(): - result.append(3) - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - t3 = self.loop.create_task(c3(result)) - - ev.set() - test_utils.run_briefly(self.loop) - self.assertEqual([3, 1, 2], result) - - self.assertTrue(t1.done()) - self.assertIsNone(t1.result()) - self.assertTrue(t2.done()) - self.assertIsNone(t2.result()) - self.assertTrue(t3.done()) - self.assertIsNone(t3.result()) - - def test_wait_on_set(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - ev.set() - - res = self.loop.run_until_complete(ev.wait()) - self.assertTrue(res) - - def test_wait_cancel(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - - wait = self.loop.create_task(ev.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) - self.assertFalse(ev._waiters) - - def test_clear(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - self.assertFalse(ev.is_set()) - - ev.set() - self.assertTrue(ev.is_set()) - - ev.clear() - self.assertFalse(ev.is_set()) - - def test_clear_with_waiters(self): - with self.assertWarns(DeprecationWarning): - ev = asyncio.Event(loop=self.loop) - result = [] - - async def c1(result): - if await ev.wait(): - result.append(1) - return True - - t = self.loop.create_task(c1(result)) - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - ev.set() - ev.clear() - self.assertFalse(ev.is_set()) - - ev.set() - ev.set() - self.assertEqual(1, len(ev._waiters)) - - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - self.assertEqual(0, len(ev._waiters)) - - self.assertTrue(t.done()) - self.assertTrue(t.result()) - - -class ConditionTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): - loop = mock.Mock() - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=loop) - self.assertIs(cond._loop, loop) - - cond = asyncio.Condition(loop=self.loop) - self.assertIs(cond._loop, self.loop) - - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) - cond = asyncio.Condition() - self.assertIs(cond._loop, self.loop) - - def test_wait(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - result = [] - - async def c1(result): - await cond.acquire() - if await cond.wait(): - result.append(1) - return True - - async def c2(result): - await cond.acquire() - if await cond.wait(): - result.append(2) - return True - - async def c3(result): - await cond.acquire() - if await cond.wait(): - result.append(3) - return True - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - self.assertFalse(cond.locked()) - - self.assertTrue(self.loop.run_until_complete(cond.acquire())) - cond.notify() - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - self.assertTrue(cond.locked()) - - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - self.assertTrue(cond.locked()) - - cond.notify(2) - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - self.assertTrue(cond.locked()) - - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2], result) - self.assertTrue(cond.locked()) - - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2, 3], result) - self.assertTrue(cond.locked()) - - self.assertTrue(t1.done()) - self.assertTrue(t1.result()) - self.assertTrue(t2.done()) - self.assertTrue(t2.result()) - self.assertTrue(t3.done()) - self.assertTrue(t3.result()) - - def test_wait_cancel(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.loop.run_until_complete(cond.acquire()) - - wait = self.loop.create_task(cond.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) - self.assertFalse(cond._waiters) - self.assertTrue(cond.locked()) - - def test_wait_cancel_contested(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - - self.loop.run_until_complete(cond.acquire()) - self.assertTrue(cond.locked()) - - wait_task = self.loop.create_task(cond.wait()) - test_utils.run_briefly(self.loop) - self.assertFalse(cond.locked()) - - # Notify, but contest the lock before cancelling - self.loop.run_until_complete(cond.acquire()) - self.assertTrue(cond.locked()) - cond.notify() - self.loop.call_soon(wait_task.cancel) - self.loop.call_soon(cond.release) - - try: - self.loop.run_until_complete(wait_task) - except asyncio.CancelledError: - # Should not happen, since no cancellation points - pass - - self.assertTrue(cond.locked()) - - def test_wait_cancel_after_notify(self): - # See bpo-32841 - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - waited = False - - async def wait_on_cond(): - nonlocal waited - async with cond: - waited = True # Make sure this area was reached - await cond.wait() - - waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) - test_utils.run_briefly(self.loop) # Start waiting - - self.loop.run_until_complete(cond.acquire()) - cond.notify() - test_utils.run_briefly(self.loop) # Get to acquire() - waiter.cancel() - test_utils.run_briefly(self.loop) # Activate cancellation - cond.release() - test_utils.run_briefly(self.loop) # Cancellation should occur - - self.assertTrue(waiter.cancelled()) - self.assertTrue(waited) - - def test_wait_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, cond.wait()) - - def test_wait_for(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - presult = False - - def predicate(): - return presult - - result = [] - - async def c1(result): - await cond.acquire() - if await cond.wait_for(predicate): - result.append(1) - cond.release() - return True - - t = self.loop.create_task(c1(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - self.loop.run_until_complete(cond.acquire()) - cond.notify() - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - presult = True - self.loop.run_until_complete(cond.acquire()) - cond.notify() - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - - self.assertTrue(t.done()) - self.assertTrue(t.result()) - - def test_wait_for_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - - # predicate can return true immediately - res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3])) - self.assertEqual([1, 2, 3], res) - - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, - cond.wait_for(lambda: False)) - - def test_notify(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - result = [] - - async def c1(result): - await cond.acquire() - if await cond.wait(): - result.append(1) - cond.release() - return True - - async def c2(result): - await cond.acquire() - if await cond.wait(): - result.append(2) - cond.release() - return True - - async def c3(result): - await cond.acquire() - if await cond.wait(): - result.append(3) - cond.release() - return True - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - self.loop.run_until_complete(cond.acquire()) - cond.notify(1) - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - - self.loop.run_until_complete(cond.acquire()) - cond.notify(1) - cond.notify(2048) - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2, 3], result) - - self.assertTrue(t1.done()) - self.assertTrue(t1.result()) - self.assertTrue(t2.done()) - self.assertTrue(t2.result()) - self.assertTrue(t3.done()) - self.assertTrue(t3.result()) - - def test_notify_all(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - - result = [] - - async def c1(result): - await cond.acquire() - if await cond.wait(): - result.append(1) - cond.release() - return True - - async def c2(result): - await cond.acquire() - if await cond.wait(): - result.append(2) - cond.release() - return True - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([], result) - - self.loop.run_until_complete(cond.acquire()) - cond.notify_all() - cond.release() - test_utils.run_briefly(self.loop) - self.assertEqual([1, 2], result) - - self.assertTrue(t1.done()) - self.assertTrue(t1.result()) - self.assertTrue(t2.done()) - self.assertTrue(t2.result()) - - def test_notify_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.assertRaises(RuntimeError, cond.notify) - - def test_notify_all_unacquired(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.assertRaises(RuntimeError, cond.notify_all) - - def test_repr(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - self.assertTrue('unlocked' in repr(cond)) - self.assertTrue(RGX_REPR.match(repr(cond))) - - self.loop.run_until_complete(cond.acquire()) - self.assertTrue('locked' in repr(cond)) - - cond._waiters.append(mock.Mock()) - self.assertTrue('waiters:1' in repr(cond)) - self.assertTrue(RGX_REPR.match(repr(cond))) - - cond._waiters.append(mock.Mock()) - self.assertTrue('waiters:2' in repr(cond)) - self.assertTrue(RGX_REPR.match(repr(cond))) - - def test_context_manager(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def acquire_cond(): - with self.assertWarns(DeprecationWarning): - return (yield from cond) - - with self.loop.run_until_complete(acquire_cond()): - self.assertTrue(cond.locked()) - - self.assertFalse(cond.locked()) - - def test_context_manager_no_yield(self): - with self.assertWarns(DeprecationWarning): - cond = asyncio.Condition(loop=self.loop) - - try: - with cond: - self.fail('RuntimeError is not raised in with expression') - except RuntimeError as err: - self.assertEqual( - str(err), - '"yield from" should be used as context manager expression') - - self.assertFalse(cond.locked()) - - def test_explicit_lock(self): - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - cond = asyncio.Condition(lock, loop=self.loop) - - self.assertIs(cond._lock, lock) - self.assertIs(cond._loop, lock._loop) - - def test_ambiguous_loops(self): - loop = self.new_test_loop() - self.addCleanup(loop.close) - with self.assertWarns(DeprecationWarning): - lock = asyncio.Lock(loop=self.loop) - with self.assertRaises(ValueError): - asyncio.Condition(lock, loop=loop) - - def test_timeout_in_block(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def task_timeout(): - condition = asyncio.Condition(loop=loop) - async with condition: - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(condition.wait(), timeout=0.5) - - with self.assertWarns(DeprecationWarning): - loop.run_until_complete(task_timeout()) - - -class SemaphoreTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_ctor_loop(self): - loop = mock.Mock() - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=loop) - self.assertIs(sem._loop, loop) - - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.assertIs(sem._loop, self.loop) - - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) - sem = asyncio.Semaphore() - self.assertIs(sem._loop, self.loop) - - def test_initial_value_zero(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(0, loop=self.loop) - self.assertTrue(sem.locked()) - - def test_repr(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) - self.assertTrue(RGX_REPR.match(repr(sem))) - - self.loop.run_until_complete(sem.acquire()) - self.assertTrue(repr(sem).endswith('[locked]>')) - self.assertTrue('waiters' not in repr(sem)) - self.assertTrue(RGX_REPR.match(repr(sem))) - - sem._waiters.append(mock.Mock()) - self.assertTrue('waiters:1' in repr(sem)) - self.assertTrue(RGX_REPR.match(repr(sem))) - - sem._waiters.append(mock.Mock()) - self.assertTrue('waiters:2' in repr(sem)) - self.assertTrue(RGX_REPR.match(repr(sem))) - - def test_semaphore(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.assertEqual(1, sem._value) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - return (yield from sem) - - res = self.loop.run_until_complete(acquire_lock()) - - self.assertTrue(res) - self.assertTrue(sem.locked()) - self.assertEqual(0, sem._value) - - sem.release() - self.assertFalse(sem.locked()) - self.assertEqual(1, sem._value) - - def test_semaphore_value(self): - self.assertRaises(ValueError, asyncio.Semaphore, -1) - - def test_acquire(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(3, loop=self.loop) - result = [] - - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertFalse(sem.locked()) - - async def c1(result): - await sem.acquire() - result.append(1) - return True - - async def c2(result): - await sem.acquire() - result.append(2) - return True - - async def c3(result): - await sem.acquire() - result.append(3) - return True - - async def c4(result): - await sem.acquire() - result.append(4) - return True - - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) - - test_utils.run_briefly(self.loop) - self.assertEqual([1], result) - self.assertTrue(sem.locked()) - self.assertEqual(2, len(sem._waiters)) - self.assertEqual(0, sem._value) - - t4 = self.loop.create_task(c4(result)) - - sem.release() - sem.release() - self.assertEqual(2, sem._value) - - test_utils.run_briefly(self.loop) - self.assertEqual(0, sem._value) - self.assertEqual(3, len(result)) - self.assertTrue(sem.locked()) - self.assertEqual(1, len(sem._waiters)) - self.assertEqual(0, sem._value) - - self.assertTrue(t1.done()) - self.assertTrue(t1.result()) - race_tasks = [t2, t3, t4] - done_tasks = [t for t in race_tasks if t.done() and t.result()] - self.assertTrue(2, len(done_tasks)) - - # cleanup locked semaphore - sem.release() - self.loop.run_until_complete(asyncio.gather(*race_tasks)) - - def test_acquire_cancel(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.loop.run_until_complete(sem.acquire()) - - acquire = self.loop.create_task(sem.acquire()) - self.loop.call_soon(acquire.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, acquire) - self.assertTrue((not sem._waiters) or - all(waiter.done() for waiter in sem._waiters)) - - def test_acquire_cancel_before_awoken(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(value=0, loop=self.loop) - - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - t3 = self.loop.create_task(sem.acquire()) - t4 = self.loop.create_task(sem.acquire()) - - test_utils.run_briefly(self.loop) - - sem.release() - t1.cancel() - t2.cancel() - - test_utils.run_briefly(self.loop) - num_done = sum(t.done() for t in [t3, t4]) - self.assertEqual(num_done, 1) - - t3.cancel() - t4.cancel() - test_utils.run_briefly(self.loop) - - def test_acquire_hang(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(value=0, loop=self.loop) - - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - - test_utils.run_briefly(self.loop) - - sem.release() - t1.cancel() - - test_utils.run_briefly(self.loop) - self.assertTrue(sem.locked()) - - def test_release_not_acquired(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.BoundedSemaphore(loop=self.loop) - - self.assertRaises(ValueError, sem.release) - - def test_release_no_waiters(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(loop=self.loop) - self.loop.run_until_complete(sem.acquire()) - self.assertTrue(sem.locked()) - - sem.release() - self.assertFalse(sem.locked()) - - def test_context_manager(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(2, loop=self.loop) - - @asyncio.coroutine - def acquire_lock(): - with self.assertWarns(DeprecationWarning): - return (yield from sem) - - with self.loop.run_until_complete(acquire_lock()): - self.assertFalse(sem.locked()) - self.assertEqual(1, sem._value) - - with self.loop.run_until_complete(acquire_lock()): - self.assertTrue(sem.locked()) - - self.assertEqual(2, sem._value) - - def test_context_manager_no_yield(self): - with self.assertWarns(DeprecationWarning): - sem = asyncio.Semaphore(2, loop=self.loop) - - try: - with sem: - self.fail('RuntimeError is not raised in with expression') - except RuntimeError as err: - self.assertEqual( - str(err), - '"yield from" should be used as context manager expression') - - self.assertEqual(2, sem._value) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py deleted file mode 100644 index a1f27dd..0000000 --- a/Lib/test/test_asyncio/test_pep492.py +++ /dev/null @@ -1,223 +0,0 @@ -"""Tests support for new syntax introduced by PEP 492.""" - -import sys -import types -import unittest - -from unittest import mock - -import asyncio -from test.test_asyncio import utils as test_utils - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -# Test that asyncio.iscoroutine() uses collections.abc.Coroutine -class FakeCoro: - def send(self, value): - pass - - def throw(self, typ, val=None, tb=None): - pass - - def close(self): - pass - - def __await__(self): - yield - - -class BaseTest(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.BaseEventLoop() - self.loop._process_events = mock.Mock() - self.loop._selector = mock.Mock() - self.loop._selector.select.return_value = () - self.set_event_loop(self.loop) - - -class LockTests(BaseTest): - - def test_context_manager_async_with(self): - with self.assertWarns(DeprecationWarning): - primitives = [ - asyncio.Lock(loop=self.loop), - asyncio.Condition(loop=self.loop), - asyncio.Semaphore(loop=self.loop), - asyncio.BoundedSemaphore(loop=self.loop), - ] - - async def test(lock): - await asyncio.sleep(0.01) - self.assertFalse(lock.locked()) - async with lock as _lock: - self.assertIs(_lock, None) - self.assertTrue(lock.locked()) - await asyncio.sleep(0.01) - self.assertTrue(lock.locked()) - self.assertFalse(lock.locked()) - - for primitive in primitives: - self.loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) - - def test_context_manager_with_await(self): - with self.assertWarns(DeprecationWarning): - primitives = [ - asyncio.Lock(loop=self.loop), - asyncio.Condition(loop=self.loop), - asyncio.Semaphore(loop=self.loop), - asyncio.BoundedSemaphore(loop=self.loop), - ] - - async def test(lock): - await asyncio.sleep(0.01) - self.assertFalse(lock.locked()) - with self.assertWarns(DeprecationWarning): - with await lock as _lock: - self.assertIs(_lock, None) - self.assertTrue(lock.locked()) - await asyncio.sleep(0.01) - self.assertTrue(lock.locked()) - self.assertFalse(lock.locked()) - - for primitive in primitives: - self.loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) - - -class StreamReaderTests(BaseTest): - - def test_readline(self): - DATA = b'line1\nline2\nline3' - - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(DATA) - stream.feed_eof() - - async def reader(): - data = [] - async for line in stream: - data.append(line) - return data - - data = self.loop.run_until_complete(reader()) - self.assertEqual(data, [b'line1\n', b'line2\n', b'line3']) - - -class CoroutineTests(BaseTest): - - def test_iscoroutine(self): - async def foo(): pass - - f = foo() - try: - self.assertTrue(asyncio.iscoroutine(f)) - finally: - f.close() # silence warning - - self.assertTrue(asyncio.iscoroutine(FakeCoro())) - - def test_iscoroutinefunction(self): - async def foo(): pass - self.assertTrue(asyncio.iscoroutinefunction(foo)) - - def test_function_returning_awaitable(self): - class Awaitable: - def __await__(self): - return ('spam',) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def func(): - return Awaitable() - - coro = func() - self.assertEqual(coro.send(None), 'spam') - coro.close() - - def test_async_def_coroutines(self): - async def bar(): - return 'spam' - async def foo(): - return await bar() - - # production mode - data = self.loop.run_until_complete(foo()) - self.assertEqual(data, 'spam') - - # debug mode - self.loop.set_debug(True) - data = self.loop.run_until_complete(foo()) - self.assertEqual(data, 'spam') - - def test_debug_mode_manages_coroutine_origin_tracking(self): - async def start(): - self.assertTrue(sys.get_coroutine_origin_tracking_depth() > 0) - - self.assertEqual(sys.get_coroutine_origin_tracking_depth(), 0) - self.loop.set_debug(True) - self.loop.run_until_complete(start()) - self.assertEqual(sys.get_coroutine_origin_tracking_depth(), 0) - - def test_types_coroutine(self): - def gen(): - yield from () - return 'spam' - - @types.coroutine - def func(): - return gen() - - async def coro(): - wrapper = func() - self.assertIsInstance(wrapper, types._GeneratorWrapper) - return await wrapper - - data = self.loop.run_until_complete(coro()) - self.assertEqual(data, 'spam') - - def test_task_print_stack(self): - T = None - - async def foo(): - f = T.get_stack(limit=1) - try: - self.assertEqual(f[0].f_code.co_name, 'foo') - finally: - f = None - - async def runner(): - nonlocal T - T = asyncio.ensure_future(foo(), loop=self.loop) - await T - - self.loop.run_until_complete(runner()) - - def test_double_await(self): - async def afunc(): - await asyncio.sleep(0.1) - - async def runner(): - coro = afunc() - t = self.loop.create_task(coro) - try: - await asyncio.sleep(0) - await coro - finally: - t.cancel() - - self.loop.set_debug(True) - with self.assertRaises( - RuntimeError, - msg='coroutine is being awaited already'): - - self.loop.run_until_complete(runner()) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py deleted file mode 100644 index 007039a..0000000 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ /dev/null @@ -1,1004 +0,0 @@ -"""Tests for proactor_events.py""" - -import io -import socket -import unittest -import sys -from unittest import mock - -import asyncio -from asyncio.proactor_events import BaseProactorEventLoop -from asyncio.proactor_events import _ProactorSocketTransport -from asyncio.proactor_events import _ProactorWritePipeTransport -from asyncio.proactor_events import _ProactorDuplexPipeTransport -from asyncio.proactor_events import _ProactorDatagramTransport -from test import support -from test.test_asyncio import utils as test_utils - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -def close_transport(transport): - # Don't call transport.close() because the event loop and the IOCP proactor - # are mocked - if transport._sock is None: - return - transport._sock.close() - transport._sock = None - - -class ProactorSocketTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.addCleanup(self.loop.close) - self.proactor = mock.Mock() - self.loop._proactor = self.proactor - self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = mock.Mock(socket.socket) - - def socket_transport(self, waiter=None): - transport = _ProactorSocketTransport(self.loop, self.sock, - self.protocol, waiter=waiter) - self.addCleanup(close_transport, transport) - return transport - - def test_ctor(self): - fut = self.loop.create_future() - tr = self.socket_transport(waiter=fut) - test_utils.run_briefly(self.loop) - self.assertIsNone(fut.result()) - self.protocol.connection_made(tr) - self.proactor.recv.assert_called_with(self.sock, 32768) - - def test_loop_reading(self): - tr = self.socket_transport() - tr._loop_reading() - self.loop._proactor.recv.assert_called_with(self.sock, 32768) - self.assertFalse(self.protocol.data_received.called) - self.assertFalse(self.protocol.eof_received.called) - - def test_loop_reading_data(self): - res = self.loop.create_future() - res.set_result(b'data') - - tr = self.socket_transport() - tr._read_fut = res - tr._loop_reading(res) - self.loop._proactor.recv.assert_called_with(self.sock, 32768) - self.protocol.data_received.assert_called_with(b'data') - - def test_loop_reading_no_data(self): - res = self.loop.create_future() - res.set_result(b'') - - tr = self.socket_transport() - self.assertRaises(AssertionError, tr._loop_reading, res) - - tr.close = mock.Mock() - tr._read_fut = res - tr._loop_reading(res) - self.assertFalse(self.loop._proactor.recv.called) - self.assertTrue(self.protocol.eof_received.called) - self.assertTrue(tr.close.called) - - def test_loop_reading_aborted(self): - err = self.loop._proactor.recv.side_effect = ConnectionAbortedError() - - tr = self.socket_transport() - tr._fatal_error = mock.Mock() - tr._loop_reading() - tr._fatal_error.assert_called_with( - err, - 'Fatal read error on pipe transport') - - def test_loop_reading_aborted_closing(self): - self.loop._proactor.recv.side_effect = ConnectionAbortedError() - - tr = self.socket_transport() - tr._closing = True - tr._fatal_error = mock.Mock() - tr._loop_reading() - self.assertFalse(tr._fatal_error.called) - - def test_loop_reading_aborted_is_fatal(self): - self.loop._proactor.recv.side_effect = ConnectionAbortedError() - tr = self.socket_transport() - tr._closing = False - tr._fatal_error = mock.Mock() - tr._loop_reading() - self.assertTrue(tr._fatal_error.called) - - def test_loop_reading_conn_reset_lost(self): - err = self.loop._proactor.recv.side_effect = ConnectionResetError() - - tr = self.socket_transport() - tr._closing = False - tr._fatal_error = mock.Mock() - tr._force_close = mock.Mock() - tr._loop_reading() - self.assertFalse(tr._fatal_error.called) - tr._force_close.assert_called_with(err) - - def test_loop_reading_exception(self): - err = self.loop._proactor.recv.side_effect = (OSError()) - - tr = self.socket_transport() - tr._fatal_error = mock.Mock() - tr._loop_reading() - tr._fatal_error.assert_called_with( - err, - 'Fatal read error on pipe transport') - - def test_write(self): - tr = self.socket_transport() - tr._loop_writing = mock.Mock() - tr.write(b'data') - self.assertEqual(tr._buffer, None) - tr._loop_writing.assert_called_with(data=b'data') - - def test_write_no_data(self): - tr = self.socket_transport() - tr.write(b'') - self.assertFalse(tr._buffer) - - def test_write_more(self): - tr = self.socket_transport() - tr._write_fut = mock.Mock() - tr._loop_writing = mock.Mock() - tr.write(b'data') - self.assertEqual(tr._buffer, b'data') - self.assertFalse(tr._loop_writing.called) - - def test_loop_writing(self): - tr = self.socket_transport() - tr._buffer = bytearray(b'data') - tr._loop_writing() - self.loop._proactor.send.assert_called_with(self.sock, b'data') - self.loop._proactor.send.return_value.add_done_callback.\ - assert_called_with(tr._loop_writing) - - @mock.patch('asyncio.proactor_events.logger') - def test_loop_writing_err(self, m_log): - err = self.loop._proactor.send.side_effect = OSError() - tr = self.socket_transport() - tr._fatal_error = mock.Mock() - tr._buffer = [b'da', b'ta'] - tr._loop_writing() - tr._fatal_error.assert_called_with( - err, - 'Fatal write error on pipe transport') - tr._conn_lost = 1 - - tr.write(b'data') - tr.write(b'data') - tr.write(b'data') - tr.write(b'data') - tr.write(b'data') - self.assertEqual(tr._buffer, None) - m_log.warning.assert_called_with('socket.send() raised exception.') - - def test_loop_writing_stop(self): - fut = self.loop.create_future() - fut.set_result(b'data') - - tr = self.socket_transport() - tr._write_fut = fut - tr._loop_writing(fut) - self.assertIsNone(tr._write_fut) - - def test_loop_writing_closing(self): - fut = self.loop.create_future() - fut.set_result(1) - - tr = self.socket_transport() - tr._write_fut = fut - tr.close() - tr._loop_writing(fut) - self.assertIsNone(tr._write_fut) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - - def test_abort(self): - tr = self.socket_transport() - tr._force_close = mock.Mock() - tr.abort() - tr._force_close.assert_called_with(None) - - def test_close(self): - tr = self.socket_transport() - tr.close() - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - self.assertTrue(tr.is_closing()) - self.assertEqual(tr._conn_lost, 1) - - self.protocol.connection_lost.reset_mock() - tr.close() - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.connection_lost.called) - - def test_close_write_fut(self): - tr = self.socket_transport() - tr._write_fut = mock.Mock() - tr.close() - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.connection_lost.called) - - def test_close_buffer(self): - tr = self.socket_transport() - tr._buffer = [b'data'] - tr.close() - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.connection_lost.called) - - @mock.patch('asyncio.base_events.logger') - def test_fatal_error(self, m_logging): - tr = self.socket_transport() - tr._force_close = mock.Mock() - tr._fatal_error(None) - self.assertTrue(tr._force_close.called) - self.assertTrue(m_logging.error.called) - - def test_force_close(self): - tr = self.socket_transport() - tr._buffer = [b'data'] - read_fut = tr._read_fut = mock.Mock() - write_fut = tr._write_fut = mock.Mock() - tr._force_close(None) - - read_fut.cancel.assert_called_with() - write_fut.cancel.assert_called_with() - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - self.assertEqual(None, tr._buffer) - self.assertEqual(tr._conn_lost, 1) - - def test_loop_writing_force_close(self): - exc_handler = mock.Mock() - self.loop.set_exception_handler(exc_handler) - fut = self.loop.create_future() - fut.set_result(1) - self.proactor.send.return_value = fut - - tr = self.socket_transport() - tr.write(b'data') - tr._force_close(None) - test_utils.run_briefly(self.loop) - exc_handler.assert_not_called() - - def test_force_close_idempotent(self): - tr = self.socket_transport() - tr._closing = True - tr._force_close(None) - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.connection_lost.called) - - def test_fatal_error_2(self): - tr = self.socket_transport() - tr._buffer = [b'data'] - tr._force_close(None) - - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - self.assertEqual(None, tr._buffer) - - def test_call_connection_lost(self): - tr = self.socket_transport() - tr._call_connection_lost(None) - self.assertTrue(self.protocol.connection_lost.called) - self.assertTrue(self.sock.close.called) - - def test_write_eof(self): - tr = self.socket_transport() - self.assertTrue(tr.can_write_eof()) - tr.write_eof() - self.sock.shutdown.assert_called_with(socket.SHUT_WR) - tr.write_eof() - self.assertEqual(self.sock.shutdown.call_count, 1) - tr.close() - - def test_write_eof_buffer(self): - tr = self.socket_transport() - f = self.loop.create_future() - tr._loop._proactor.send.return_value = f - tr.write(b'data') - tr.write_eof() - self.assertTrue(tr._eof_written) - self.assertFalse(self.sock.shutdown.called) - tr._loop._proactor.send.assert_called_with(self.sock, b'data') - f.set_result(4) - self.loop._run_once() - self.sock.shutdown.assert_called_with(socket.SHUT_WR) - tr.close() - - def test_write_eof_write_pipe(self): - tr = _ProactorWritePipeTransport( - self.loop, self.sock, self.protocol) - self.assertTrue(tr.can_write_eof()) - tr.write_eof() - self.assertTrue(tr.is_closing()) - self.loop._run_once() - self.assertTrue(self.sock.close.called) - tr.close() - - def test_write_eof_buffer_write_pipe(self): - tr = _ProactorWritePipeTransport(self.loop, self.sock, self.protocol) - f = self.loop.create_future() - tr._loop._proactor.send.return_value = f - tr.write(b'data') - tr.write_eof() - self.assertTrue(tr.is_closing()) - self.assertFalse(self.sock.shutdown.called) - tr._loop._proactor.send.assert_called_with(self.sock, b'data') - f.set_result(4) - self.loop._run_once() - self.loop._run_once() - self.assertTrue(self.sock.close.called) - tr.close() - - def test_write_eof_duplex_pipe(self): - tr = _ProactorDuplexPipeTransport( - self.loop, self.sock, self.protocol) - self.assertFalse(tr.can_write_eof()) - with self.assertRaises(NotImplementedError): - tr.write_eof() - close_transport(tr) - - def test_pause_resume_reading(self): - tr = self.socket_transport() - futures = [] - for msg in [b'data1', b'data2', b'data3', b'data4', b'data5', b'']: - f = self.loop.create_future() - f.set_result(msg) - futures.append(f) - - self.loop._proactor.recv.side_effect = futures - self.loop._run_once() - self.assertFalse(tr._paused) - self.assertTrue(tr.is_reading()) - self.loop._run_once() - self.protocol.data_received.assert_called_with(b'data1') - self.loop._run_once() - self.protocol.data_received.assert_called_with(b'data2') - - tr.pause_reading() - tr.pause_reading() - self.assertTrue(tr._paused) - self.assertFalse(tr.is_reading()) - for i in range(10): - self.loop._run_once() - self.protocol.data_received.assert_called_with(b'data2') - - tr.resume_reading() - tr.resume_reading() - self.assertFalse(tr._paused) - self.assertTrue(tr.is_reading()) - self.loop._run_once() - self.protocol.data_received.assert_called_with(b'data3') - self.loop._run_once() - self.protocol.data_received.assert_called_with(b'data4') - - tr.pause_reading() - tr.resume_reading() - self.loop.call_exception_handler = mock.Mock() - self.loop._run_once() - self.loop.call_exception_handler.assert_not_called() - self.protocol.data_received.assert_called_with(b'data5') - tr.close() - - self.assertFalse(tr.is_reading()) - - - def pause_writing_transport(self, high): - tr = self.socket_transport() - tr.set_write_buffer_limits(high=high) - - self.assertEqual(tr.get_write_buffer_size(), 0) - self.assertFalse(self.protocol.pause_writing.called) - self.assertFalse(self.protocol.resume_writing.called) - return tr - - def test_pause_resume_writing(self): - tr = self.pause_writing_transport(high=4) - - # write a large chunk, must pause writing - fut = self.loop.create_future() - self.loop._proactor.send.return_value = fut - tr.write(b'large data') - self.loop._run_once() - self.assertTrue(self.protocol.pause_writing.called) - - # flush the buffer - fut.set_result(None) - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 0) - self.assertTrue(self.protocol.resume_writing.called) - - def test_pause_writing_2write(self): - tr = self.pause_writing_transport(high=4) - - # first short write, the buffer is not full (3 <= 4) - fut1 = self.loop.create_future() - self.loop._proactor.send.return_value = fut1 - tr.write(b'123') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 3) - self.assertFalse(self.protocol.pause_writing.called) - - # fill the buffer, must pause writing (6 > 4) - tr.write(b'abc') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 6) - self.assertTrue(self.protocol.pause_writing.called) - - def test_pause_writing_3write(self): - tr = self.pause_writing_transport(high=4) - - # first short write, the buffer is not full (1 <= 4) - fut = self.loop.create_future() - self.loop._proactor.send.return_value = fut - tr.write(b'1') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 1) - self.assertFalse(self.protocol.pause_writing.called) - - # second short write, the buffer is not full (3 <= 4) - tr.write(b'23') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 3) - self.assertFalse(self.protocol.pause_writing.called) - - # fill the buffer, must pause writing (6 > 4) - tr.write(b'abc') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 6) - self.assertTrue(self.protocol.pause_writing.called) - - def test_dont_pause_writing(self): - tr = self.pause_writing_transport(high=4) - - # write a large chunk which completes immediately, - # it should not pause writing - fut = self.loop.create_future() - fut.set_result(None) - self.loop._proactor.send.return_value = fut - tr.write(b'very large data') - self.loop._run_once() - self.assertEqual(tr.get_write_buffer_size(), 0) - self.assertFalse(self.protocol.pause_writing.called) - - -class ProactorDatagramTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.proactor = mock.Mock() - self.loop._proactor = self.proactor - self.protocol = test_utils.make_test_protocol(asyncio.DatagramProtocol) - self.sock = mock.Mock(spec_set=socket.socket) - self.sock.fileno.return_value = 7 - - def datagram_transport(self, address=None): - self.sock.getpeername.side_effect = None if address else OSError - transport = _ProactorDatagramTransport(self.loop, self.sock, - self.protocol, - address=address) - self.addCleanup(close_transport, transport) - return transport - - def test_sendto(self): - data = b'data' - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.proactor.sendto.called) - self.proactor.sendto.assert_called_with( - self.sock, data, addr=('0.0.0.0', 1234)) - - def test_sendto_bytearray(self): - data = bytearray(b'data') - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.proactor.sendto.called) - self.proactor.sendto.assert_called_with( - self.sock, b'data', addr=('0.0.0.0', 1234)) - - def test_sendto_memoryview(self): - data = memoryview(b'data') - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.proactor.sendto.called) - self.proactor.sendto.assert_called_with( - self.sock, b'data', addr=('0.0.0.0', 1234)) - - def test_sendto_no_data(self): - transport = self.datagram_transport() - transport._buffer.append((b'data', ('0.0.0.0', 12345))) - transport.sendto(b'', ()) - self.assertFalse(self.sock.sendto.called) - self.assertEqual( - [(b'data', ('0.0.0.0', 12345))], list(transport._buffer)) - - def test_sendto_buffer(self): - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport._write_fut = object() - transport.sendto(b'data2', ('0.0.0.0', 12345)) - self.assertFalse(self.proactor.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - - def test_sendto_buffer_bytearray(self): - data2 = bytearray(b'data2') - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport._write_fut = object() - transport.sendto(data2, ('0.0.0.0', 12345)) - self.assertFalse(self.proactor.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - self.assertIsInstance(transport._buffer[1][0], bytes) - - def test_sendto_buffer_memoryview(self): - data2 = memoryview(b'data2') - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport._write_fut = object() - transport.sendto(data2, ('0.0.0.0', 12345)) - self.assertFalse(self.proactor.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - self.assertIsInstance(transport._buffer[1][0], bytes) - - @mock.patch('asyncio.proactor_events.logger') - def test_sendto_exception(self, m_log): - data = b'data' - err = self.proactor.sendto.side_effect = RuntimeError() - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport.sendto(data, ()) - - self.assertTrue(transport._fatal_error.called) - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on datagram transport') - transport._conn_lost = 1 - - transport._address = ('123',) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - m_log.warning.assert_called_with('socket.sendto() raised exception.') - - def test_sendto_error_received(self): - data = b'data' - - self.sock.sendto.side_effect = ConnectionRefusedError - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport.sendto(data, ()) - - self.assertEqual(transport._conn_lost, 0) - self.assertFalse(transport._fatal_error.called) - - def test_sendto_error_received_connected(self): - data = b'data' - - self.proactor.send.side_effect = ConnectionRefusedError - - transport = self.datagram_transport(address=('0.0.0.0', 1)) - transport._fatal_error = mock.Mock() - transport.sendto(data) - - self.assertFalse(transport._fatal_error.called) - self.assertTrue(self.protocol.error_received.called) - - def test_sendto_str(self): - transport = self.datagram_transport() - self.assertRaises(TypeError, transport.sendto, 'str', ()) - - def test_sendto_connected_addr(self): - transport = self.datagram_transport(address=('0.0.0.0', 1)) - self.assertRaises( - ValueError, transport.sendto, b'str', ('0.0.0.0', 2)) - - def test_sendto_closing(self): - transport = self.datagram_transport(address=(1,)) - transport.close() - self.assertEqual(transport._conn_lost, 1) - transport.sendto(b'data', (1,)) - self.assertEqual(transport._conn_lost, 2) - - def test__loop_writing_closing(self): - transport = self.datagram_transport() - transport._closing = True - transport._loop_writing() - self.assertIsNone(transport._write_fut) - test_utils.run_briefly(self.loop) - self.sock.close.assert_called_with() - self.protocol.connection_lost.assert_called_with(None) - - def test__loop_writing_exception(self): - err = self.proactor.sendto.side_effect = RuntimeError() - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._loop_writing() - - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on datagram transport') - - def test__loop_writing_error_received(self): - self.proactor.sendto.side_effect = ConnectionRefusedError - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._loop_writing() - - self.assertFalse(transport._fatal_error.called) - - def test__loop_writing_error_received_connection(self): - self.proactor.send.side_effect = ConnectionRefusedError - - transport = self.datagram_transport(address=('0.0.0.0', 1)) - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._loop_writing() - - self.assertFalse(transport._fatal_error.called) - self.assertTrue(self.protocol.error_received.called) - - @mock.patch('asyncio.base_events.logger.error') - def test_fatal_error_connected(self, m_exc): - transport = self.datagram_transport(address=('0.0.0.0', 1)) - err = ConnectionRefusedError() - transport._fatal_error(err) - self.assertFalse(self.protocol.error_received.called) - m_exc.assert_not_called() - - -class BaseProactorEventLoopTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - - self.sock = test_utils.mock_nonblocking_socket() - self.proactor = mock.Mock() - - self.ssock, self.csock = mock.Mock(), mock.Mock() - - with mock.patch('asyncio.proactor_events.socket.socketpair', - return_value=(self.ssock, self.csock)): - with mock.patch('signal.set_wakeup_fd'): - self.loop = BaseProactorEventLoop(self.proactor) - self.set_event_loop(self.loop) - - @mock.patch('asyncio.proactor_events.socket.socketpair') - def test_ctor(self, socketpair): - ssock, csock = socketpair.return_value = ( - mock.Mock(), mock.Mock()) - with mock.patch('signal.set_wakeup_fd'): - loop = BaseProactorEventLoop(self.proactor) - self.assertIs(loop._ssock, ssock) - self.assertIs(loop._csock, csock) - self.assertEqual(loop._internal_fds, 1) - loop.close() - - def test_close_self_pipe(self): - self.loop._close_self_pipe() - self.assertEqual(self.loop._internal_fds, 0) - self.assertTrue(self.ssock.close.called) - self.assertTrue(self.csock.close.called) - self.assertIsNone(self.loop._ssock) - self.assertIsNone(self.loop._csock) - - # Don't call close(): _close_self_pipe() cannot be called twice - self.loop._closed = True - - def test_close(self): - self.loop._close_self_pipe = mock.Mock() - self.loop.close() - self.assertTrue(self.loop._close_self_pipe.called) - self.assertTrue(self.proactor.close.called) - self.assertIsNone(self.loop._proactor) - - self.loop._close_self_pipe.reset_mock() - self.loop.close() - self.assertFalse(self.loop._close_self_pipe.called) - - def test_make_socket_transport(self): - tr = self.loop._make_socket_transport(self.sock, asyncio.Protocol()) - self.assertIsInstance(tr, _ProactorSocketTransport) - close_transport(tr) - - def test_loop_self_reading(self): - self.loop._loop_self_reading() - self.proactor.recv.assert_called_with(self.ssock, 4096) - self.proactor.recv.return_value.add_done_callback.assert_called_with( - self.loop._loop_self_reading) - - def test_loop_self_reading_fut(self): - fut = mock.Mock() - self.loop._loop_self_reading(fut) - self.assertTrue(fut.result.called) - self.proactor.recv.assert_called_with(self.ssock, 4096) - self.proactor.recv.return_value.add_done_callback.assert_called_with( - self.loop._loop_self_reading) - - def test_loop_self_reading_exception(self): - self.loop.call_exception_handler = mock.Mock() - self.proactor.recv.side_effect = OSError() - self.loop._loop_self_reading() - self.assertTrue(self.loop.call_exception_handler.called) - - def test_write_to_self(self): - self.loop._write_to_self() - self.csock.send.assert_called_with(b'\0') - - def test_process_events(self): - self.loop._process_events([]) - - @mock.patch('asyncio.base_events.logger') - def test_create_server(self, m_log): - pf = mock.Mock() - call_soon = self.loop.call_soon = mock.Mock() - - self.loop._start_serving(pf, self.sock) - self.assertTrue(call_soon.called) - - # callback - loop = call_soon.call_args[0][0] - loop() - self.proactor.accept.assert_called_with(self.sock) - - # conn - fut = mock.Mock() - fut.result.return_value = (mock.Mock(), mock.Mock()) - - make_tr = self.loop._make_socket_transport = mock.Mock() - loop(fut) - self.assertTrue(fut.result.called) - self.assertTrue(make_tr.called) - - # exception - fut.result.side_effect = OSError() - loop(fut) - self.assertTrue(self.sock.close.called) - self.assertTrue(m_log.error.called) - - def test_create_server_cancel(self): - pf = mock.Mock() - call_soon = self.loop.call_soon = mock.Mock() - - self.loop._start_serving(pf, self.sock) - loop = call_soon.call_args[0][0] - - # cancelled - fut = self.loop.create_future() - fut.cancel() - loop(fut) - self.assertTrue(self.sock.close.called) - - def test_stop_serving(self): - sock1 = mock.Mock() - future1 = mock.Mock() - sock2 = mock.Mock() - future2 = mock.Mock() - self.loop._accept_futures = { - sock1.fileno(): future1, - sock2.fileno(): future2 - } - - self.loop._stop_serving(sock1) - self.assertTrue(sock1.close.called) - self.assertTrue(future1.cancel.called) - self.proactor._stop_serving.assert_called_with(sock1) - self.assertFalse(sock2.close.called) - self.assertFalse(future2.cancel.called) - - def datagram_transport(self): - self.protocol = test_utils.make_test_protocol(asyncio.DatagramProtocol) - return self.loop._make_datagram_transport(self.sock, self.protocol) - - def test_make_datagram_transport(self): - tr = self.datagram_transport() - self.assertIsInstance(tr, _ProactorDatagramTransport) - close_transport(tr) - - def test_datagram_loop_writing(self): - tr = self.datagram_transport() - tr._buffer.appendleft((b'data', ('127.0.0.1', 12068))) - tr._loop_writing() - self.loop._proactor.sendto.assert_called_with(self.sock, b'data', addr=('127.0.0.1', 12068)) - self.loop._proactor.sendto.return_value.add_done_callback.\ - assert_called_with(tr._loop_writing) - - close_transport(tr) - - def test_datagram_loop_reading(self): - tr = self.datagram_transport() - tr._loop_reading() - self.loop._proactor.recvfrom.assert_called_with(self.sock, 256 * 1024) - self.assertFalse(self.protocol.datagram_received.called) - self.assertFalse(self.protocol.error_received.called) - close_transport(tr) - - def test_datagram_loop_reading_data(self): - res = self.loop.create_future() - res.set_result((b'data', ('127.0.0.1', 12068))) - - tr = self.datagram_transport() - tr._read_fut = res - tr._loop_reading(res) - self.loop._proactor.recvfrom.assert_called_with(self.sock, 256 * 1024) - self.protocol.datagram_received.assert_called_with(b'data', ('127.0.0.1', 12068)) - close_transport(tr) - - def test_datagram_loop_reading_no_data(self): - res = self.loop.create_future() - res.set_result((b'', ('127.0.0.1', 12068))) - - tr = self.datagram_transport() - self.assertRaises(AssertionError, tr._loop_reading, res) - - tr.close = mock.Mock() - tr._read_fut = res - tr._loop_reading(res) - self.assertTrue(self.loop._proactor.recvfrom.called) - self.assertFalse(self.protocol.error_received.called) - self.assertFalse(tr.close.called) - close_transport(tr) - - def test_datagram_loop_reading_aborted(self): - err = self.loop._proactor.recvfrom.side_effect = ConnectionAbortedError() - - tr = self.datagram_transport() - tr._fatal_error = mock.Mock() - tr._protocol.error_received = mock.Mock() - tr._loop_reading() - tr._protocol.error_received.assert_called_with(err) - close_transport(tr) - - def test_datagram_loop_writing_aborted(self): - err = self.loop._proactor.sendto.side_effect = ConnectionAbortedError() - - tr = self.datagram_transport() - tr._fatal_error = mock.Mock() - tr._protocol.error_received = mock.Mock() - tr._buffer.appendleft((b'Hello', ('127.0.0.1', 12068))) - tr._loop_writing() - tr._protocol.error_received.assert_called_with(err) - close_transport(tr) - - -@unittest.skipIf(sys.platform != 'win32', - 'Proactor is supported on Windows only') -class ProactorEventLoopUnixSockSendfileTests(test_utils.TestCase): - DATA = b"12345abcde" * 16 * 1024 # 160 KiB - - class MyProto(asyncio.Protocol): - - def __init__(self, loop): - self.started = False - self.closed = False - self.data = bytearray() - self.fut = loop.create_future() - self.transport = None - - def connection_made(self, transport): - self.started = True - self.transport = transport - - def data_received(self, data): - self.data.extend(data) - - def connection_lost(self, exc): - self.closed = True - self.fut.set_result(None) - - async def wait_closed(self): - await self.fut - - @classmethod - def setUpClass(cls): - with open(support.TESTFN, 'wb') as fp: - fp.write(cls.DATA) - super().setUpClass() - - @classmethod - def tearDownClass(cls): - support.unlink(support.TESTFN) - super().tearDownClass() - - def setUp(self): - self.loop = asyncio.ProactorEventLoop() - self.set_event_loop(self.loop) - self.addCleanup(self.loop.close) - self.file = open(support.TESTFN, 'rb') - self.addCleanup(self.file.close) - super().setUp() - - def make_socket(self, cleanup=True): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(False) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) - if cleanup: - self.addCleanup(sock.close) - return sock - - def run_loop(self, coro): - return self.loop.run_until_complete(coro) - - def prepare(self): - sock = self.make_socket() - proto = self.MyProto(self.loop) - port = support.find_unused_port() - srv_sock = self.make_socket(cleanup=False) - srv_sock.bind(('127.0.0.1', port)) - server = self.run_loop(self.loop.create_server( - lambda: proto, sock=srv_sock)) - self.run_loop(self.loop.sock_connect(sock, srv_sock.getsockname())) - - def cleanup(): - if proto.transport is not None: - # can be None if the task was cancelled before - # connection_made callback - proto.transport.close() - self.run_loop(proto.wait_closed()) - - server.close() - self.run_loop(server.wait_closed()) - - self.addCleanup(cleanup) - - return sock, proto - - def test_sock_sendfile_not_a_file(self): - sock, proto = self.prepare() - f = object() - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_iobuffer(self): - sock, proto = self.prepare() - f = io.BytesIO() - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_not_regular_file(self): - sock, proto = self.prepare() - f = mock.Mock() - f.fileno.return_value = -1 - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_protocols.py b/Lib/test/test_asyncio/test_protocols.py deleted file mode 100644 index 438111c..0000000 --- a/Lib/test/test_asyncio/test_protocols.py +++ /dev/null @@ -1,57 +0,0 @@ -import unittest -from unittest import mock - -import asyncio - - -class ProtocolsAbsTests(unittest.TestCase): - - def test_base_protocol(self): - f = mock.Mock() - p = asyncio.BaseProtocol() - self.assertIsNone(p.connection_made(f)) - self.assertIsNone(p.connection_lost(f)) - self.assertIsNone(p.pause_writing()) - self.assertIsNone(p.resume_writing()) - self.assertFalse(hasattr(p, '__dict__')) - - def test_protocol(self): - f = mock.Mock() - p = asyncio.Protocol() - self.assertIsNone(p.connection_made(f)) - self.assertIsNone(p.connection_lost(f)) - self.assertIsNone(p.data_received(f)) - self.assertIsNone(p.eof_received()) - self.assertIsNone(p.pause_writing()) - self.assertIsNone(p.resume_writing()) - self.assertFalse(hasattr(p, '__dict__')) - - def test_buffered_protocol(self): - f = mock.Mock() - p = asyncio.BufferedProtocol() - self.assertIsNone(p.connection_made(f)) - self.assertIsNone(p.connection_lost(f)) - self.assertIsNone(p.get_buffer(100)) - self.assertIsNone(p.buffer_updated(150)) - self.assertIsNone(p.pause_writing()) - self.assertIsNone(p.resume_writing()) - self.assertFalse(hasattr(p, '__dict__')) - - def test_datagram_protocol(self): - f = mock.Mock() - dp = asyncio.DatagramProtocol() - self.assertIsNone(dp.connection_made(f)) - self.assertIsNone(dp.connection_lost(f)) - self.assertIsNone(dp.error_received(f)) - self.assertIsNone(dp.datagram_received(f, f)) - self.assertFalse(hasattr(dp, '__dict__')) - - def test_subprocess_protocol(self): - f = mock.Mock() - sp = asyncio.SubprocessProtocol() - self.assertIsNone(sp.connection_made(f)) - self.assertIsNone(sp.connection_lost(f)) - self.assertIsNone(sp.pipe_data_received(1, f)) - self.assertIsNone(sp.pipe_connection_lost(1, f)) - self.assertIsNone(sp.process_exited()) - self.assertFalse(hasattr(sp, '__dict__')) diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py deleted file mode 100644 index 5c9aaa8..0000000 --- a/Lib/test/test_asyncio/test_queues.py +++ /dev/null @@ -1,718 +0,0 @@ -"""Tests for queues.py""" - -import unittest -from unittest import mock - -import asyncio -from test.test_asyncio import utils as test_utils - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class _QueueTestBase(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - -class QueueBasicTests(_QueueTestBase): - - def _test_repr_or_str(self, fn, expect_id): - """Test Queue's repr or str. - - fn is repr or str. expect_id is True if we expect the Queue's id to - appear in fn(Queue()). - """ - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0.1 - self.assertAlmostEqual(0.2, when) - yield 0.1 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - self.assertTrue(fn(q).startswith('<Queue'), fn(q)) - id_is_present = hex(id(q)) in fn(q) - self.assertEqual(expect_id, id_is_present) - - async def add_getter(): - q = asyncio.Queue(loop=loop) - # Start a task that waits to get. - loop.create_task(q.get()) - # Let it start waiting. - await asyncio.sleep(0.1) - self.assertTrue('_getters[1]' in fn(q)) - # resume q.get coroutine to finish generator - q.put_nowait(0) - - with self.assertWarns(DeprecationWarning): - loop.run_until_complete(add_getter()) - - async def add_putter(): - q = asyncio.Queue(maxsize=1, loop=loop) - q.put_nowait(1) - # Start a task that waits to put. - loop.create_task(q.put(2)) - # Let it start waiting. - await asyncio.sleep(0.1) - self.assertTrue('_putters[1]' in fn(q)) - # resume q.put coroutine to finish generator - q.get_nowait() - - with self.assertWarns(DeprecationWarning): - loop.run_until_complete(add_putter()) - q = asyncio.Queue(loop=loop) - q.put_nowait(1) - self.assertTrue('_queue=[1]' in fn(q)) - - def test_ctor_loop(self): - loop = mock.Mock() - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - self.assertIs(q._loop, loop) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - self.assertIs(q._loop, self.loop) - - def test_ctor_noloop(self): - asyncio.set_event_loop(self.loop) - q = asyncio.Queue() - self.assertIs(q._loop, self.loop) - - def test_repr(self): - self._test_repr_or_str(repr, True) - - def test_str(self): - self._test_repr_or_str(str, False) - - def test_empty(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - self.assertTrue(q.empty()) - q.put_nowait(1) - self.assertFalse(q.empty()) - self.assertEqual(1, q.get_nowait()) - self.assertTrue(q.empty()) - - def test_full(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - self.assertFalse(q.full()) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=1, loop=self.loop) - q.put_nowait(1) - self.assertTrue(q.full()) - - def test_order(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - for i in [1, 3, 2]: - q.put_nowait(i) - - items = [q.get_nowait() for _ in range(3)] - self.assertEqual([1, 3, 2], items) - - def test_maxsize(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.01, when) - when = yield 0.01 - self.assertAlmostEqual(0.02, when) - yield 0.01 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=2, loop=loop) - self.assertEqual(2, q.maxsize) - have_been_put = [] - - async def putter(): - for i in range(3): - await q.put(i) - have_been_put.append(i) - return True - - async def test(): - t = loop.create_task(putter()) - await asyncio.sleep(0.01) - - # The putter is blocked after putting two items. - self.assertEqual([0, 1], have_been_put) - self.assertEqual(0, q.get_nowait()) - - # Let the putter resume and put last item. - await asyncio.sleep(0.01) - self.assertEqual([0, 1, 2], have_been_put) - self.assertEqual(1, q.get_nowait()) - self.assertEqual(2, q.get_nowait()) - - self.assertTrue(t.done()) - self.assertTrue(t.result()) - - loop.run_until_complete(test()) - self.assertAlmostEqual(0.02, loop.time()) - - -class QueueGetTests(_QueueTestBase): - - def test_blocking_get(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - q.put_nowait(1) - - async def queue_get(): - return await q.get() - - res = self.loop.run_until_complete(queue_get()) - self.assertEqual(1, res) - - def test_get_with_putters(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(1, loop=self.loop) - q.put_nowait(1) - - waiter = self.loop.create_future() - q._putters.append(waiter) - - res = self.loop.run_until_complete(q.get()) - self.assertEqual(1, res) - self.assertTrue(waiter.done()) - self.assertIsNone(waiter.result()) - - def test_blocking_get_wait(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.01, when) - yield 0.01 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - started = asyncio.Event(loop=loop) - finished = False - - async def queue_get(): - nonlocal finished - started.set() - res = await q.get() - finished = True - return res - - async def queue_put(): - loop.call_later(0.01, q.put_nowait, 1) - queue_get_task = loop.create_task(queue_get()) - await started.wait() - self.assertFalse(finished) - res = await queue_get_task - self.assertTrue(finished) - return res - - res = loop.run_until_complete(queue_put()) - self.assertEqual(1, res) - self.assertAlmostEqual(0.01, loop.time()) - - def test_nonblocking_get(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - q.put_nowait(1) - self.assertEqual(1, q.get_nowait()) - - def test_nonblocking_get_exception(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - self.assertRaises(asyncio.QueueEmpty, q.get_nowait) - - def test_get_cancelled(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.01, when) - when = yield 0.01 - self.assertAlmostEqual(0.061, when) - yield 0.05 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - - async def queue_get(): - return await asyncio.wait_for(q.get(), 0.051) - - async def test(): - get_task = loop.create_task(queue_get()) - await asyncio.sleep(0.01) # let the task start - q.put_nowait(1) - return await get_task - - self.assertEqual(1, loop.run_until_complete(test())) - self.assertAlmostEqual(0.06, loop.time()) - - def test_get_cancelled_race(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - - t1 = self.loop.create_task(q.get()) - t2 = self.loop.create_task(q.get()) - - test_utils.run_briefly(self.loop) - t1.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(t1.done()) - q.put_nowait('a') - test_utils.run_briefly(self.loop) - self.assertEqual(t2.result(), 'a') - - def test_get_with_waiting_putters(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop, maxsize=1) - self.loop.create_task(q.put('a')) - self.loop.create_task(q.put('b')) - test_utils.run_briefly(self.loop) - self.assertEqual(self.loop.run_until_complete(q.get()), 'a') - self.assertEqual(self.loop.run_until_complete(q.get()), 'b') - - def test_why_are_getters_waiting(self): - # From issue #268. - - async def consumer(queue, num_expected): - for _ in range(num_expected): - await queue.get() - - async def producer(queue, num_items): - for i in range(num_items): - await queue.put(i) - - queue_size = 1 - producer_num_items = 5 - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(queue_size, loop=self.loop) - - self.loop.run_until_complete( - asyncio.gather(producer(q, producer_num_items), - consumer(q, producer_num_items), - loop=self.loop), - ) - - def test_cancelled_getters_not_being_held_in_self_getters(self): - def a_generator(): - yield 0.1 - yield 0.2 - - self.loop = self.new_test_loop(a_generator) - - async def consumer(queue): - try: - item = await asyncio.wait_for(queue.get(), 0.1) - except asyncio.TimeoutError: - pass - - with self.assertWarns(DeprecationWarning): - queue = asyncio.Queue(loop=self.loop, maxsize=5) - self.loop.run_until_complete(self.loop.create_task(consumer(queue))) - self.assertEqual(len(queue._getters), 0) - - -class QueuePutTests(_QueueTestBase): - - def test_blocking_put(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - - async def queue_put(): - # No maxsize, won't block. - await q.put(1) - - self.loop.run_until_complete(queue_put()) - - def test_blocking_put_wait(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.01, when) - yield 0.01 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=1, loop=loop) - started = asyncio.Event(loop=loop) - finished = False - - async def queue_put(): - nonlocal finished - started.set() - await q.put(1) - await q.put(2) - finished = True - - async def queue_get(): - loop.call_later(0.01, q.get_nowait) - queue_put_task = loop.create_task(queue_put()) - await started.wait() - self.assertFalse(finished) - await queue_put_task - self.assertTrue(finished) - - loop.run_until_complete(queue_get()) - self.assertAlmostEqual(0.01, loop.time()) - - def test_nonblocking_put(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - q.put_nowait(1) - self.assertEqual(1, q.get_nowait()) - - def test_get_cancel_drop_one_pending_reader(self): - def gen(): - yield 0.01 - yield 0.1 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - - reader = loop.create_task(q.get()) - - loop.run_until_complete(asyncio.sleep(0.01)) - - q.put_nowait(1) - q.put_nowait(2) - reader.cancel() - - try: - loop.run_until_complete(reader) - except asyncio.CancelledError: - # try again - reader = loop.create_task(q.get()) - loop.run_until_complete(reader) - - result = reader.result() - # if we get 2, it means 1 got dropped! - self.assertEqual(1, result) - - def test_get_cancel_drop_many_pending_readers(self): - def gen(): - yield 0.01 - yield 0.1 - - loop = self.new_test_loop(gen) - loop.set_debug(True) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=loop) - - reader1 = loop.create_task(q.get()) - reader2 = loop.create_task(q.get()) - reader3 = loop.create_task(q.get()) - - loop.run_until_complete(asyncio.sleep(0.01)) - - q.put_nowait(1) - q.put_nowait(2) - reader1.cancel() - - try: - loop.run_until_complete(reader1) - except asyncio.CancelledError: - pass - - loop.run_until_complete(reader3) - - # It is undefined in which order concurrent readers receive results. - self.assertEqual({reader2.result(), reader3.result()}, {1, 2}) - - def test_put_cancel_drop(self): - - def gen(): - yield 0.01 - yield 0.1 - - loop = self.new_test_loop(gen) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(1, loop=loop) - - q.put_nowait(1) - - # putting a second item in the queue has to block (qsize=1) - writer = loop.create_task(q.put(2)) - loop.run_until_complete(asyncio.sleep(0.01)) - - value1 = q.get_nowait() - self.assertEqual(value1, 1) - - writer.cancel() - try: - loop.run_until_complete(writer) - except asyncio.CancelledError: - # try again - writer = loop.create_task(q.put(2)) - loop.run_until_complete(writer) - - value2 = q.get_nowait() - self.assertEqual(value2, 2) - self.assertEqual(q.qsize(), 0) - - def test_nonblocking_put_exception(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=1, loop=self.loop) - q.put_nowait(1) - self.assertRaises(asyncio.QueueFull, q.put_nowait, 2) - - def test_float_maxsize(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=1.3, loop=self.loop) - q.put_nowait(1) - q.put_nowait(2) - self.assertTrue(q.full()) - self.assertRaises(asyncio.QueueFull, q.put_nowait, 3) - - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(maxsize=1.3, loop=self.loop) - - async def queue_put(): - await q.put(1) - await q.put(2) - self.assertTrue(q.full()) - self.loop.run_until_complete(queue_put()) - - def test_put_cancelled(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - - async def queue_put(): - await q.put(1) - return True - - async def test(): - return await q.get() - - t = self.loop.create_task(queue_put()) - self.assertEqual(1, self.loop.run_until_complete(test())) - self.assertTrue(t.done()) - self.assertTrue(t.result()) - - def test_put_cancelled_race(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop, maxsize=1) - - put_a = self.loop.create_task(q.put('a')) - put_b = self.loop.create_task(q.put('b')) - put_c = self.loop.create_task(q.put('X')) - - test_utils.run_briefly(self.loop) - self.assertTrue(put_a.done()) - self.assertFalse(put_b.done()) - - put_c.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(put_c.done()) - self.assertEqual(q.get_nowait(), 'a') - test_utils.run_briefly(self.loop) - self.assertEqual(q.get_nowait(), 'b') - - self.loop.run_until_complete(put_b) - - def test_put_with_waiting_getters(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.Queue(loop=self.loop) - t = self.loop.create_task(q.get()) - test_utils.run_briefly(self.loop) - self.loop.run_until_complete(q.put('a')) - self.assertEqual(self.loop.run_until_complete(t), 'a') - - def test_why_are_putters_waiting(self): - # From issue #265. - - with self.assertWarns(DeprecationWarning): - queue = asyncio.Queue(2, loop=self.loop) - - async def putter(item): - await queue.put(item) - - async def getter(): - await asyncio.sleep(0) - num = queue.qsize() - for _ in range(num): - item = queue.get_nowait() - - t0 = putter(0) - t1 = putter(1) - t2 = putter(2) - t3 = putter(3) - self.loop.run_until_complete( - asyncio.gather(getter(), t0, t1, t2, t3, loop=self.loop)) - - def test_cancelled_puts_not_being_held_in_self_putters(self): - def a_generator(): - yield 0.01 - yield 0.1 - - loop = self.new_test_loop(a_generator) - - # Full queue. - with self.assertWarns(DeprecationWarning): - queue = asyncio.Queue(loop=loop, maxsize=1) - queue.put_nowait(1) - - # Task waiting for space to put an item in the queue. - put_task = loop.create_task(queue.put(1)) - loop.run_until_complete(asyncio.sleep(0.01)) - - # Check that the putter is correctly removed from queue._putters when - # the task is canceled. - self.assertEqual(len(queue._putters), 1) - put_task.cancel() - with self.assertRaises(asyncio.CancelledError): - loop.run_until_complete(put_task) - self.assertEqual(len(queue._putters), 0) - - def test_cancelled_put_silence_value_error_exception(self): - def gen(): - yield 0.01 - yield 0.1 - - loop = self.new_test_loop(gen) - - # Full Queue. - with self.assertWarns(DeprecationWarning): - queue = asyncio.Queue(1, loop=loop) - queue.put_nowait(1) - - # Task waiting for space to put a item in the queue. - put_task = loop.create_task(queue.put(1)) - loop.run_until_complete(asyncio.sleep(0.01)) - - # get_nowait() remove the future of put_task from queue._putters. - queue.get_nowait() - # When canceled, queue.put is going to remove its future from - # self._putters but it was removed previously by queue.get_nowait(). - put_task.cancel() - - # The ValueError exception triggered by queue._putters.remove(putter) - # inside queue.put should be silenced. - # If the ValueError is silenced we should catch a CancelledError. - with self.assertRaises(asyncio.CancelledError): - loop.run_until_complete(put_task) - - -class LifoQueueTests(_QueueTestBase): - - def test_order(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.LifoQueue(loop=self.loop) - for i in [1, 3, 2]: - q.put_nowait(i) - - items = [q.get_nowait() for _ in range(3)] - self.assertEqual([2, 3, 1], items) - - -class PriorityQueueTests(_QueueTestBase): - - def test_order(self): - with self.assertWarns(DeprecationWarning): - q = asyncio.PriorityQueue(loop=self.loop) - for i in [1, 3, 2]: - q.put_nowait(i) - - items = [q.get_nowait() for _ in range(3)] - self.assertEqual([1, 2, 3], items) - - -class _QueueJoinTestMixin: - - q_class = None - - def test_task_done_underflow(self): - with self.assertWarns(DeprecationWarning): - q = self.q_class(loop=self.loop) - self.assertRaises(ValueError, q.task_done) - - def test_task_done(self): - with self.assertWarns(DeprecationWarning): - q = self.q_class(loop=self.loop) - for i in range(100): - q.put_nowait(i) - - accumulator = 0 - - # Two workers get items from the queue and call task_done after each. - # Join the queue and assert all items have been processed. - running = True - - async def worker(): - nonlocal accumulator - - while running: - item = await q.get() - accumulator += item - q.task_done() - - async def test(): - tasks = [self.loop.create_task(worker()) - for index in range(2)] - - await q.join() - return tasks - - tasks = self.loop.run_until_complete(test()) - self.assertEqual(sum(range(100)), accumulator) - - # close running generators - running = False - for i in range(len(tasks)): - q.put_nowait(0) - self.loop.run_until_complete(asyncio.wait(tasks)) - - def test_join_empty_queue(self): - with self.assertWarns(DeprecationWarning): - q = self.q_class(loop=self.loop) - - # Test that a queue join()s successfully, and before anything else - # (done twice for insurance). - - async def join(): - await q.join() - await q.join() - - self.loop.run_until_complete(join()) - - def test_format(self): - with self.assertWarns(DeprecationWarning): - q = self.q_class(loop=self.loop) - self.assertEqual(q._format(), 'maxsize=0') - - q._unfinished_tasks = 2 - self.assertEqual(q._format(), 'maxsize=0 tasks=2') - - -class QueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): - q_class = asyncio.Queue - - -class LifoQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): - q_class = asyncio.LifoQueue - - -class PriorityQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): - q_class = asyncio.PriorityQueue - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py deleted file mode 100644 index 3b58dde..0000000 --- a/Lib/test/test_asyncio/test_runners.py +++ /dev/null @@ -1,179 +0,0 @@ -import asyncio -import unittest - -from unittest import mock -from . import utils as test_utils - - -class TestPolicy(asyncio.AbstractEventLoopPolicy): - - def __init__(self, loop_factory): - self.loop_factory = loop_factory - self.loop = None - - def get_event_loop(self): - # shouldn't ever be called by asyncio.run() - raise RuntimeError - - def new_event_loop(self): - return self.loop_factory() - - def set_event_loop(self, loop): - if loop is not None: - # we want to check if the loop is closed - # in BaseTest.tearDown - self.loop = loop - - -class BaseTest(unittest.TestCase): - - def new_loop(self): - loop = asyncio.BaseEventLoop() - loop._process_events = mock.Mock() - loop._selector = mock.Mock() - loop._selector.select.return_value = () - loop.shutdown_ag_run = False - - async def shutdown_asyncgens(): - loop.shutdown_ag_run = True - loop.shutdown_asyncgens = shutdown_asyncgens - - return loop - - def setUp(self): - super().setUp() - - policy = TestPolicy(self.new_loop) - asyncio.set_event_loop_policy(policy) - - def tearDown(self): - policy = asyncio.get_event_loop_policy() - if policy.loop is not None: - self.assertTrue(policy.loop.is_closed()) - self.assertTrue(policy.loop.shutdown_ag_run) - - asyncio.set_event_loop_policy(None) - super().tearDown() - - -class RunTests(BaseTest): - - def test_asyncio_run_return(self): - async def main(): - await asyncio.sleep(0) - return 42 - - self.assertEqual(asyncio.run(main()), 42) - - def test_asyncio_run_raises(self): - async def main(): - await asyncio.sleep(0) - raise ValueError('spam') - - with self.assertRaisesRegex(ValueError, 'spam'): - asyncio.run(main()) - - def test_asyncio_run_only_coro(self): - for o in {1, lambda: None}: - with self.subTest(obj=o), \ - self.assertRaisesRegex(ValueError, - 'a coroutine was expected'): - asyncio.run(o) - - def test_asyncio_run_debug(self): - async def main(expected): - loop = asyncio.get_event_loop() - self.assertIs(loop.get_debug(), expected) - - asyncio.run(main(False)) - asyncio.run(main(True), debug=True) - - def test_asyncio_run_from_running_loop(self): - async def main(): - coro = main() - try: - asyncio.run(coro) - finally: - coro.close() # Suppress ResourceWarning - - with self.assertRaisesRegex(RuntimeError, - 'cannot be called from a running'): - asyncio.run(main()) - - def test_asyncio_run_cancels_hanging_tasks(self): - lo_task = None - - async def leftover(): - await asyncio.sleep(0.1) - - async def main(): - nonlocal lo_task - lo_task = asyncio.create_task(leftover()) - return 123 - - self.assertEqual(asyncio.run(main()), 123) - self.assertTrue(lo_task.done()) - - def test_asyncio_run_reports_hanging_tasks_errors(self): - lo_task = None - call_exc_handler_mock = mock.Mock() - - async def leftover(): - try: - await asyncio.sleep(0.1) - except asyncio.CancelledError: - 1 / 0 - - async def main(): - loop = asyncio.get_running_loop() - loop.call_exception_handler = call_exc_handler_mock - - nonlocal lo_task - lo_task = asyncio.create_task(leftover()) - return 123 - - self.assertEqual(asyncio.run(main()), 123) - self.assertTrue(lo_task.done()) - - call_exc_handler_mock.assert_called_with({ - 'message': test_utils.MockPattern(r'asyncio.run.*shutdown'), - 'task': lo_task, - 'exception': test_utils.MockInstanceOf(ZeroDivisionError) - }) - - def test_asyncio_run_closes_gens_after_hanging_tasks_errors(self): - spinner = None - lazyboy = None - - class FancyExit(Exception): - pass - - async def fidget(): - while True: - yield 1 - await asyncio.sleep(1) - - async def spin(): - nonlocal spinner - spinner = fidget() - try: - async for the_meaning_of_life in spinner: # NoQA - pass - except asyncio.CancelledError: - 1 / 0 - - async def main(): - loop = asyncio.get_running_loop() - loop.call_exception_handler = mock.Mock() - - nonlocal lazyboy - lazyboy = asyncio.create_task(spin()) - raise FancyExit - - with self.assertRaises(FancyExit): - asyncio.run(main()) - - self.assertTrue(lazyboy.done()) - - self.assertIsNone(spinner.ag_frame) - self.assertFalse(spinner.ag_running) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py deleted file mode 100644 index 1613c75..0000000 --- a/Lib/test/test_asyncio/test_selector_events.py +++ /dev/null @@ -1,1373 +0,0 @@ -"""Tests for selector_events.py""" - -import selectors -import socket -import unittest -from unittest import mock -try: - import ssl -except ImportError: - ssl = None - -import asyncio -from asyncio.selector_events import BaseSelectorEventLoop -from asyncio.selector_events import _SelectorTransport -from asyncio.selector_events import _SelectorSocketTransport -from asyncio.selector_events import _SelectorDatagramTransport -from test.test_asyncio import utils as test_utils - - -MOCK_ANY = mock.ANY - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class TestBaseSelectorEventLoop(BaseSelectorEventLoop): - - def _make_self_pipe(self): - self._ssock = mock.Mock() - self._csock = mock.Mock() - self._internal_fds += 1 - - def _close_self_pipe(self): - pass - - -def list_to_buffer(l=()): - return bytearray().join(l) - - -def close_transport(transport): - # Don't call transport.close() because the event loop and the selector - # are mocked - if transport._sock is None: - return - transport._sock.close() - transport._sock = None - - -class BaseSelectorEventLoopTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.selector = mock.Mock() - self.selector.select.return_value = [] - self.loop = TestBaseSelectorEventLoop(self.selector) - self.set_event_loop(self.loop) - - def test_make_socket_transport(self): - m = mock.Mock() - self.loop.add_reader = mock.Mock() - self.loop.add_reader._is_coroutine = False - transport = self.loop._make_socket_transport(m, asyncio.Protocol()) - self.assertIsInstance(transport, _SelectorSocketTransport) - - # Calling repr() must not fail when the event loop is closed - self.loop.close() - repr(transport) - - close_transport(transport) - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_make_ssl_transport(self): - m = mock.Mock() - self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False - self.loop._add_writer = mock.Mock() - self.loop._remove_reader = mock.Mock() - self.loop._remove_writer = mock.Mock() - waiter = self.loop.create_future() - with test_utils.disable_logger(): - transport = self.loop._make_ssl_transport( - m, asyncio.Protocol(), m, waiter) - - with self.assertRaisesRegex(RuntimeError, - r'SSL transport.*not.*initialized'): - transport.is_reading() - - # execute the handshake while the logger is disabled - # to ignore SSL handshake failure - test_utils.run_briefly(self.loop) - - self.assertTrue(transport.is_reading()) - transport.pause_reading() - transport.pause_reading() - self.assertFalse(transport.is_reading()) - transport.resume_reading() - transport.resume_reading() - self.assertTrue(transport.is_reading()) - - # Sanity check - class_name = transport.__class__.__name__ - self.assertIn("ssl", class_name.lower()) - self.assertIn("transport", class_name.lower()) - - transport.close() - # execute pending callbacks to close the socket transport - test_utils.run_briefly(self.loop) - - @mock.patch('asyncio.selector_events.ssl', None) - @mock.patch('asyncio.sslproto.ssl', None) - def test_make_ssl_transport_without_ssl_error(self): - m = mock.Mock() - self.loop.add_reader = mock.Mock() - self.loop.add_writer = mock.Mock() - self.loop.remove_reader = mock.Mock() - self.loop.remove_writer = mock.Mock() - with self.assertRaises(RuntimeError): - self.loop._make_ssl_transport(m, m, m, m) - - def test_close(self): - class EventLoop(BaseSelectorEventLoop): - def _make_self_pipe(self): - self._ssock = mock.Mock() - self._csock = mock.Mock() - self._internal_fds += 1 - - self.loop = EventLoop(self.selector) - self.set_event_loop(self.loop) - - ssock = self.loop._ssock - ssock.fileno.return_value = 7 - csock = self.loop._csock - csock.fileno.return_value = 1 - remove_reader = self.loop._remove_reader = mock.Mock() - - self.loop._selector.close() - self.loop._selector = selector = mock.Mock() - self.assertFalse(self.loop.is_closed()) - - self.loop.close() - self.assertTrue(self.loop.is_closed()) - self.assertIsNone(self.loop._selector) - self.assertIsNone(self.loop._csock) - self.assertIsNone(self.loop._ssock) - selector.close.assert_called_with() - ssock.close.assert_called_with() - csock.close.assert_called_with() - remove_reader.assert_called_with(7) - - # it should be possible to call close() more than once - self.loop.close() - self.loop.close() - - # operation blocked when the loop is closed - f = self.loop.create_future() - self.assertRaises(RuntimeError, self.loop.run_forever) - self.assertRaises(RuntimeError, self.loop.run_until_complete, f) - fd = 0 - def callback(): - pass - self.assertRaises(RuntimeError, self.loop.add_reader, fd, callback) - self.assertRaises(RuntimeError, self.loop.add_writer, fd, callback) - - def test_close_no_selector(self): - self.loop.remove_reader = mock.Mock() - self.loop._selector.close() - self.loop._selector = None - self.loop.close() - self.assertIsNone(self.loop._selector) - - def test_read_from_self_tryagain(self): - self.loop._ssock.recv.side_effect = BlockingIOError - self.assertIsNone(self.loop._read_from_self()) - - def test_read_from_self_exception(self): - self.loop._ssock.recv.side_effect = OSError - self.assertRaises(OSError, self.loop._read_from_self) - - def test_write_to_self_tryagain(self): - self.loop._csock.send.side_effect = BlockingIOError - with test_utils.disable_logger(): - self.assertIsNone(self.loop._write_to_self()) - - def test_write_to_self_exception(self): - # _write_to_self() swallows OSError - self.loop._csock.send.side_effect = RuntimeError() - self.assertRaises(RuntimeError, self.loop._write_to_self) - - def test_add_reader(self): - self.loop._selector.get_key.side_effect = KeyError - cb = lambda: True - self.loop.add_reader(1, cb) - - self.assertTrue(self.loop._selector.register.called) - fd, mask, (r, w) = self.loop._selector.register.call_args[0] - self.assertEqual(1, fd) - self.assertEqual(selectors.EVENT_READ, mask) - self.assertEqual(cb, r._callback) - self.assertIsNone(w) - - def test_add_reader_existing(self): - reader = mock.Mock() - writer = mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (reader, writer)) - cb = lambda: True - self.loop.add_reader(1, cb) - - self.assertTrue(reader.cancel.called) - self.assertFalse(self.loop._selector.register.called) - self.assertTrue(self.loop._selector.modify.called) - fd, mask, (r, w) = self.loop._selector.modify.call_args[0] - self.assertEqual(1, fd) - self.assertEqual(selectors.EVENT_WRITE | selectors.EVENT_READ, mask) - self.assertEqual(cb, r._callback) - self.assertEqual(writer, w) - - def test_add_reader_existing_writer(self): - writer = mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (None, writer)) - cb = lambda: True - self.loop.add_reader(1, cb) - - self.assertFalse(self.loop._selector.register.called) - self.assertTrue(self.loop._selector.modify.called) - fd, mask, (r, w) = self.loop._selector.modify.call_args[0] - self.assertEqual(1, fd) - self.assertEqual(selectors.EVENT_WRITE | selectors.EVENT_READ, mask) - self.assertEqual(cb, r._callback) - self.assertEqual(writer, w) - - def test_remove_reader(self): - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (None, None)) - self.assertFalse(self.loop.remove_reader(1)) - - self.assertTrue(self.loop._selector.unregister.called) - - def test_remove_reader_read_write(self): - reader = mock.Mock() - writer = mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, - (reader, writer)) - self.assertTrue( - self.loop.remove_reader(1)) - - self.assertFalse(self.loop._selector.unregister.called) - self.assertEqual( - (1, selectors.EVENT_WRITE, (None, writer)), - self.loop._selector.modify.call_args[0]) - - def test_remove_reader_unknown(self): - self.loop._selector.get_key.side_effect = KeyError - self.assertFalse( - self.loop.remove_reader(1)) - - def test_add_writer(self): - self.loop._selector.get_key.side_effect = KeyError - cb = lambda: True - self.loop.add_writer(1, cb) - - self.assertTrue(self.loop._selector.register.called) - fd, mask, (r, w) = self.loop._selector.register.call_args[0] - self.assertEqual(1, fd) - self.assertEqual(selectors.EVENT_WRITE, mask) - self.assertIsNone(r) - self.assertEqual(cb, w._callback) - - def test_add_writer_existing(self): - reader = mock.Mock() - writer = mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (reader, writer)) - cb = lambda: True - self.loop.add_writer(1, cb) - - self.assertTrue(writer.cancel.called) - self.assertFalse(self.loop._selector.register.called) - self.assertTrue(self.loop._selector.modify.called) - fd, mask, (r, w) = self.loop._selector.modify.call_args[0] - self.assertEqual(1, fd) - self.assertEqual(selectors.EVENT_WRITE | selectors.EVENT_READ, mask) - self.assertEqual(reader, r) - self.assertEqual(cb, w._callback) - - def test_remove_writer(self): - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (None, None)) - self.assertFalse(self.loop.remove_writer(1)) - - self.assertTrue(self.loop._selector.unregister.called) - - def test_remove_writer_read_write(self): - reader = mock.Mock() - writer = mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, - (reader, writer)) - self.assertTrue( - self.loop.remove_writer(1)) - - self.assertFalse(self.loop._selector.unregister.called) - self.assertEqual( - (1, selectors.EVENT_READ, (reader, None)), - self.loop._selector.modify.call_args[0]) - - def test_remove_writer_unknown(self): - self.loop._selector.get_key.side_effect = KeyError - self.assertFalse( - self.loop.remove_writer(1)) - - def test_process_events_read(self): - reader = mock.Mock() - reader._cancelled = False - - self.loop._add_callback = mock.Mock() - self.loop._process_events( - [(selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (reader, None)), - selectors.EVENT_READ)]) - self.assertTrue(self.loop._add_callback.called) - self.loop._add_callback.assert_called_with(reader) - - def test_process_events_read_cancelled(self): - reader = mock.Mock() - reader.cancelled = True - - self.loop._remove_reader = mock.Mock() - self.loop._process_events( - [(selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (reader, None)), - selectors.EVENT_READ)]) - self.loop._remove_reader.assert_called_with(1) - - def test_process_events_write(self): - writer = mock.Mock() - writer._cancelled = False - - self.loop._add_callback = mock.Mock() - self.loop._process_events( - [(selectors.SelectorKey(1, 1, selectors.EVENT_WRITE, - (None, writer)), - selectors.EVENT_WRITE)]) - self.loop._add_callback.assert_called_with(writer) - - def test_process_events_write_cancelled(self): - writer = mock.Mock() - writer.cancelled = True - self.loop._remove_writer = mock.Mock() - - self.loop._process_events( - [(selectors.SelectorKey(1, 1, selectors.EVENT_WRITE, - (None, writer)), - selectors.EVENT_WRITE)]) - self.loop._remove_writer.assert_called_with(1) - - def test_accept_connection_multiple(self): - sock = mock.Mock() - sock.accept.return_value = (mock.Mock(), mock.Mock()) - backlog = 100 - # Mock the coroutine generation for a connection to prevent - # warnings related to un-awaited coroutines. _accept_connection2 - # is an async function that is patched with AsyncMock. create_task - # creates a task out of coroutine returned by AsyncMock, so use - # asyncio.sleep(0) to ensure created tasks are complete to avoid - # task pending warnings. - mock_obj = mock.patch.object - with mock_obj(self.loop, '_accept_connection2') as accept2_mock: - self.loop._accept_connection( - mock.Mock(), sock, backlog=backlog) - self.loop.run_until_complete(asyncio.sleep(0)) - self.assertEqual(sock.accept.call_count, backlog) - - -class SelectorTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = mock.Mock(socket.socket) - self.sock.fileno.return_value = 7 - - def create_transport(self): - transport = _SelectorTransport(self.loop, self.sock, self.protocol, - None) - self.addCleanup(close_transport, transport) - return transport - - def test_ctor(self): - tr = self.create_transport() - self.assertIs(tr._loop, self.loop) - self.assertIs(tr._sock, self.sock) - self.assertIs(tr._sock_fd, 7) - - def test_abort(self): - tr = self.create_transport() - tr._force_close = mock.Mock() - - tr.abort() - tr._force_close.assert_called_with(None) - - def test_close(self): - tr = self.create_transport() - tr.close() - - self.assertTrue(tr.is_closing()) - self.assertEqual(1, self.loop.remove_reader_count[7]) - self.protocol.connection_lost(None) - self.assertEqual(tr._conn_lost, 1) - - tr.close() - self.assertEqual(tr._conn_lost, 1) - self.assertEqual(1, self.loop.remove_reader_count[7]) - - def test_close_write_buffer(self): - tr = self.create_transport() - tr._buffer.extend(b'data') - tr.close() - - self.assertFalse(self.loop.readers) - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.connection_lost.called) - - def test_force_close(self): - tr = self.create_transport() - tr._buffer.extend(b'1') - self.loop._add_reader(7, mock.sentinel) - self.loop._add_writer(7, mock.sentinel) - tr._force_close(None) - - self.assertTrue(tr.is_closing()) - self.assertEqual(tr._buffer, list_to_buffer()) - self.assertFalse(self.loop.readers) - self.assertFalse(self.loop.writers) - - # second close should not remove reader - tr._force_close(None) - self.assertFalse(self.loop.readers) - self.assertEqual(1, self.loop.remove_reader_count[7]) - - @mock.patch('asyncio.log.logger.error') - def test_fatal_error(self, m_exc): - exc = OSError() - tr = self.create_transport() - tr._force_close = mock.Mock() - tr._fatal_error(exc) - - m_exc.assert_not_called() - - tr._force_close.assert_called_with(exc) - - @mock.patch('asyncio.log.logger.error') - def test_fatal_error_custom_exception(self, m_exc): - class MyError(Exception): - pass - exc = MyError() - tr = self.create_transport() - tr._force_close = mock.Mock() - tr._fatal_error(exc) - - m_exc.assert_called_with( - test_utils.MockPattern( - 'Fatal error on transport\nprotocol:.*\ntransport:.*'), - exc_info=(MyError, MOCK_ANY, MOCK_ANY)) - - tr._force_close.assert_called_with(exc) - - def test_connection_lost(self): - exc = OSError() - tr = self.create_transport() - self.assertIsNotNone(tr._protocol) - self.assertIsNotNone(tr._loop) - tr._call_connection_lost(exc) - - self.protocol.connection_lost.assert_called_with(exc) - self.sock.close.assert_called_with() - self.assertIsNone(tr._sock) - - self.assertIsNone(tr._protocol) - self.assertIsNone(tr._loop) - - def test__add_reader(self): - tr = self.create_transport() - tr._buffer.extend(b'1') - tr._add_reader(7, mock.sentinel) - self.assertTrue(self.loop.readers) - - tr._force_close(None) - - self.assertTrue(tr.is_closing()) - self.assertFalse(self.loop.readers) - - # can not add readers after closing - tr._add_reader(7, mock.sentinel) - self.assertFalse(self.loop.readers) - - -class SelectorSocketTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = mock.Mock(socket.socket) - self.sock_fd = self.sock.fileno.return_value = 7 - - def socket_transport(self, waiter=None): - transport = _SelectorSocketTransport(self.loop, self.sock, - self.protocol, waiter=waiter) - self.addCleanup(close_transport, transport) - return transport - - def test_ctor(self): - waiter = self.loop.create_future() - tr = self.socket_transport(waiter=waiter) - self.loop.run_until_complete(waiter) - - self.loop.assert_reader(7, tr._read_ready) - test_utils.run_briefly(self.loop) - self.protocol.connection_made.assert_called_with(tr) - - def test_ctor_with_waiter(self): - waiter = self.loop.create_future() - self.socket_transport(waiter=waiter) - self.loop.run_until_complete(waiter) - - self.assertIsNone(waiter.result()) - - def test_pause_resume_reading(self): - tr = self.socket_transport() - test_utils.run_briefly(self.loop) - self.assertFalse(tr._paused) - self.assertTrue(tr.is_reading()) - self.loop.assert_reader(7, tr._read_ready) - - tr.pause_reading() - tr.pause_reading() - self.assertTrue(tr._paused) - self.assertFalse(tr.is_reading()) - self.loop.assert_no_reader(7) - - tr.resume_reading() - tr.resume_reading() - self.assertFalse(tr._paused) - self.assertTrue(tr.is_reading()) - self.loop.assert_reader(7, tr._read_ready) - - tr.close() - self.assertFalse(tr.is_reading()) - self.loop.assert_no_reader(7) - - def test_read_eof_received_error(self): - transport = self.socket_transport() - transport.close = mock.Mock() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - - self.protocol.eof_received.side_effect = LookupError() - - self.sock.recv.return_value = b'' - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - self.assertTrue(transport._fatal_error.called) - - def test_data_received_error(self): - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - self.protocol.data_received.side_effect = LookupError() - - self.sock.recv.return_value = b'data' - transport._read_ready() - - self.assertTrue(transport._fatal_error.called) - self.assertTrue(self.protocol.data_received.called) - - def test_read_ready(self): - transport = self.socket_transport() - - self.sock.recv.return_value = b'data' - transport._read_ready() - - self.protocol.data_received.assert_called_with(b'data') - - def test_read_ready_eof(self): - transport = self.socket_transport() - transport.close = mock.Mock() - - self.sock.recv.return_value = b'' - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - transport.close.assert_called_with() - - def test_read_ready_eof_keep_open(self): - transport = self.socket_transport() - transport.close = mock.Mock() - - self.sock.recv.return_value = b'' - self.protocol.eof_received.return_value = True - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - self.assertFalse(transport.close.called) - - @mock.patch('logging.exception') - def test_read_ready_tryagain(self, m_exc): - self.sock.recv.side_effect = BlockingIOError - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - - @mock.patch('logging.exception') - def test_read_ready_tryagain_interrupted(self, m_exc): - self.sock.recv.side_effect = InterruptedError - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - - @mock.patch('logging.exception') - def test_read_ready_conn_reset(self, m_exc): - err = self.sock.recv.side_effect = ConnectionResetError() - - transport = self.socket_transport() - transport._force_close = mock.Mock() - with test_utils.disable_logger(): - transport._read_ready() - transport._force_close.assert_called_with(err) - - @mock.patch('logging.exception') - def test_read_ready_err(self, m_exc): - err = self.sock.recv.side_effect = OSError() - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - transport._fatal_error.assert_called_with( - err, - 'Fatal read error on socket transport') - - def test_write(self): - data = b'data' - self.sock.send.return_value = len(data) - - transport = self.socket_transport() - transport.write(data) - self.sock.send.assert_called_with(data) - - def test_write_bytearray(self): - data = bytearray(b'data') - self.sock.send.return_value = len(data) - - transport = self.socket_transport() - transport.write(data) - self.sock.send.assert_called_with(data) - self.assertEqual(data, bytearray(b'data')) # Hasn't been mutated. - - def test_write_memoryview(self): - data = memoryview(b'data') - self.sock.send.return_value = len(data) - - transport = self.socket_transport() - transport.write(data) - self.sock.send.assert_called_with(data) - - def test_write_no_data(self): - transport = self.socket_transport() - transport._buffer.extend(b'data') - transport.write(b'') - self.assertFalse(self.sock.send.called) - self.assertEqual(list_to_buffer([b'data']), transport._buffer) - - def test_write_buffer(self): - transport = self.socket_transport() - transport._buffer.extend(b'data1') - transport.write(b'data2') - self.assertFalse(self.sock.send.called) - self.assertEqual(list_to_buffer([b'data1', b'data2']), - transport._buffer) - - def test_write_partial(self): - data = b'data' - self.sock.send.return_value = 2 - - transport = self.socket_transport() - transport.write(data) - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'ta']), transport._buffer) - - def test_write_partial_bytearray(self): - data = bytearray(b'data') - self.sock.send.return_value = 2 - - transport = self.socket_transport() - transport.write(data) - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'ta']), transport._buffer) - self.assertEqual(data, bytearray(b'data')) # Hasn't been mutated. - - def test_write_partial_memoryview(self): - data = memoryview(b'data') - self.sock.send.return_value = 2 - - transport = self.socket_transport() - transport.write(data) - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'ta']), transport._buffer) - - def test_write_partial_none(self): - data = b'data' - self.sock.send.return_value = 0 - self.sock.fileno.return_value = 7 - - transport = self.socket_transport() - transport.write(data) - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'data']), transport._buffer) - - def test_write_tryagain(self): - self.sock.send.side_effect = BlockingIOError - - data = b'data' - transport = self.socket_transport() - transport.write(data) - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'data']), transport._buffer) - - @mock.patch('asyncio.selector_events.logger') - def test_write_exception(self, m_log): - err = self.sock.send.side_effect = OSError() - - data = b'data' - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport.write(data) - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on socket transport') - transport._conn_lost = 1 - - self.sock.reset_mock() - transport.write(data) - self.assertFalse(self.sock.send.called) - self.assertEqual(transport._conn_lost, 2) - transport.write(data) - transport.write(data) - transport.write(data) - transport.write(data) - m_log.warning.assert_called_with('socket.send() raised exception.') - - def test_write_str(self): - transport = self.socket_transport() - self.assertRaises(TypeError, transport.write, 'str') - - def test_write_closing(self): - transport = self.socket_transport() - transport.close() - self.assertEqual(transport._conn_lost, 1) - transport.write(b'data') - self.assertEqual(transport._conn_lost, 2) - - def test_write_ready(self): - data = b'data' - self.sock.send.return_value = len(data) - - transport = self.socket_transport() - transport._buffer.extend(data) - self.loop._add_writer(7, transport._write_ready) - transport._write_ready() - self.assertTrue(self.sock.send.called) - self.assertFalse(self.loop.writers) - - def test_write_ready_closing(self): - data = b'data' - self.sock.send.return_value = len(data) - - transport = self.socket_transport() - transport._closing = True - transport._buffer.extend(data) - self.loop._add_writer(7, transport._write_ready) - transport._write_ready() - self.assertTrue(self.sock.send.called) - self.assertFalse(self.loop.writers) - self.sock.close.assert_called_with() - self.protocol.connection_lost.assert_called_with(None) - - def test_write_ready_no_data(self): - transport = self.socket_transport() - # This is an internal error. - self.assertRaises(AssertionError, transport._write_ready) - - def test_write_ready_partial(self): - data = b'data' - self.sock.send.return_value = 2 - - transport = self.socket_transport() - transport._buffer.extend(data) - self.loop._add_writer(7, transport._write_ready) - transport._write_ready() - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'ta']), transport._buffer) - - def test_write_ready_partial_none(self): - data = b'data' - self.sock.send.return_value = 0 - - transport = self.socket_transport() - transport._buffer.extend(data) - self.loop._add_writer(7, transport._write_ready) - transport._write_ready() - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'data']), transport._buffer) - - def test_write_ready_tryagain(self): - self.sock.send.side_effect = BlockingIOError - - transport = self.socket_transport() - transport._buffer = list_to_buffer([b'data1', b'data2']) - self.loop._add_writer(7, transport._write_ready) - transport._write_ready() - - self.loop.assert_writer(7, transport._write_ready) - self.assertEqual(list_to_buffer([b'data1data2']), transport._buffer) - - def test_write_ready_exception(self): - err = self.sock.send.side_effect = OSError() - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._buffer.extend(b'data') - transport._write_ready() - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on socket transport') - - def test_write_eof(self): - tr = self.socket_transport() - self.assertTrue(tr.can_write_eof()) - tr.write_eof() - self.sock.shutdown.assert_called_with(socket.SHUT_WR) - tr.write_eof() - self.assertEqual(self.sock.shutdown.call_count, 1) - tr.close() - - def test_write_eof_buffer(self): - tr = self.socket_transport() - self.sock.send.side_effect = BlockingIOError - tr.write(b'data') - tr.write_eof() - self.assertEqual(tr._buffer, list_to_buffer([b'data'])) - self.assertTrue(tr._eof) - self.assertFalse(self.sock.shutdown.called) - self.sock.send.side_effect = lambda _: 4 - tr._write_ready() - self.assertTrue(self.sock.send.called) - self.sock.shutdown.assert_called_with(socket.SHUT_WR) - tr.close() - - def test_write_eof_after_close(self): - tr = self.socket_transport() - tr.close() - self.loop.run_until_complete(asyncio.sleep(0)) - tr.write_eof() - - @mock.patch('asyncio.base_events.logger') - def test_transport_close_remove_writer(self, m_log): - remove_writer = self.loop._remove_writer = mock.Mock() - - transport = self.socket_transport() - transport.close() - remove_writer.assert_called_with(self.sock_fd) - - -class SelectorSocketTransportBufferedProtocolTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - self.protocol = test_utils.make_test_protocol(asyncio.BufferedProtocol) - self.buf = bytearray(1) - self.protocol.get_buffer.side_effect = lambda hint: self.buf - - self.sock = mock.Mock(socket.socket) - self.sock_fd = self.sock.fileno.return_value = 7 - - def socket_transport(self, waiter=None): - transport = _SelectorSocketTransport(self.loop, self.sock, - self.protocol, waiter=waiter) - self.addCleanup(close_transport, transport) - return transport - - def test_ctor(self): - waiter = self.loop.create_future() - tr = self.socket_transport(waiter=waiter) - self.loop.run_until_complete(waiter) - - self.loop.assert_reader(7, tr._read_ready) - test_utils.run_briefly(self.loop) - self.protocol.connection_made.assert_called_with(tr) - - def test_get_buffer_error(self): - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - self.protocol.get_buffer.side_effect = LookupError() - - transport._read_ready() - - self.assertTrue(transport._fatal_error.called) - self.assertTrue(self.protocol.get_buffer.called) - self.assertFalse(self.protocol.buffer_updated.called) - - def test_get_buffer_zerosized(self): - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - self.protocol.get_buffer.side_effect = lambda hint: bytearray(0) - - transport._read_ready() - - self.assertTrue(transport._fatal_error.called) - self.assertTrue(self.protocol.get_buffer.called) - self.assertFalse(self.protocol.buffer_updated.called) - - def test_proto_type_switch(self): - self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - transport = self.socket_transport() - - self.sock.recv.return_value = b'data' - transport._read_ready() - - self.protocol.data_received.assert_called_with(b'data') - - # switch protocol to a BufferedProtocol - - buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) - buf = bytearray(4) - buf_proto.get_buffer.side_effect = lambda hint: buf - - transport.set_protocol(buf_proto) - - self.sock.recv_into.return_value = 10 - transport._read_ready() - - buf_proto.get_buffer.assert_called_with(-1) - buf_proto.buffer_updated.assert_called_with(10) - - def test_buffer_updated_error(self): - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - self.protocol.buffer_updated.side_effect = LookupError() - - self.sock.recv_into.return_value = 10 - transport._read_ready() - - self.assertTrue(transport._fatal_error.called) - self.assertTrue(self.protocol.get_buffer.called) - self.assertTrue(self.protocol.buffer_updated.called) - - def test_read_eof_received_error(self): - transport = self.socket_transport() - transport.close = mock.Mock() - transport._fatal_error = mock.Mock() - - self.loop.call_exception_handler = mock.Mock() - - self.protocol.eof_received.side_effect = LookupError() - - self.sock.recv_into.return_value = 0 - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - self.assertTrue(transport._fatal_error.called) - - def test_read_ready(self): - transport = self.socket_transport() - - self.sock.recv_into.return_value = 10 - transport._read_ready() - - self.protocol.get_buffer.assert_called_with(-1) - self.protocol.buffer_updated.assert_called_with(10) - - def test_read_ready_eof(self): - transport = self.socket_transport() - transport.close = mock.Mock() - - self.sock.recv_into.return_value = 0 - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - transport.close.assert_called_with() - - def test_read_ready_eof_keep_open(self): - transport = self.socket_transport() - transport.close = mock.Mock() - - self.sock.recv_into.return_value = 0 - self.protocol.eof_received.return_value = True - transport._read_ready() - - self.protocol.eof_received.assert_called_with() - self.assertFalse(transport.close.called) - - @mock.patch('logging.exception') - def test_read_ready_tryagain(self, m_exc): - self.sock.recv_into.side_effect = BlockingIOError - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - - @mock.patch('logging.exception') - def test_read_ready_tryagain_interrupted(self, m_exc): - self.sock.recv_into.side_effect = InterruptedError - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - - @mock.patch('logging.exception') - def test_read_ready_conn_reset(self, m_exc): - err = self.sock.recv_into.side_effect = ConnectionResetError() - - transport = self.socket_transport() - transport._force_close = mock.Mock() - with test_utils.disable_logger(): - transport._read_ready() - transport._force_close.assert_called_with(err) - - @mock.patch('logging.exception') - def test_read_ready_err(self, m_exc): - err = self.sock.recv_into.side_effect = OSError() - - transport = self.socket_transport() - transport._fatal_error = mock.Mock() - transport._read_ready() - - transport._fatal_error.assert_called_with( - err, - 'Fatal read error on socket transport') - - -class SelectorDatagramTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.protocol = test_utils.make_test_protocol(asyncio.DatagramProtocol) - self.sock = mock.Mock(spec_set=socket.socket) - self.sock.fileno.return_value = 7 - - def datagram_transport(self, address=None): - self.sock.getpeername.side_effect = None if address else OSError - transport = _SelectorDatagramTransport(self.loop, self.sock, - self.protocol, - address=address) - self.addCleanup(close_transport, transport) - return transport - - def test_read_ready(self): - transport = self.datagram_transport() - - self.sock.recvfrom.return_value = (b'data', ('0.0.0.0', 1234)) - transport._read_ready() - - self.protocol.datagram_received.assert_called_with( - b'data', ('0.0.0.0', 1234)) - - def test_read_ready_tryagain(self): - transport = self.datagram_transport() - - self.sock.recvfrom.side_effect = BlockingIOError - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - - def test_read_ready_err(self): - transport = self.datagram_transport() - - err = self.sock.recvfrom.side_effect = RuntimeError() - transport._fatal_error = mock.Mock() - transport._read_ready() - - transport._fatal_error.assert_called_with( - err, - 'Fatal read error on datagram transport') - - def test_read_ready_oserr(self): - transport = self.datagram_transport() - - err = self.sock.recvfrom.side_effect = OSError() - transport._fatal_error = mock.Mock() - transport._read_ready() - - self.assertFalse(transport._fatal_error.called) - self.protocol.error_received.assert_called_with(err) - - def test_sendto(self): - data = b'data' - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.sock.sendto.called) - self.assertEqual( - self.sock.sendto.call_args[0], (data, ('0.0.0.0', 1234))) - - def test_sendto_bytearray(self): - data = bytearray(b'data') - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.sock.sendto.called) - self.assertEqual( - self.sock.sendto.call_args[0], (data, ('0.0.0.0', 1234))) - - def test_sendto_memoryview(self): - data = memoryview(b'data') - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 1234)) - self.assertTrue(self.sock.sendto.called) - self.assertEqual( - self.sock.sendto.call_args[0], (data, ('0.0.0.0', 1234))) - - def test_sendto_no_data(self): - transport = self.datagram_transport() - transport._buffer.append((b'data', ('0.0.0.0', 12345))) - transport.sendto(b'', ()) - self.assertFalse(self.sock.sendto.called) - self.assertEqual( - [(b'data', ('0.0.0.0', 12345))], list(transport._buffer)) - - def test_sendto_buffer(self): - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport.sendto(b'data2', ('0.0.0.0', 12345)) - self.assertFalse(self.sock.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - - def test_sendto_buffer_bytearray(self): - data2 = bytearray(b'data2') - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport.sendto(data2, ('0.0.0.0', 12345)) - self.assertFalse(self.sock.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - self.assertIsInstance(transport._buffer[1][0], bytes) - - def test_sendto_buffer_memoryview(self): - data2 = memoryview(b'data2') - transport = self.datagram_transport() - transport._buffer.append((b'data1', ('0.0.0.0', 12345))) - transport.sendto(data2, ('0.0.0.0', 12345)) - self.assertFalse(self.sock.sendto.called) - self.assertEqual( - [(b'data1', ('0.0.0.0', 12345)), - (b'data2', ('0.0.0.0', 12345))], - list(transport._buffer)) - self.assertIsInstance(transport._buffer[1][0], bytes) - - def test_sendto_tryagain(self): - data = b'data' - - self.sock.sendto.side_effect = BlockingIOError - - transport = self.datagram_transport() - transport.sendto(data, ('0.0.0.0', 12345)) - - self.loop.assert_writer(7, transport._sendto_ready) - self.assertEqual( - [(b'data', ('0.0.0.0', 12345))], list(transport._buffer)) - - @mock.patch('asyncio.selector_events.logger') - def test_sendto_exception(self, m_log): - data = b'data' - err = self.sock.sendto.side_effect = RuntimeError() - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport.sendto(data, ()) - - self.assertTrue(transport._fatal_error.called) - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on datagram transport') - transport._conn_lost = 1 - - transport._address = ('123',) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - transport.sendto(data) - m_log.warning.assert_called_with('socket.send() raised exception.') - - def test_sendto_error_received(self): - data = b'data' - - self.sock.sendto.side_effect = ConnectionRefusedError - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport.sendto(data, ()) - - self.assertEqual(transport._conn_lost, 0) - self.assertFalse(transport._fatal_error.called) - - def test_sendto_error_received_connected(self): - data = b'data' - - self.sock.send.side_effect = ConnectionRefusedError - - transport = self.datagram_transport(address=('0.0.0.0', 1)) - transport._fatal_error = mock.Mock() - transport.sendto(data) - - self.assertFalse(transport._fatal_error.called) - self.assertTrue(self.protocol.error_received.called) - - def test_sendto_str(self): - transport = self.datagram_transport() - self.assertRaises(TypeError, transport.sendto, 'str', ()) - - def test_sendto_connected_addr(self): - transport = self.datagram_transport(address=('0.0.0.0', 1)) - self.assertRaises( - ValueError, transport.sendto, b'str', ('0.0.0.0', 2)) - - def test_sendto_closing(self): - transport = self.datagram_transport(address=(1,)) - transport.close() - self.assertEqual(transport._conn_lost, 1) - transport.sendto(b'data', (1,)) - self.assertEqual(transport._conn_lost, 2) - - def test_sendto_ready(self): - data = b'data' - self.sock.sendto.return_value = len(data) - - transport = self.datagram_transport() - transport._buffer.append((data, ('0.0.0.0', 12345))) - self.loop._add_writer(7, transport._sendto_ready) - transport._sendto_ready() - self.assertTrue(self.sock.sendto.called) - self.assertEqual( - self.sock.sendto.call_args[0], (data, ('0.0.0.0', 12345))) - self.assertFalse(self.loop.writers) - - def test_sendto_ready_closing(self): - data = b'data' - self.sock.send.return_value = len(data) - - transport = self.datagram_transport() - transport._closing = True - transport._buffer.append((data, ())) - self.loop._add_writer(7, transport._sendto_ready) - transport._sendto_ready() - self.sock.sendto.assert_called_with(data, ()) - self.assertFalse(self.loop.writers) - self.sock.close.assert_called_with() - self.protocol.connection_lost.assert_called_with(None) - - def test_sendto_ready_no_data(self): - transport = self.datagram_transport() - self.loop._add_writer(7, transport._sendto_ready) - transport._sendto_ready() - self.assertFalse(self.sock.sendto.called) - self.assertFalse(self.loop.writers) - - def test_sendto_ready_tryagain(self): - self.sock.sendto.side_effect = BlockingIOError - - transport = self.datagram_transport() - transport._buffer.extend([(b'data1', ()), (b'data2', ())]) - self.loop._add_writer(7, transport._sendto_ready) - transport._sendto_ready() - - self.loop.assert_writer(7, transport._sendto_ready) - self.assertEqual( - [(b'data1', ()), (b'data2', ())], - list(transport._buffer)) - - def test_sendto_ready_exception(self): - err = self.sock.sendto.side_effect = RuntimeError() - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._sendto_ready() - - transport._fatal_error.assert_called_with( - err, - 'Fatal write error on datagram transport') - - def test_sendto_ready_error_received(self): - self.sock.sendto.side_effect = ConnectionRefusedError - - transport = self.datagram_transport() - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._sendto_ready() - - self.assertFalse(transport._fatal_error.called) - - def test_sendto_ready_error_received_connection(self): - self.sock.send.side_effect = ConnectionRefusedError - - transport = self.datagram_transport(address=('0.0.0.0', 1)) - transport._fatal_error = mock.Mock() - transport._buffer.append((b'data', ())) - transport._sendto_ready() - - self.assertFalse(transport._fatal_error.called) - self.assertTrue(self.protocol.error_received.called) - - @mock.patch('asyncio.base_events.logger.error') - def test_fatal_error_connected(self, m_exc): - transport = self.datagram_transport(address=('0.0.0.0', 1)) - err = ConnectionRefusedError() - transport._fatal_error(err) - self.assertFalse(self.protocol.error_received.called) - m_exc.assert_not_called() - - @mock.patch('asyncio.base_events.logger.error') - def test_fatal_error_connected_custom_error(self, m_exc): - class MyException(Exception): - pass - transport = self.datagram_transport(address=('0.0.0.0', 1)) - err = MyException() - transport._fatal_error(err) - self.assertFalse(self.protocol.error_received.called) - m_exc.assert_called_with( - test_utils.MockPattern( - 'Fatal error on transport\nprotocol:.*\ntransport:.*'), - exc_info=(MyException, MOCK_ANY, MOCK_ANY)) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py deleted file mode 100644 index 3b7f784..0000000 --- a/Lib/test/test_asyncio/test_sendfile.py +++ /dev/null @@ -1,555 +0,0 @@ -"""Tests for sendfile functionality.""" - -import asyncio -import os -import socket -import sys -import tempfile -import unittest -from asyncio import base_events -from asyncio import constants -from unittest import mock -from test import support -from test.test_asyncio import utils as test_utils - -try: - import ssl -except ImportError: - ssl = None - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class MySendfileProto(asyncio.Protocol): - - def __init__(self, loop=None, close_after=0): - self.transport = None - self.state = 'INITIAL' - self.nbytes = 0 - if loop is not None: - self.connected = loop.create_future() - self.done = loop.create_future() - self.data = bytearray() - self.close_after = close_after - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - if self.connected: - self.connected.set_result(None) - - def eof_received(self): - assert self.state == 'CONNECTED', self.state - self.state = 'EOF' - - def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - def data_received(self, data): - assert self.state == 'CONNECTED', self.state - self.nbytes += len(data) - self.data.extend(data) - super().data_received(data) - if self.close_after and self.nbytes >= self.close_after: - self.transport.close() - - -class MyProto(asyncio.Protocol): - - def __init__(self, loop): - self.started = False - self.closed = False - self.data = bytearray() - self.fut = loop.create_future() - self.transport = None - - def connection_made(self, transport): - self.started = True - self.transport = transport - - def data_received(self, data): - self.data.extend(data) - - def connection_lost(self, exc): - self.closed = True - self.fut.set_result(None) - - async def wait_closed(self): - await self.fut - - -class SendfileBase: - - # 128 KiB plus small unaligned to buffer chunk - DATA = b"SendfileBaseData" * (1024 * 8 + 1) - - # Reduce socket buffer size to test on relative small data sets. - BUF_SIZE = 4 * 1024 # 4 KiB - - def create_event_loop(self): - raise NotImplementedError - - @classmethod - def setUpClass(cls): - with open(support.TESTFN, 'wb') as fp: - fp.write(cls.DATA) - super().setUpClass() - - @classmethod - def tearDownClass(cls): - support.unlink(support.TESTFN) - super().tearDownClass() - - def setUp(self): - self.file = open(support.TESTFN, 'rb') - self.addCleanup(self.file.close) - self.loop = self.create_event_loop() - self.set_event_loop(self.loop) - super().setUp() - - def tearDown(self): - # just in case if we have transport close callbacks - if not self.loop.is_closed(): - test_utils.run_briefly(self.loop) - - self.doCleanups() - support.gc_collect() - super().tearDown() - - def run_loop(self, coro): - return self.loop.run_until_complete(coro) - - -class SockSendfileMixin(SendfileBase): - - @classmethod - def setUpClass(cls): - cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE - constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 - super().setUpClass() - - @classmethod - def tearDownClass(cls): - constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize - super().tearDownClass() - - def make_socket(self, cleanup=True): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(False) - if cleanup: - self.addCleanup(sock.close) - return sock - - def reduce_receive_buffer_size(self, sock): - # Reduce receive socket buffer size to test on relative - # small data sets. - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.BUF_SIZE) - - def reduce_send_buffer_size(self, sock, transport=None): - # Reduce send socket buffer size to test on relative small data sets. - - # On macOS, SO_SNDBUF is reset by connect(). So this method - # should be called after the socket is connected. - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.BUF_SIZE) - - if transport is not None: - transport.set_write_buffer_limits(high=self.BUF_SIZE) - - def prepare_socksendfile(self): - proto = MyProto(self.loop) - port = support.find_unused_port() - srv_sock = self.make_socket(cleanup=False) - srv_sock.bind((support.HOST, port)) - server = self.run_loop(self.loop.create_server( - lambda: proto, sock=srv_sock)) - self.reduce_receive_buffer_size(srv_sock) - - sock = self.make_socket() - self.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) - self.reduce_send_buffer_size(sock) - - def cleanup(): - if proto.transport is not None: - # can be None if the task was cancelled before - # connection_made callback - proto.transport.close() - self.run_loop(proto.wait_closed()) - - server.close() - self.run_loop(server.wait_closed()) - - self.addCleanup(cleanup) - - return sock, proto - - def test_sock_sendfile_success(self): - sock, proto = self.prepare_socksendfile() - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sock_sendfile_with_offset_and_count(self): - sock, proto = self.prepare_socksendfile() - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file, - 1000, 2000)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(proto.data, self.DATA[1000:3000]) - self.assertEqual(self.file.tell(), 3000) - self.assertEqual(ret, 2000) - - def test_sock_sendfile_zero_size(self): - sock, proto = self.prepare_socksendfile() - with tempfile.TemporaryFile() as f: - ret = self.run_loop(self.loop.sock_sendfile(sock, f, - 0, None)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, 0) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_mix_with_regular_send(self): - buf = b"mix_regular_send" * (4 * 1024) # 64 KiB - sock, proto = self.prepare_socksendfile() - self.run_loop(self.loop.sock_sendall(sock, buf)) - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) - self.run_loop(self.loop.sock_sendall(sock, buf)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, len(self.DATA)) - expected = buf + self.DATA + buf - self.assertEqual(proto.data, expected) - self.assertEqual(self.file.tell(), len(self.DATA)) - - -class SendfileMixin(SendfileBase): - - # Note: sendfile via SSL transport is equal to sendfile fallback - - def prepare_sendfile(self, *, is_ssl=False, close_after=0): - port = support.find_unused_port() - srv_proto = MySendfileProto(loop=self.loop, - close_after=close_after) - if is_ssl: - if not ssl: - self.skipTest("No ssl module") - srv_ctx = test_utils.simple_server_sslcontext() - cli_ctx = test_utils.simple_client_sslcontext() - else: - srv_ctx = None - cli_ctx = None - srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - srv_sock.bind((support.HOST, port)) - server = self.run_loop(self.loop.create_server( - lambda: srv_proto, sock=srv_sock, ssl=srv_ctx)) - self.reduce_receive_buffer_size(srv_sock) - - if is_ssl: - server_hostname = support.HOST - else: - server_hostname = None - cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - cli_sock.connect((support.HOST, port)) - - cli_proto = MySendfileProto(loop=self.loop) - tr, pr = self.run_loop(self.loop.create_connection( - lambda: cli_proto, sock=cli_sock, - ssl=cli_ctx, server_hostname=server_hostname)) - self.reduce_send_buffer_size(cli_sock, transport=tr) - - def cleanup(): - srv_proto.transport.close() - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.run_loop(cli_proto.done) - - server.close() - self.run_loop(server.wait_closed()) - - self.addCleanup(cleanup) - return srv_proto, cli_proto - - @unittest.skipIf(sys.platform == 'win32', "UDP sockets are not supported") - def test_sendfile_not_supported(self): - tr, pr = self.run_loop( - self.loop.create_datagram_endpoint( - asyncio.DatagramProtocol, - family=socket.AF_INET)) - try: - with self.assertRaisesRegex(RuntimeError, "not supported"): - self.run_loop( - self.loop.sendfile(tr, self.file)) - self.assertEqual(0, self.file.tell()) - finally: - # don't use self.addCleanup because it produces resource warning - tr.close() - - def test_sendfile(self): - srv_proto, cli_proto = self.prepare_sendfile() - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.nbytes, len(self.DATA)) - self.assertEqual(srv_proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_force_fallback(self): - srv_proto, cli_proto = self.prepare_sendfile() - - def sendfile_native(transp, file, offset, count): - # to raise SendfileNotAvailableError - return base_events.BaseEventLoop._sendfile_native( - self.loop, transp, file, offset, count) - - self.loop._sendfile_native = sendfile_native - - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.nbytes, len(self.DATA)) - self.assertEqual(srv_proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_force_unsupported_native(self): - if sys.platform == 'win32': - if isinstance(self.loop, asyncio.ProactorEventLoop): - self.skipTest("Fails on proactor event loop") - srv_proto, cli_proto = self.prepare_sendfile() - - def sendfile_native(transp, file, offset, count): - # to raise SendfileNotAvailableError - return base_events.BaseEventLoop._sendfile_native( - self.loop, transp, file, offset, count) - - self.loop._sendfile_native = sendfile_native - - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not supported"): - self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file, - fallback=False)) - - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(srv_proto.nbytes, 0) - self.assertEqual(self.file.tell(), 0) - - def test_sendfile_ssl(self): - srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.nbytes, len(self.DATA)) - self.assertEqual(srv_proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_for_closing_transp(self): - srv_proto, cli_proto = self.prepare_sendfile() - cli_proto.transport.close() - with self.assertRaisesRegex(RuntimeError, "is closing"): - self.run_loop(self.loop.sendfile(cli_proto.transport, self.file)) - self.run_loop(srv_proto.done) - self.assertEqual(srv_proto.nbytes, 0) - self.assertEqual(self.file.tell(), 0) - - def test_sendfile_pre_and_post_data(self): - srv_proto, cli_proto = self.prepare_sendfile() - PREFIX = b'PREFIX__' * 1024 # 8 KiB - SUFFIX = b'--SUFFIX' * 1024 # 8 KiB - cli_proto.transport.write(PREFIX) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.write(SUFFIX) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.data, PREFIX + self.DATA + SUFFIX) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_ssl_pre_and_post_data(self): - srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) - PREFIX = b'zxcvbnm' * 1024 - SUFFIX = b'0987654321' * 1024 - cli_proto.transport.write(PREFIX) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.write(SUFFIX) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.data, PREFIX + self.DATA + SUFFIX) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_partial(self): - srv_proto, cli_proto = self.prepare_sendfile() - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file, 1000, 100)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, 100) - self.assertEqual(srv_proto.nbytes, 100) - self.assertEqual(srv_proto.data, self.DATA[1000:1100]) - self.assertEqual(self.file.tell(), 1100) - - def test_sendfile_ssl_partial(self): - srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file, 1000, 100)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, 100) - self.assertEqual(srv_proto.nbytes, 100) - self.assertEqual(srv_proto.data, self.DATA[1000:1100]) - self.assertEqual(self.file.tell(), 1100) - - def test_sendfile_close_peer_after_receiving(self): - srv_proto, cli_proto = self.prepare_sendfile( - close_after=len(self.DATA)) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - cli_proto.transport.close() - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.nbytes, len(self.DATA)) - self.assertEqual(srv_proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_ssl_close_peer_after_receiving(self): - srv_proto, cli_proto = self.prepare_sendfile( - is_ssl=True, close_after=len(self.DATA)) - ret = self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - self.run_loop(srv_proto.done) - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(srv_proto.nbytes, len(self.DATA)) - self.assertEqual(srv_proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sendfile_close_peer_in_the_middle_of_receiving(self): - srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) - with self.assertRaises(ConnectionError): - self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - self.run_loop(srv_proto.done) - - self.assertTrue(1024 <= srv_proto.nbytes < len(self.DATA), - srv_proto.nbytes) - self.assertTrue(1024 <= self.file.tell() < len(self.DATA), - self.file.tell()) - self.assertTrue(cli_proto.transport.is_closing()) - - def test_sendfile_fallback_close_peer_in_the_middle_of_receiving(self): - - def sendfile_native(transp, file, offset, count): - # to raise SendfileNotAvailableError - return base_events.BaseEventLoop._sendfile_native( - self.loop, transp, file, offset, count) - - self.loop._sendfile_native = sendfile_native - - srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) - with self.assertRaises(ConnectionError): - self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) - self.run_loop(srv_proto.done) - - self.assertTrue(1024 <= srv_proto.nbytes < len(self.DATA), - srv_proto.nbytes) - self.assertTrue(1024 <= self.file.tell() < len(self.DATA), - self.file.tell()) - - @unittest.skipIf(not hasattr(os, 'sendfile'), - "Don't have native sendfile support") - def test_sendfile_prevents_bare_write(self): - srv_proto, cli_proto = self.prepare_sendfile() - fut = self.loop.create_future() - - async def coro(): - fut.set_result(None) - return await self.loop.sendfile(cli_proto.transport, self.file) - - t = self.loop.create_task(coro()) - self.run_loop(fut) - with self.assertRaisesRegex(RuntimeError, - "sendfile is in progress"): - cli_proto.transport.write(b'data') - ret = self.run_loop(t) - self.assertEqual(ret, len(self.DATA)) - - def test_sendfile_no_fallback_for_fallback_transport(self): - transport = mock.Mock() - transport.is_closing.side_effect = lambda: False - transport._sendfile_compatible = constants._SendfileMode.FALLBACK - with self.assertRaisesRegex(RuntimeError, 'fallback is disabled'): - self.loop.run_until_complete( - self.loop.sendfile(transport, None, fallback=False)) - - -class SendfileTestsBase(SendfileMixin, SockSendfileMixin): - pass - - -if sys.platform == 'win32': - - class SelectEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop() - - class ProactorEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.ProactorEventLoop() - -else: - import selectors - - if hasattr(selectors, 'KqueueSelector'): - class KqueueEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop( - selectors.KqueueSelector()) - - if hasattr(selectors, 'EpollSelector'): - class EPollEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.EpollSelector()) - - if hasattr(selectors, 'PollSelector'): - class PollEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.PollSelector()) - - # Should always exist. - class SelectEventLoopTests(SendfileTestsBase, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.SelectSelector()) diff --git a/Lib/test/test_asyncio/test_server.py b/Lib/test/test_asyncio/test_server.py deleted file mode 100644 index d47ccc0..0000000 --- a/Lib/test/test_asyncio/test_server.py +++ /dev/null @@ -1,133 +0,0 @@ -import asyncio -import time -import threading -import unittest - -from test import support -from test.test_asyncio import utils as test_utils -from test.test_asyncio import functional as func_tests - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class BaseStartServer(func_tests.FunctionalTestCaseMixin): - - def new_loop(self): - raise NotImplementedError - - def test_start_server_1(self): - HELLO_MSG = b'1' * 1024 * 5 + b'\n' - - def client(sock, addr): - for i in range(10): - time.sleep(0.2) - if srv.is_serving(): - break - else: - raise RuntimeError - - sock.settimeout(2) - sock.connect(addr) - sock.send(HELLO_MSG) - sock.recv_all(1) - sock.close() - - async def serve(reader, writer): - await reader.readline() - main_task.cancel() - writer.write(b'1') - writer.close() - await writer.wait_closed() - - async def main(srv): - async with srv: - await srv.serve_forever() - - with self.assertWarns(DeprecationWarning): - srv = self.loop.run_until_complete(asyncio.start_server( - serve, support.HOSTv4, 0, loop=self.loop, start_serving=False)) - - self.assertFalse(srv.is_serving()) - - main_task = self.loop.create_task(main(srv)) - - addr = srv.sockets[0].getsockname() - with self.assertRaises(asyncio.CancelledError): - with self.tcp_client(lambda sock: client(sock, addr)): - self.loop.run_until_complete(main_task) - - self.assertEqual(srv.sockets, ()) - - self.assertIsNone(srv._sockets) - self.assertIsNone(srv._waiters) - self.assertFalse(srv.is_serving()) - - with self.assertRaisesRegex(RuntimeError, r'is closed'): - self.loop.run_until_complete(srv.serve_forever()) - - -class SelectorStartServerTests(BaseStartServer, unittest.TestCase): - - def new_loop(self): - return asyncio.SelectorEventLoop() - - @support.skip_unless_bind_unix_socket - def test_start_unix_server_1(self): - HELLO_MSG = b'1' * 1024 * 5 + b'\n' - started = threading.Event() - - def client(sock, addr): - sock.settimeout(2) - started.wait(5) - sock.connect(addr) - sock.send(HELLO_MSG) - sock.recv_all(1) - sock.close() - - async def serve(reader, writer): - await reader.readline() - main_task.cancel() - writer.write(b'1') - writer.close() - await writer.wait_closed() - - async def main(srv): - async with srv: - self.assertFalse(srv.is_serving()) - await srv.start_serving() - self.assertTrue(srv.is_serving()) - started.set() - await srv.serve_forever() - - with test_utils.unix_socket_path() as addr: - with self.assertWarns(DeprecationWarning): - srv = self.loop.run_until_complete(asyncio.start_unix_server( - serve, addr, loop=self.loop, start_serving=False)) - - main_task = self.loop.create_task(main(srv)) - - with self.assertRaises(asyncio.CancelledError): - with self.unix_client(lambda sock: client(sock, addr)): - self.loop.run_until_complete(main_task) - - self.assertEqual(srv.sockets, ()) - - self.assertIsNone(srv._sockets) - self.assertIsNone(srv._waiters) - self.assertFalse(srv.is_serving()) - - with self.assertRaisesRegex(RuntimeError, r'is closed'): - self.loop.run_until_complete(srv.serve_forever()) - - -@unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') -class ProactorStartServerTests(BaseStartServer, unittest.TestCase): - - def new_loop(self): - return asyncio.ProactorEventLoop() - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py deleted file mode 100644 index 89c2af9..0000000 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ /dev/null @@ -1,343 +0,0 @@ -import socket -import asyncio -import sys -from asyncio import proactor_events -from itertools import cycle, islice -from test.test_asyncio import utils as test_utils -from test import support - - -class MyProto(asyncio.Protocol): - connected = None - done = None - - def __init__(self, loop=None): - self.transport = None - self.state = 'INITIAL' - self.nbytes = 0 - if loop is not None: - self.connected = loop.create_future() - self.done = loop.create_future() - - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - if self.connected: - self.connected.set_result(None) - transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') - - def data_received(self, data): - assert self.state == 'CONNECTED', self.state - self.nbytes += len(data) - - def eof_received(self): - assert self.state == 'CONNECTED', self.state - self.state = 'EOF' - - def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state - self.state = 'CLOSED' - if self.done: - self.done.set_result(None) - - -class BaseSockTestsMixin: - - def create_event_loop(self): - raise NotImplementedError - - def setUp(self): - self.loop = self.create_event_loop() - self.set_event_loop(self.loop) - super().setUp() - - def tearDown(self): - # just in case if we have transport close callbacks - if not self.loop.is_closed(): - test_utils.run_briefly(self.loop) - - self.doCleanups() - support.gc_collect() - super().tearDown() - - def _basetest_sock_client_ops(self, httpd, sock): - if not isinstance(self.loop, proactor_events.BaseProactorEventLoop): - # in debug mode, socket operations must fail - # if the socket is not in blocking mode - self.loop.set_debug(True) - sock.setblocking(True) - with self.assertRaises(ValueError): - self.loop.run_until_complete( - self.loop.sock_connect(sock, httpd.address)) - with self.assertRaises(ValueError): - self.loop.run_until_complete( - self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) - with self.assertRaises(ValueError): - self.loop.run_until_complete( - self.loop.sock_recv(sock, 1024)) - with self.assertRaises(ValueError): - self.loop.run_until_complete( - self.loop.sock_recv_into(sock, bytearray())) - with self.assertRaises(ValueError): - self.loop.run_until_complete( - self.loop.sock_accept(sock)) - - # test in non-blocking mode - sock.setblocking(False) - self.loop.run_until_complete( - self.loop.sock_connect(sock, httpd.address)) - self.loop.run_until_complete( - self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) - data = self.loop.run_until_complete( - self.loop.sock_recv(sock, 1024)) - # consume data - self.loop.run_until_complete( - self.loop.sock_recv(sock, 1024)) - sock.close() - self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) - - def _basetest_sock_recv_into(self, httpd, sock): - # same as _basetest_sock_client_ops, but using sock_recv_into - sock.setblocking(False) - self.loop.run_until_complete( - self.loop.sock_connect(sock, httpd.address)) - self.loop.run_until_complete( - self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) - data = bytearray(1024) - with memoryview(data) as buf: - nbytes = self.loop.run_until_complete( - self.loop.sock_recv_into(sock, buf[:1024])) - # consume data - self.loop.run_until_complete( - self.loop.sock_recv_into(sock, buf[nbytes:])) - sock.close() - self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) - - def test_sock_client_ops(self): - with test_utils.run_test_server() as httpd: - sock = socket.socket() - self._basetest_sock_client_ops(httpd, sock) - sock = socket.socket() - self._basetest_sock_recv_into(httpd, sock) - - async def _basetest_huge_content(self, address): - sock = socket.socket() - sock.setblocking(False) - DATA_SIZE = 10_000_00 - - chunk = b'0123456789' * (DATA_SIZE // 10) - - await self.loop.sock_connect(sock, address) - await self.loop.sock_sendall(sock, - (b'POST /loop HTTP/1.0\r\n' + - b'Content-Length: %d\r\n' % DATA_SIZE + - b'\r\n')) - - task = asyncio.create_task(self.loop.sock_sendall(sock, chunk)) - - data = await self.loop.sock_recv(sock, DATA_SIZE) - # HTTP headers size is less than MTU, - # they are sent by the first packet always - self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) - while data.find(b'\r\n\r\n') == -1: - data += await self.loop.sock_recv(sock, DATA_SIZE) - # Strip headers - headers = data[:data.index(b'\r\n\r\n') + 4] - data = data[len(headers):] - - size = DATA_SIZE - checker = cycle(b'0123456789') - - expected = bytes(islice(checker, len(data))) - self.assertEqual(data, expected) - size -= len(data) - - while True: - data = await self.loop.sock_recv(sock, DATA_SIZE) - if not data: - break - expected = bytes(islice(checker, len(data))) - self.assertEqual(data, expected) - size -= len(data) - self.assertEqual(size, 0) - - await task - sock.close() - - def test_huge_content(self): - with test_utils.run_test_server() as httpd: - self.loop.run_until_complete( - self._basetest_huge_content(httpd.address)) - - async def _basetest_huge_content_recvinto(self, address): - sock = socket.socket() - sock.setblocking(False) - DATA_SIZE = 10_000_00 - - chunk = b'0123456789' * (DATA_SIZE // 10) - - await self.loop.sock_connect(sock, address) - await self.loop.sock_sendall(sock, - (b'POST /loop HTTP/1.0\r\n' + - b'Content-Length: %d\r\n' % DATA_SIZE + - b'\r\n')) - - task = asyncio.create_task(self.loop.sock_sendall(sock, chunk)) - - array = bytearray(DATA_SIZE) - buf = memoryview(array) - - nbytes = await self.loop.sock_recv_into(sock, buf) - data = bytes(buf[:nbytes]) - # HTTP headers size is less than MTU, - # they are sent by the first packet always - self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) - while data.find(b'\r\n\r\n') == -1: - nbytes = await self.loop.sock_recv_into(sock, buf) - data = bytes(buf[:nbytes]) - # Strip headers - headers = data[:data.index(b'\r\n\r\n') + 4] - data = data[len(headers):] - - size = DATA_SIZE - checker = cycle(b'0123456789') - - expected = bytes(islice(checker, len(data))) - self.assertEqual(data, expected) - size -= len(data) - - while True: - nbytes = await self.loop.sock_recv_into(sock, buf) - data = buf[:nbytes] - if not data: - break - expected = bytes(islice(checker, len(data))) - self.assertEqual(data, expected) - size -= len(data) - self.assertEqual(size, 0) - - await task - sock.close() - - def test_huge_content_recvinto(self): - with test_utils.run_test_server() as httpd: - self.loop.run_until_complete( - self._basetest_huge_content_recvinto(httpd.address)) - - @support.skip_unless_bind_unix_socket - def test_unix_sock_client_ops(self): - with test_utils.run_test_unix_server() as httpd: - sock = socket.socket(socket.AF_UNIX) - self._basetest_sock_client_ops(httpd, sock) - sock = socket.socket(socket.AF_UNIX) - self._basetest_sock_recv_into(httpd, sock) - - def test_sock_client_fail(self): - # Make sure that we will get an unused port - address = None - try: - s = socket.socket() - s.bind(('127.0.0.1', 0)) - address = s.getsockname() - finally: - s.close() - - sock = socket.socket() - sock.setblocking(False) - with self.assertRaises(ConnectionRefusedError): - self.loop.run_until_complete( - self.loop.sock_connect(sock, address)) - sock.close() - - def test_sock_accept(self): - listener = socket.socket() - listener.setblocking(False) - listener.bind(('127.0.0.1', 0)) - listener.listen(1) - client = socket.socket() - client.connect(listener.getsockname()) - - f = self.loop.sock_accept(listener) - conn, addr = self.loop.run_until_complete(f) - self.assertEqual(conn.gettimeout(), 0) - self.assertEqual(addr, client.getsockname()) - self.assertEqual(client.getpeername(), listener.getsockname()) - client.close() - conn.close() - listener.close() - - def test_create_connection_sock(self): - with test_utils.run_test_server() as httpd: - sock = None - infos = self.loop.run_until_complete( - self.loop.getaddrinfo( - *httpd.address, type=socket.SOCK_STREAM)) - for family, type, proto, cname, address in infos: - try: - sock = socket.socket(family=family, type=type, proto=proto) - sock.setblocking(False) - self.loop.run_until_complete( - self.loop.sock_connect(sock, address)) - except BaseException: - pass - else: - break - else: - assert False, 'Can not create socket.' - - f = self.loop.create_connection( - lambda: MyProto(loop=self.loop), sock=sock) - tr, pr = self.loop.run_until_complete(f) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, asyncio.Protocol) - self.loop.run_until_complete(pr.done) - self.assertGreater(pr.nbytes, 0) - tr.close() - - -if sys.platform == 'win32': - - class SelectEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop() - - class ProactorEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.ProactorEventLoop() - -else: - import selectors - - if hasattr(selectors, 'KqueueSelector'): - class KqueueEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop( - selectors.KqueueSelector()) - - if hasattr(selectors, 'EpollSelector'): - class EPollEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.EpollSelector()) - - if hasattr(selectors, 'PollSelector'): - class PollEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.PollSelector()) - - # Should always exist. - class SelectEventLoopTests(BaseSockTestsMixin, - test_utils.TestCase): - - def create_event_loop(self): - return asyncio.SelectorEventLoop(selectors.SelectSelector()) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py deleted file mode 100644 index c716eac..0000000 --- a/Lib/test/test_asyncio/test_sslproto.py +++ /dev/null @@ -1,778 +0,0 @@ -"""Tests for asyncio/sslproto.py.""" - -import logging -import socket -import sys -from test import support -import unittest -import weakref -from unittest import mock -try: - import ssl -except ImportError: - ssl = None - -import asyncio -from asyncio import log -from asyncio import protocols -from asyncio import sslproto -from test import support -from test.test_asyncio import utils as test_utils -from test.test_asyncio import functional as func_tests - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -@unittest.skipIf(ssl is None, 'No ssl module') -class SslProtoHandshakeTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def ssl_protocol(self, *, waiter=None, proto=None): - sslcontext = test_utils.dummy_ssl_context() - if proto is None: # app protocol - proto = asyncio.Protocol() - ssl_proto = sslproto.SSLProtocol(self.loop, proto, sslcontext, waiter, - ssl_handshake_timeout=0.1) - self.assertIs(ssl_proto._app_transport.get_protocol(), proto) - self.addCleanup(ssl_proto._app_transport.close) - return ssl_proto - - def connection_made(self, ssl_proto, *, do_handshake=None): - transport = mock.Mock() - sslpipe = mock.Mock() - sslpipe.shutdown.return_value = b'' - if do_handshake: - sslpipe.do_handshake.side_effect = do_handshake - else: - def mock_handshake(callback): - return [] - sslpipe.do_handshake.side_effect = mock_handshake - with mock.patch('asyncio.sslproto._SSLPipe', return_value=sslpipe): - ssl_proto.connection_made(transport) - return transport - - def test_handshake_timeout_zero(self): - sslcontext = test_utils.dummy_ssl_context() - app_proto = mock.Mock() - waiter = mock.Mock() - with self.assertRaisesRegex(ValueError, 'a positive number'): - sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter, - ssl_handshake_timeout=0) - - def test_handshake_timeout_negative(self): - sslcontext = test_utils.dummy_ssl_context() - app_proto = mock.Mock() - waiter = mock.Mock() - with self.assertRaisesRegex(ValueError, 'a positive number'): - sslproto.SSLProtocol(self.loop, app_proto, sslcontext, waiter, - ssl_handshake_timeout=-10) - - def test_eof_received_waiter(self): - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - self.connection_made(ssl_proto) - ssl_proto.eof_received() - test_utils.run_briefly(self.loop) - self.assertIsInstance(waiter.exception(), ConnectionResetError) - - def test_fatal_error_no_name_error(self): - # From issue #363. - # _fatal_error() generates a NameError if sslproto.py - # does not import base_events. - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - # Temporarily turn off error logging so as not to spoil test output. - log_level = log.logger.getEffectiveLevel() - log.logger.setLevel(logging.FATAL) - try: - ssl_proto._fatal_error(None) - finally: - # Restore error logging. - log.logger.setLevel(log_level) - - def test_connection_lost(self): - # From issue #472. - # yield from waiter hang if lost_connection was called. - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - self.connection_made(ssl_proto) - ssl_proto.connection_lost(ConnectionAbortedError) - test_utils.run_briefly(self.loop) - self.assertIsInstance(waiter.exception(), ConnectionAbortedError) - - def test_close_during_handshake(self): - # bpo-29743 Closing transport during handshake process leaks socket - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - - transport = self.connection_made(ssl_proto) - test_utils.run_briefly(self.loop) - - ssl_proto._app_transport.close() - self.assertTrue(transport.abort.called) - - def test_get_extra_info_on_closed_connection(self): - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - self.assertIsNone(ssl_proto._get_extra_info('socket')) - default = object() - self.assertIs(ssl_proto._get_extra_info('socket', default), default) - self.connection_made(ssl_proto) - self.assertIsNotNone(ssl_proto._get_extra_info('socket')) - ssl_proto.connection_lost(None) - self.assertIsNone(ssl_proto._get_extra_info('socket')) - - def test_set_new_app_protocol(self): - waiter = self.loop.create_future() - ssl_proto = self.ssl_protocol(waiter=waiter) - new_app_proto = asyncio.Protocol() - ssl_proto._app_transport.set_protocol(new_app_proto) - self.assertIs(ssl_proto._app_transport.get_protocol(), new_app_proto) - self.assertIs(ssl_proto._app_protocol, new_app_proto) - - def test_data_received_after_closing(self): - ssl_proto = self.ssl_protocol() - self.connection_made(ssl_proto) - transp = ssl_proto._app_transport - - transp.close() - - # should not raise - self.assertIsNone(ssl_proto.data_received(b'data')) - - def test_write_after_closing(self): - ssl_proto = self.ssl_protocol() - self.connection_made(ssl_proto) - transp = ssl_proto._app_transport - transp.close() - - # should not raise - self.assertIsNone(transp.write(b'data')) - - -############################################################################## -# Start TLS Tests -############################################################################## - - -class BaseStartTLS(func_tests.FunctionalTestCaseMixin): - - PAYLOAD_SIZE = 1024 * 100 - TIMEOUT = support.LONG_TIMEOUT - - def new_loop(self): - raise NotImplementedError - - def test_buf_feed_data(self): - - class Proto(asyncio.BufferedProtocol): - - def __init__(self, bufsize, usemv): - self.buf = bytearray(bufsize) - self.mv = memoryview(self.buf) - self.data = b'' - self.usemv = usemv - - def get_buffer(self, sizehint): - if self.usemv: - return self.mv - else: - return self.buf - - def buffer_updated(self, nsize): - if self.usemv: - self.data += self.mv[:nsize] - else: - self.data += self.buf[:nsize] - - for usemv in [False, True]: - proto = Proto(1, usemv) - protocols._feed_data_to_buffered_proto(proto, b'12345') - self.assertEqual(proto.data, b'12345') - - proto = Proto(2, usemv) - protocols._feed_data_to_buffered_proto(proto, b'12345') - self.assertEqual(proto.data, b'12345') - - proto = Proto(2, usemv) - protocols._feed_data_to_buffered_proto(proto, b'1234') - self.assertEqual(proto.data, b'1234') - - proto = Proto(4, usemv) - protocols._feed_data_to_buffered_proto(proto, b'1234') - self.assertEqual(proto.data, b'1234') - - proto = Proto(100, usemv) - protocols._feed_data_to_buffered_proto(proto, b'12345') - self.assertEqual(proto.data, b'12345') - - proto = Proto(0, usemv) - with self.assertRaisesRegex(RuntimeError, 'empty buffer'): - protocols._feed_data_to_buffered_proto(proto, b'12345') - - def test_start_tls_client_reg_proto_1(self): - HELLO_MSG = b'1' * self.PAYLOAD_SIZE - - server_context = test_utils.simple_server_sslcontext() - client_context = test_utils.simple_client_sslcontext() - - def serve(sock): - sock.settimeout(self.TIMEOUT) - - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.start_tls(server_context, server_side=True) - - sock.sendall(b'O') - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.shutdown(socket.SHUT_RDWR) - sock.close() - - class ClientProto(asyncio.Protocol): - def __init__(self, on_data, on_eof): - self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 - - def connection_made(proto, tr): - proto.con_made_cnt += 1 - # Ensure connection_made gets called only once. - self.assertEqual(proto.con_made_cnt, 1) - - def data_received(self, data): - self.on_data.set_result(data) - - def eof_received(self): - self.on_eof.set_result(True) - - async def client(addr): - await asyncio.sleep(0.5) - - on_data = self.loop.create_future() - on_eof = self.loop.create_future() - - tr, proto = await self.loop.create_connection( - lambda: ClientProto(on_data, on_eof), *addr) - - tr.write(HELLO_MSG) - new_tr = await self.loop.start_tls(tr, proto, client_context) - - self.assertEqual(await on_data, b'O') - new_tr.write(HELLO_MSG) - await on_eof - - new_tr.close() - - with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: - self.loop.run_until_complete( - asyncio.wait_for(client(srv.addr), - timeout=support.SHORT_TIMEOUT)) - - # No garbage is left if SSL is closed uncleanly - client_context = weakref.ref(client_context) - self.assertIsNone(client_context()) - - def test_create_connection_memory_leak(self): - HELLO_MSG = b'1' * self.PAYLOAD_SIZE - - server_context = test_utils.simple_server_sslcontext() - client_context = test_utils.simple_client_sslcontext() - - def serve(sock): - sock.settimeout(self.TIMEOUT) - - sock.start_tls(server_context, server_side=True) - - sock.sendall(b'O') - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.shutdown(socket.SHUT_RDWR) - sock.close() - - class ClientProto(asyncio.Protocol): - def __init__(self, on_data, on_eof): - self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 - - def connection_made(proto, tr): - # XXX: We assume user stores the transport in protocol - proto.tr = tr - proto.con_made_cnt += 1 - # Ensure connection_made gets called only once. - self.assertEqual(proto.con_made_cnt, 1) - - def data_received(self, data): - self.on_data.set_result(data) - - def eof_received(self): - self.on_eof.set_result(True) - - async def client(addr): - await asyncio.sleep(0.5) - - on_data = self.loop.create_future() - on_eof = self.loop.create_future() - - tr, proto = await self.loop.create_connection( - lambda: ClientProto(on_data, on_eof), *addr, - ssl=client_context) - - self.assertEqual(await on_data, b'O') - tr.write(HELLO_MSG) - await on_eof - - tr.close() - - with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: - self.loop.run_until_complete( - asyncio.wait_for(client(srv.addr), - timeout=support.SHORT_TIMEOUT)) - - # No garbage is left for SSL client from loop.create_connection, even - # if user stores the SSLTransport in corresponding protocol instance - client_context = weakref.ref(client_context) - self.assertIsNone(client_context()) - - def test_start_tls_client_buf_proto_1(self): - HELLO_MSG = b'1' * self.PAYLOAD_SIZE - - server_context = test_utils.simple_server_sslcontext() - client_context = test_utils.simple_client_sslcontext() - client_con_made_calls = 0 - - def serve(sock): - sock.settimeout(self.TIMEOUT) - - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.start_tls(server_context, server_side=True) - - sock.sendall(b'O') - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.sendall(b'2') - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.shutdown(socket.SHUT_RDWR) - sock.close() - - class ClientProtoFirst(asyncio.BufferedProtocol): - def __init__(self, on_data): - self.on_data = on_data - self.buf = bytearray(1) - - def connection_made(self, tr): - nonlocal client_con_made_calls - client_con_made_calls += 1 - - def get_buffer(self, sizehint): - return self.buf - - def buffer_updated(self, nsize): - assert nsize == 1 - self.on_data.set_result(bytes(self.buf[:nsize])) - - class ClientProtoSecond(asyncio.Protocol): - def __init__(self, on_data, on_eof): - self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 - - def connection_made(self, tr): - nonlocal client_con_made_calls - client_con_made_calls += 1 - - def data_received(self, data): - self.on_data.set_result(data) - - def eof_received(self): - self.on_eof.set_result(True) - - async def client(addr): - await asyncio.sleep(0.5) - - on_data1 = self.loop.create_future() - on_data2 = self.loop.create_future() - on_eof = self.loop.create_future() - - tr, proto = await self.loop.create_connection( - lambda: ClientProtoFirst(on_data1), *addr) - - tr.write(HELLO_MSG) - new_tr = await self.loop.start_tls(tr, proto, client_context) - - self.assertEqual(await on_data1, b'O') - new_tr.write(HELLO_MSG) - - new_tr.set_protocol(ClientProtoSecond(on_data2, on_eof)) - self.assertEqual(await on_data2, b'2') - new_tr.write(HELLO_MSG) - await on_eof - - new_tr.close() - - # connection_made() should be called only once -- when - # we establish connection for the first time. Start TLS - # doesn't call connection_made() on application protocols. - self.assertEqual(client_con_made_calls, 1) - - with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: - self.loop.run_until_complete( - asyncio.wait_for(client(srv.addr), - timeout=self.TIMEOUT)) - - def test_start_tls_slow_client_cancel(self): - HELLO_MSG = b'1' * self.PAYLOAD_SIZE - - client_context = test_utils.simple_client_sslcontext() - server_waits_on_handshake = self.loop.create_future() - - def serve(sock): - sock.settimeout(self.TIMEOUT) - - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - try: - self.loop.call_soon_threadsafe( - server_waits_on_handshake.set_result, None) - data = sock.recv_all(1024 * 1024) - except ConnectionAbortedError: - pass - finally: - sock.close() - - class ClientProto(asyncio.Protocol): - def __init__(self, on_data, on_eof): - self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 - - def connection_made(proto, tr): - proto.con_made_cnt += 1 - # Ensure connection_made gets called only once. - self.assertEqual(proto.con_made_cnt, 1) - - def data_received(self, data): - self.on_data.set_result(data) - - def eof_received(self): - self.on_eof.set_result(True) - - async def client(addr): - await asyncio.sleep(0.5) - - on_data = self.loop.create_future() - on_eof = self.loop.create_future() - - tr, proto = await self.loop.create_connection( - lambda: ClientProto(on_data, on_eof), *addr) - - tr.write(HELLO_MSG) - - await server_waits_on_handshake - - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for( - self.loop.start_tls(tr, proto, client_context), - 0.5) - - with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: - self.loop.run_until_complete( - asyncio.wait_for(client(srv.addr), - timeout=support.SHORT_TIMEOUT)) - - def test_start_tls_server_1(self): - HELLO_MSG = b'1' * self.PAYLOAD_SIZE - ANSWER = b'answer' - - server_context = test_utils.simple_server_sslcontext() - client_context = test_utils.simple_client_sslcontext() - answer = None - - def client(sock, addr): - nonlocal answer - sock.settimeout(self.TIMEOUT) - - sock.connect(addr) - data = sock.recv_all(len(HELLO_MSG)) - self.assertEqual(len(data), len(HELLO_MSG)) - - sock.start_tls(client_context) - sock.sendall(HELLO_MSG) - answer = sock.recv_all(len(ANSWER)) - sock.close() - - class ServerProto(asyncio.Protocol): - def __init__(self, on_con, on_con_lost, on_got_hello): - self.on_con = on_con - self.on_con_lost = on_con_lost - self.on_got_hello = on_got_hello - self.data = b'' - self.transport = None - - def connection_made(self, tr): - self.transport = tr - self.on_con.set_result(tr) - - def replace_transport(self, tr): - self.transport = tr - - def data_received(self, data): - self.data += data - if len(self.data) >= len(HELLO_MSG): - self.on_got_hello.set_result(None) - - def connection_lost(self, exc): - self.transport = None - if exc is None: - self.on_con_lost.set_result(None) - else: - self.on_con_lost.set_exception(exc) - - async def main(proto, on_con, on_con_lost, on_got_hello): - tr = await on_con - tr.write(HELLO_MSG) - - self.assertEqual(proto.data, b'') - - new_tr = await self.loop.start_tls( - tr, proto, server_context, - server_side=True, - ssl_handshake_timeout=self.TIMEOUT) - proto.replace_transport(new_tr) - - await on_got_hello - new_tr.write(ANSWER) - - await on_con_lost - self.assertEqual(proto.data, HELLO_MSG) - new_tr.close() - - async def run_main(): - on_con = self.loop.create_future() - on_con_lost = self.loop.create_future() - on_got_hello = self.loop.create_future() - proto = ServerProto(on_con, on_con_lost, on_got_hello) - - server = await self.loop.create_server( - lambda: proto, '127.0.0.1', 0) - addr = server.sockets[0].getsockname() - - with self.tcp_client(lambda sock: client(sock, addr), - timeout=self.TIMEOUT): - await asyncio.wait_for( - main(proto, on_con, on_con_lost, on_got_hello), - timeout=self.TIMEOUT) - - server.close() - await server.wait_closed() - self.assertEqual(answer, ANSWER) - - self.loop.run_until_complete(run_main()) - - def test_start_tls_wrong_args(self): - async def main(): - with self.assertRaisesRegex(TypeError, 'SSLContext, got'): - await self.loop.start_tls(None, None, None) - - sslctx = test_utils.simple_server_sslcontext() - with self.assertRaisesRegex(TypeError, 'is not supported'): - await self.loop.start_tls(None, None, sslctx) - - self.loop.run_until_complete(main()) - - def test_handshake_timeout(self): - # bpo-29970: Check that a connection is aborted if handshake is not - # completed in timeout period, instead of remaining open indefinitely - client_sslctx = test_utils.simple_client_sslcontext() - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - server_side_aborted = False - - def server(sock): - nonlocal server_side_aborted - try: - sock.recv_all(1024 * 1024) - except ConnectionAbortedError: - server_side_aborted = True - finally: - sock.close() - - async def client(addr): - await asyncio.wait_for( - self.loop.create_connection( - asyncio.Protocol, - *addr, - ssl=client_sslctx, - server_hostname='', - ssl_handshake_timeout=support.SHORT_TIMEOUT), - 0.5) - - with self.tcp_server(server, - max_clients=1, - backlog=1) as srv: - - with self.assertRaises(asyncio.TimeoutError): - self.loop.run_until_complete(client(srv.addr)) - - self.assertTrue(server_side_aborted) - - # Python issue #23197: cancelling a handshake must not raise an - # exception or log an error, even if the handshake failed - self.assertEqual(messages, []) - - # The 10s handshake timeout should be cancelled to free related - # objects without really waiting for 10s - client_sslctx = weakref.ref(client_sslctx) - self.assertIsNone(client_sslctx()) - - def test_create_connection_ssl_slow_handshake(self): - client_sslctx = test_utils.simple_client_sslcontext() - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - def server(sock): - try: - sock.recv_all(1024 * 1024) - except ConnectionAbortedError: - pass - finally: - sock.close() - - async def client(addr): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_connection( - *addr, - ssl=client_sslctx, - server_hostname='', - loop=self.loop, - ssl_handshake_timeout=1.0) - - with self.tcp_server(server, - max_clients=1, - backlog=1) as srv: - - with self.assertRaisesRegex( - ConnectionAbortedError, - r'SSL handshake.*is taking longer'): - - self.loop.run_until_complete(client(srv.addr)) - - self.assertEqual(messages, []) - - def test_create_connection_ssl_failed_certificate(self): - self.loop.set_exception_handler(lambda loop, ctx: None) - - sslctx = test_utils.simple_server_sslcontext() - client_sslctx = test_utils.simple_client_sslcontext( - disable_verify=False) - - def server(sock): - try: - sock.start_tls( - sslctx, - server_side=True) - except ssl.SSLError: - pass - except OSError: - pass - finally: - sock.close() - - async def client(addr): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_connection( - *addr, - ssl=client_sslctx, - server_hostname='', - loop=self.loop, - ssl_handshake_timeout=support.LOOPBACK_TIMEOUT) - - with self.tcp_server(server, - max_clients=1, - backlog=1) as srv: - - with self.assertRaises(ssl.SSLCertVerificationError): - self.loop.run_until_complete(client(srv.addr)) - - def test_start_tls_client_corrupted_ssl(self): - self.loop.set_exception_handler(lambda loop, ctx: None) - - sslctx = test_utils.simple_server_sslcontext() - client_sslctx = test_utils.simple_client_sslcontext() - - def server(sock): - orig_sock = sock.dup() - try: - sock.start_tls( - sslctx, - server_side=True) - sock.sendall(b'A\n') - sock.recv_all(1) - orig_sock.send(b'please corrupt the SSL connection') - except ssl.SSLError: - pass - finally: - orig_sock.close() - sock.close() - - async def client(addr): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_connection( - *addr, - ssl=client_sslctx, - server_hostname='', - loop=self.loop) - - self.assertEqual(await reader.readline(), b'A\n') - writer.write(b'B') - with self.assertRaises(ssl.SSLError): - await reader.readline() - - writer.close() - return 'OK' - - with self.tcp_server(server, - max_clients=1, - backlog=1) as srv: - - res = self.loop.run_until_complete(client(srv.addr)) - - self.assertEqual(res, 'OK') - - -@unittest.skipIf(ssl is None, 'No ssl module') -class SelectorStartTLSTests(BaseStartTLS, unittest.TestCase): - - def new_loop(self): - return asyncio.SelectorEventLoop() - - -@unittest.skipIf(ssl is None, 'No ssl module') -@unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') -class ProactorStartTLSTests(BaseStartTLS, unittest.TestCase): - - def new_loop(self): - return asyncio.ProactorEventLoop() - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py deleted file mode 100644 index 12bd536..0000000 --- a/Lib/test/test_asyncio/test_streams.py +++ /dev/null @@ -1,992 +0,0 @@ -"""Tests for streams.py.""" - -import gc -import os -import queue -import pickle -import socket -import sys -import threading -import unittest -from unittest import mock -from test import support -try: - import ssl -except ImportError: - ssl = None - -import asyncio -from test.test_asyncio import utils as test_utils - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class StreamTests(test_utils.TestCase): - - DATA = b'line1\nline2\nline3\n' - - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def tearDown(self): - # just in case if we have transport close callbacks - test_utils.run_briefly(self.loop) - - self.loop.close() - gc.collect() - super().tearDown() - - @mock.patch('asyncio.streams.events') - def test_ctor_global_loop(self, m_events): - stream = asyncio.StreamReader() - self.assertIs(stream._loop, m_events.get_event_loop.return_value) - - def _basetest_open_connection(self, open_connection_fut): - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - with self.assertWarns(DeprecationWarning): - reader, writer = self.loop.run_until_complete(open_connection_fut) - writer.write(b'GET / HTTP/1.0\r\n\r\n') - f = reader.readline() - data = self.loop.run_until_complete(f) - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - f = reader.read() - data = self.loop.run_until_complete(f) - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - writer.close() - self.assertEqual(messages, []) - - def test_open_connection(self): - with test_utils.run_test_server() as httpd: - conn_fut = asyncio.open_connection(*httpd.address, - loop=self.loop) - self._basetest_open_connection(conn_fut) - - @support.skip_unless_bind_unix_socket - def test_open_unix_connection(self): - with test_utils.run_test_unix_server() as httpd: - conn_fut = asyncio.open_unix_connection(httpd.address, - loop=self.loop) - self._basetest_open_connection(conn_fut) - - def _basetest_open_connection_no_loop_ssl(self, open_connection_fut): - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - try: - with self.assertWarns(DeprecationWarning): - reader, writer = self.loop.run_until_complete(open_connection_fut) - finally: - asyncio.set_event_loop(None) - writer.write(b'GET / HTTP/1.0\r\n\r\n') - f = reader.read() - data = self.loop.run_until_complete(f) - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - - writer.close() - self.assertEqual(messages, []) - - @unittest.skipIf(ssl is None, 'No ssl module') - def test_open_connection_no_loop_ssl(self): - with test_utils.run_test_server(use_ssl=True) as httpd: - conn_fut = asyncio.open_connection( - *httpd.address, - ssl=test_utils.dummy_ssl_context(), - loop=self.loop) - - self._basetest_open_connection_no_loop_ssl(conn_fut) - - @support.skip_unless_bind_unix_socket - @unittest.skipIf(ssl is None, 'No ssl module') - def test_open_unix_connection_no_loop_ssl(self): - with test_utils.run_test_unix_server(use_ssl=True) as httpd: - conn_fut = asyncio.open_unix_connection( - httpd.address, - ssl=test_utils.dummy_ssl_context(), - server_hostname='', - loop=self.loop) - - self._basetest_open_connection_no_loop_ssl(conn_fut) - - def _basetest_open_connection_error(self, open_connection_fut): - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - with self.assertWarns(DeprecationWarning): - reader, writer = self.loop.run_until_complete(open_connection_fut) - writer._protocol.connection_lost(ZeroDivisionError()) - f = reader.read() - with self.assertRaises(ZeroDivisionError): - self.loop.run_until_complete(f) - writer.close() - test_utils.run_briefly(self.loop) - self.assertEqual(messages, []) - - def test_open_connection_error(self): - with test_utils.run_test_server() as httpd: - conn_fut = asyncio.open_connection(*httpd.address, - loop=self.loop) - self._basetest_open_connection_error(conn_fut) - - @support.skip_unless_bind_unix_socket - def test_open_unix_connection_error(self): - with test_utils.run_test_unix_server() as httpd: - conn_fut = asyncio.open_unix_connection(httpd.address, - loop=self.loop) - self._basetest_open_connection_error(conn_fut) - - def test_feed_empty_data(self): - stream = asyncio.StreamReader(loop=self.loop) - - stream.feed_data(b'') - self.assertEqual(b'', stream._buffer) - - def test_feed_nonempty_data(self): - stream = asyncio.StreamReader(loop=self.loop) - - stream.feed_data(self.DATA) - self.assertEqual(self.DATA, stream._buffer) - - def test_read_zero(self): - # Read zero bytes. - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(self.DATA) - - data = self.loop.run_until_complete(stream.read(0)) - self.assertEqual(b'', data) - self.assertEqual(self.DATA, stream._buffer) - - def test_read(self): - # Read bytes. - stream = asyncio.StreamReader(loop=self.loop) - read_task = self.loop.create_task(stream.read(30)) - - def cb(): - stream.feed_data(self.DATA) - self.loop.call_soon(cb) - - data = self.loop.run_until_complete(read_task) - self.assertEqual(self.DATA, data) - self.assertEqual(b'', stream._buffer) - - def test_read_line_breaks(self): - # Read bytes without line breaks. - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'line1') - stream.feed_data(b'line2') - - data = self.loop.run_until_complete(stream.read(5)) - - self.assertEqual(b'line1', data) - self.assertEqual(b'line2', stream._buffer) - - def test_read_eof(self): - # Read bytes, stop at eof. - stream = asyncio.StreamReader(loop=self.loop) - read_task = self.loop.create_task(stream.read(1024)) - - def cb(): - stream.feed_eof() - self.loop.call_soon(cb) - - data = self.loop.run_until_complete(read_task) - self.assertEqual(b'', data) - self.assertEqual(b'', stream._buffer) - - def test_read_until_eof(self): - # Read all bytes until eof. - stream = asyncio.StreamReader(loop=self.loop) - read_task = self.loop.create_task(stream.read(-1)) - - def cb(): - stream.feed_data(b'chunk1\n') - stream.feed_data(b'chunk2') - stream.feed_eof() - self.loop.call_soon(cb) - - data = self.loop.run_until_complete(read_task) - - self.assertEqual(b'chunk1\nchunk2', data) - self.assertEqual(b'', stream._buffer) - - def test_read_exception(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'line\n') - - data = self.loop.run_until_complete(stream.read(2)) - self.assertEqual(b'li', data) - - stream.set_exception(ValueError()) - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.read(2)) - - def test_invalid_limit(self): - with self.assertRaisesRegex(ValueError, 'imit'): - asyncio.StreamReader(limit=0, loop=self.loop) - - with self.assertRaisesRegex(ValueError, 'imit'): - asyncio.StreamReader(limit=-1, loop=self.loop) - - def test_read_limit(self): - stream = asyncio.StreamReader(limit=3, loop=self.loop) - stream.feed_data(b'chunk') - data = self.loop.run_until_complete(stream.read(5)) - self.assertEqual(b'chunk', data) - self.assertEqual(b'', stream._buffer) - - def test_readline(self): - # Read one line. 'readline' will need to wait for the data - # to come from 'cb' - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'chunk1 ') - read_task = self.loop.create_task(stream.readline()) - - def cb(): - stream.feed_data(b'chunk2 ') - stream.feed_data(b'chunk3 ') - stream.feed_data(b'\n chunk4') - self.loop.call_soon(cb) - - line = self.loop.run_until_complete(read_task) - self.assertEqual(b'chunk1 chunk2 chunk3 \n', line) - self.assertEqual(b' chunk4', stream._buffer) - - def test_readline_limit_with_existing_data(self): - # Read one line. The data is in StreamReader's buffer - # before the event loop is run. - - stream = asyncio.StreamReader(limit=3, loop=self.loop) - stream.feed_data(b'li') - stream.feed_data(b'ne1\nline2\n') - - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readline()) - # The buffer should contain the remaining data after exception - self.assertEqual(b'line2\n', stream._buffer) - - stream = asyncio.StreamReader(limit=3, loop=self.loop) - stream.feed_data(b'li') - stream.feed_data(b'ne1') - stream.feed_data(b'li') - - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readline()) - # No b'\n' at the end. The 'limit' is set to 3. So before - # waiting for the new data in buffer, 'readline' will consume - # the entire buffer, and since the length of the consumed data - # is more than 3, it will raise a ValueError. The buffer is - # expected to be empty now. - self.assertEqual(b'', stream._buffer) - - def test_at_eof(self): - stream = asyncio.StreamReader(loop=self.loop) - self.assertFalse(stream.at_eof()) - - stream.feed_data(b'some data\n') - self.assertFalse(stream.at_eof()) - - self.loop.run_until_complete(stream.readline()) - self.assertFalse(stream.at_eof()) - - stream.feed_data(b'some data\n') - stream.feed_eof() - self.loop.run_until_complete(stream.readline()) - self.assertTrue(stream.at_eof()) - - def test_readline_limit(self): - # Read one line. StreamReaders are fed with data after - # their 'readline' methods are called. - - stream = asyncio.StreamReader(limit=7, loop=self.loop) - def cb(): - stream.feed_data(b'chunk1') - stream.feed_data(b'chunk2') - stream.feed_data(b'chunk3\n') - stream.feed_eof() - self.loop.call_soon(cb) - - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readline()) - # The buffer had just one line of data, and after raising - # a ValueError it should be empty. - self.assertEqual(b'', stream._buffer) - - stream = asyncio.StreamReader(limit=7, loop=self.loop) - def cb(): - stream.feed_data(b'chunk1') - stream.feed_data(b'chunk2\n') - stream.feed_data(b'chunk3\n') - stream.feed_eof() - self.loop.call_soon(cb) - - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readline()) - self.assertEqual(b'chunk3\n', stream._buffer) - - # check strictness of the limit - stream = asyncio.StreamReader(limit=7, loop=self.loop) - stream.feed_data(b'1234567\n') - line = self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'1234567\n', line) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'12345678\n') - with self.assertRaises(ValueError) as cm: - self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'12345678') - with self.assertRaises(ValueError) as cm: - self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'', stream._buffer) - - def test_readline_nolimit_nowait(self): - # All needed data for the first 'readline' call will be - # in the buffer. - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(self.DATA[:6]) - stream.feed_data(self.DATA[6:]) - - line = self.loop.run_until_complete(stream.readline()) - - self.assertEqual(b'line1\n', line) - self.assertEqual(b'line2\nline3\n', stream._buffer) - - def test_readline_eof(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'some data') - stream.feed_eof() - - line = self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'some data', line) - - def test_readline_empty_eof(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_eof() - - line = self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'', line) - - def test_readline_read_byte_count(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(self.DATA) - - self.loop.run_until_complete(stream.readline()) - - data = self.loop.run_until_complete(stream.read(7)) - - self.assertEqual(b'line2\nl', data) - self.assertEqual(b'ine3\n', stream._buffer) - - def test_readline_exception(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'line\n') - - data = self.loop.run_until_complete(stream.readline()) - self.assertEqual(b'line\n', data) - - stream.set_exception(ValueError()) - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readline()) - self.assertEqual(b'', stream._buffer) - - def test_readuntil_separator(self): - stream = asyncio.StreamReader(loop=self.loop) - with self.assertRaisesRegex(ValueError, 'Separator should be'): - self.loop.run_until_complete(stream.readuntil(separator=b'')) - - def test_readuntil_multi_chunks(self): - stream = asyncio.StreamReader(loop=self.loop) - - stream.feed_data(b'lineAAA') - data = self.loop.run_until_complete(stream.readuntil(separator=b'AAA')) - self.assertEqual(b'lineAAA', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'lineAAA') - data = self.loop.run_until_complete(stream.readuntil(b'AAA')) - self.assertEqual(b'lineAAA', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'lineAAAxxx') - data = self.loop.run_until_complete(stream.readuntil(b'AAA')) - self.assertEqual(b'lineAAA', data) - self.assertEqual(b'xxx', stream._buffer) - - def test_readuntil_multi_chunks_1(self): - stream = asyncio.StreamReader(loop=self.loop) - - stream.feed_data(b'QWEaa') - stream.feed_data(b'XYaa') - stream.feed_data(b'a') - data = self.loop.run_until_complete(stream.readuntil(b'aaa')) - self.assertEqual(b'QWEaaXYaaa', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'QWEaa') - stream.feed_data(b'XYa') - stream.feed_data(b'aa') - data = self.loop.run_until_complete(stream.readuntil(b'aaa')) - self.assertEqual(b'QWEaaXYaaa', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'aaa') - data = self.loop.run_until_complete(stream.readuntil(b'aaa')) - self.assertEqual(b'aaa', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'Xaaa') - data = self.loop.run_until_complete(stream.readuntil(b'aaa')) - self.assertEqual(b'Xaaa', data) - self.assertEqual(b'', stream._buffer) - - stream.feed_data(b'XXX') - stream.feed_data(b'a') - stream.feed_data(b'a') - stream.feed_data(b'a') - data = self.loop.run_until_complete(stream.readuntil(b'aaa')) - self.assertEqual(b'XXXaaa', data) - self.assertEqual(b'', stream._buffer) - - def test_readuntil_eof(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'some dataAA') - stream.feed_eof() - - with self.assertRaises(asyncio.IncompleteReadError) as cm: - self.loop.run_until_complete(stream.readuntil(b'AAA')) - self.assertEqual(cm.exception.partial, b'some dataAA') - self.assertIsNone(cm.exception.expected) - self.assertEqual(b'', stream._buffer) - - def test_readuntil_limit_found_sep(self): - stream = asyncio.StreamReader(loop=self.loop, limit=3) - stream.feed_data(b'some dataAA') - with self.assertRaisesRegex(asyncio.LimitOverrunError, - 'not found') as cm: - self.loop.run_until_complete(stream.readuntil(b'AAA')) - - self.assertEqual(b'some dataAA', stream._buffer) - - stream.feed_data(b'A') - with self.assertRaisesRegex(asyncio.LimitOverrunError, - 'is found') as cm: - self.loop.run_until_complete(stream.readuntil(b'AAA')) - - self.assertEqual(b'some dataAAA', stream._buffer) - - def test_readexactly_zero_or_less(self): - # Read exact number of bytes (zero or less). - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(self.DATA) - - data = self.loop.run_until_complete(stream.readexactly(0)) - self.assertEqual(b'', data) - self.assertEqual(self.DATA, stream._buffer) - - with self.assertRaisesRegex(ValueError, 'less than zero'): - self.loop.run_until_complete(stream.readexactly(-1)) - self.assertEqual(self.DATA, stream._buffer) - - def test_readexactly(self): - # Read exact number of bytes. - stream = asyncio.StreamReader(loop=self.loop) - - n = 2 * len(self.DATA) - read_task = self.loop.create_task(stream.readexactly(n)) - - def cb(): - stream.feed_data(self.DATA) - stream.feed_data(self.DATA) - stream.feed_data(self.DATA) - self.loop.call_soon(cb) - - data = self.loop.run_until_complete(read_task) - self.assertEqual(self.DATA + self.DATA, data) - self.assertEqual(self.DATA, stream._buffer) - - def test_readexactly_limit(self): - stream = asyncio.StreamReader(limit=3, loop=self.loop) - stream.feed_data(b'chunk') - data = self.loop.run_until_complete(stream.readexactly(5)) - self.assertEqual(b'chunk', data) - self.assertEqual(b'', stream._buffer) - - def test_readexactly_eof(self): - # Read exact number of bytes (eof). - stream = asyncio.StreamReader(loop=self.loop) - n = 2 * len(self.DATA) - read_task = self.loop.create_task(stream.readexactly(n)) - - def cb(): - stream.feed_data(self.DATA) - stream.feed_eof() - self.loop.call_soon(cb) - - with self.assertRaises(asyncio.IncompleteReadError) as cm: - self.loop.run_until_complete(read_task) - self.assertEqual(cm.exception.partial, self.DATA) - self.assertEqual(cm.exception.expected, n) - self.assertEqual(str(cm.exception), - '18 bytes read on a total of 36 expected bytes') - self.assertEqual(b'', stream._buffer) - - def test_readexactly_exception(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'line\n') - - data = self.loop.run_until_complete(stream.readexactly(2)) - self.assertEqual(b'li', data) - - stream.set_exception(ValueError()) - self.assertRaises( - ValueError, self.loop.run_until_complete, stream.readexactly(2)) - - def test_exception(self): - stream = asyncio.StreamReader(loop=self.loop) - self.assertIsNone(stream.exception()) - - exc = ValueError() - stream.set_exception(exc) - self.assertIs(stream.exception(), exc) - - def test_exception_waiter(self): - stream = asyncio.StreamReader(loop=self.loop) - - async def set_err(): - stream.set_exception(ValueError()) - - t1 = self.loop.create_task(stream.readline()) - t2 = self.loop.create_task(set_err()) - - self.loop.run_until_complete(asyncio.wait([t1, t2])) - - self.assertRaises(ValueError, t1.result) - - def test_exception_cancel(self): - stream = asyncio.StreamReader(loop=self.loop) - - t = self.loop.create_task(stream.readline()) - test_utils.run_briefly(self.loop) - t.cancel() - test_utils.run_briefly(self.loop) - # The following line fails if set_exception() isn't careful. - stream.set_exception(RuntimeError('message')) - test_utils.run_briefly(self.loop) - self.assertIs(stream._waiter, None) - - def test_start_server(self): - - class MyServer: - - def __init__(self, loop): - self.server = None - self.loop = loop - - async def handle_client(self, client_reader, client_writer): - data = await client_reader.readline() - client_writer.write(data) - await client_writer.drain() - client_writer.close() - await client_writer.wait_closed() - - def start(self): - sock = socket.create_server(('127.0.0.1', 0)) - self.server = self.loop.run_until_complete( - asyncio.start_server(self.handle_client, - sock=sock, - loop=self.loop)) - return sock.getsockname() - - def handle_client_callback(self, client_reader, client_writer): - self.loop.create_task(self.handle_client(client_reader, - client_writer)) - - def start_callback(self): - sock = socket.create_server(('127.0.0.1', 0)) - addr = sock.getsockname() - sock.close() - self.server = self.loop.run_until_complete( - asyncio.start_server(self.handle_client_callback, - host=addr[0], port=addr[1], - loop=self.loop)) - return addr - - def stop(self): - if self.server is not None: - self.server.close() - self.loop.run_until_complete(self.server.wait_closed()) - self.server = None - - async def client(addr): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_connection( - *addr, loop=self.loop) - # send a line - writer.write(b"hello world!\n") - # read it back - msgback = await reader.readline() - writer.close() - await writer.wait_closed() - return msgback - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - # test the server variant with a coroutine as client handler - server = MyServer(self.loop) - with self.assertWarns(DeprecationWarning): - addr = server.start() - msg = self.loop.run_until_complete(self.loop.create_task(client(addr))) - server.stop() - self.assertEqual(msg, b"hello world!\n") - - # test the server variant with a callback as client handler - server = MyServer(self.loop) - with self.assertWarns(DeprecationWarning): - addr = server.start_callback() - msg = self.loop.run_until_complete(self.loop.create_task(client(addr))) - server.stop() - self.assertEqual(msg, b"hello world!\n") - - self.assertEqual(messages, []) - - @support.skip_unless_bind_unix_socket - def test_start_unix_server(self): - - class MyServer: - - def __init__(self, loop, path): - self.server = None - self.loop = loop - self.path = path - - async def handle_client(self, client_reader, client_writer): - data = await client_reader.readline() - client_writer.write(data) - await client_writer.drain() - client_writer.close() - await client_writer.wait_closed() - - def start(self): - self.server = self.loop.run_until_complete( - asyncio.start_unix_server(self.handle_client, - path=self.path, - loop=self.loop)) - - def handle_client_callback(self, client_reader, client_writer): - self.loop.create_task(self.handle_client(client_reader, - client_writer)) - - def start_callback(self): - start = asyncio.start_unix_server(self.handle_client_callback, - path=self.path, - loop=self.loop) - self.server = self.loop.run_until_complete(start) - - def stop(self): - if self.server is not None: - self.server.close() - self.loop.run_until_complete(self.server.wait_closed()) - self.server = None - - async def client(path): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_unix_connection( - path, loop=self.loop) - # send a line - writer.write(b"hello world!\n") - # read it back - msgback = await reader.readline() - writer.close() - await writer.wait_closed() - return msgback - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - # test the server variant with a coroutine as client handler - with test_utils.unix_socket_path() as path: - server = MyServer(self.loop, path) - with self.assertWarns(DeprecationWarning): - server.start() - msg = self.loop.run_until_complete( - self.loop.create_task(client(path))) - server.stop() - self.assertEqual(msg, b"hello world!\n") - - # test the server variant with a callback as client handler - with test_utils.unix_socket_path() as path: - server = MyServer(self.loop, path) - with self.assertWarns(DeprecationWarning): - server.start_callback() - msg = self.loop.run_until_complete( - self.loop.create_task(client(path))) - server.stop() - self.assertEqual(msg, b"hello world!\n") - - self.assertEqual(messages, []) - - @unittest.skipIf(sys.platform == 'win32', "Don't have pipes") - def test_read_all_from_pipe_reader(self): - # See asyncio issue 168. This test is derived from the example - # subprocess_attach_read_pipe.py, but we configure the - # StreamReader's limit so that twice it is less than the size - # of the data writter. Also we must explicitly attach a child - # watcher to the event loop. - - code = """\ -import os, sys -fd = int(sys.argv[1]) -os.write(fd, b'data') -os.close(fd) -""" - rfd, wfd = os.pipe() - args = [sys.executable, '-c', code, str(wfd)] - - pipe = open(rfd, 'rb', 0) - reader = asyncio.StreamReader(loop=self.loop, limit=1) - protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop) - transport, _ = self.loop.run_until_complete( - self.loop.connect_read_pipe(lambda: protocol, pipe)) - - watcher = asyncio.SafeChildWatcher() - watcher.attach_loop(self.loop) - try: - asyncio.set_child_watcher(watcher) - create = asyncio.create_subprocess_exec( - *args, - pass_fds={wfd}, - ) - proc = self.loop.run_until_complete(create) - self.loop.run_until_complete(proc.wait()) - finally: - asyncio.set_child_watcher(None) - - os.close(wfd) - data = self.loop.run_until_complete(reader.read(-1)) - self.assertEqual(data, b'data') - - def test_streamreader_constructor(self): - self.addCleanup(asyncio.set_event_loop, None) - asyncio.set_event_loop(self.loop) - - # asyncio issue #184: Ensure that StreamReaderProtocol constructor - # retrieves the current loop if the loop parameter is not set - reader = asyncio.StreamReader() - self.assertIs(reader._loop, self.loop) - - def test_streamreaderprotocol_constructor(self): - self.addCleanup(asyncio.set_event_loop, None) - asyncio.set_event_loop(self.loop) - - # asyncio issue #184: Ensure that StreamReaderProtocol constructor - # retrieves the current loop if the loop parameter is not set - reader = mock.Mock() - protocol = asyncio.StreamReaderProtocol(reader) - self.assertIs(protocol._loop, self.loop) - - def test_drain_raises(self): - # See http://bugs.python.org/issue25441 - - # This test should not use asyncio for the mock server; the - # whole point of the test is to test for a bug in drain() - # where it never gives up the event loop but the socket is - # closed on the server side. - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - q = queue.Queue() - - def server(): - # Runs in a separate thread. - with socket.create_server(('localhost', 0)) as sock: - addr = sock.getsockname() - q.put(addr) - clt, _ = sock.accept() - clt.close() - - async def client(host, port): - with self.assertWarns(DeprecationWarning): - reader, writer = await asyncio.open_connection( - host, port, loop=self.loop) - - while True: - writer.write(b"foo\n") - await writer.drain() - - # Start the server thread and wait for it to be listening. - thread = threading.Thread(target=server) - thread.setDaemon(True) - thread.start() - addr = q.get() - - # Should not be stuck in an infinite loop. - with self.assertRaises((ConnectionResetError, ConnectionAbortedError, - BrokenPipeError)): - self.loop.run_until_complete(client(*addr)) - - # Clean up the thread. (Only on success; on failure, it may - # be stuck in accept().) - thread.join() - self.assertEqual([], messages) - - def test___repr__(self): - stream = asyncio.StreamReader(loop=self.loop) - self.assertEqual("<StreamReader>", repr(stream)) - - def test___repr__nondefault_limit(self): - stream = asyncio.StreamReader(loop=self.loop, limit=123) - self.assertEqual("<StreamReader limit=123>", repr(stream)) - - def test___repr__eof(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_eof() - self.assertEqual("<StreamReader eof>", repr(stream)) - - def test___repr__data(self): - stream = asyncio.StreamReader(loop=self.loop) - stream.feed_data(b'data') - self.assertEqual("<StreamReader 4 bytes>", repr(stream)) - - def test___repr__exception(self): - stream = asyncio.StreamReader(loop=self.loop) - exc = RuntimeError() - stream.set_exception(exc) - self.assertEqual("<StreamReader exception=RuntimeError()>", - repr(stream)) - - def test___repr__waiter(self): - stream = asyncio.StreamReader(loop=self.loop) - stream._waiter = asyncio.Future(loop=self.loop) - self.assertRegex( - repr(stream), - r"<StreamReader waiter=<Future pending[\S ]*>>") - stream._waiter.set_result(None) - self.loop.run_until_complete(stream._waiter) - stream._waiter = None - self.assertEqual("<StreamReader>", repr(stream)) - - def test___repr__transport(self): - stream = asyncio.StreamReader(loop=self.loop) - stream._transport = mock.Mock() - stream._transport.__repr__ = mock.Mock() - stream._transport.__repr__.return_value = "<Transport>" - self.assertEqual("<StreamReader transport=<Transport>>", repr(stream)) - - def test_IncompleteReadError_pickleable(self): - e = asyncio.IncompleteReadError(b'abc', 10) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(pickle_protocol=proto): - e2 = pickle.loads(pickle.dumps(e, protocol=proto)) - self.assertEqual(str(e), str(e2)) - self.assertEqual(e.partial, e2.partial) - self.assertEqual(e.expected, e2.expected) - - def test_LimitOverrunError_pickleable(self): - e = asyncio.LimitOverrunError('message', 10) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(pickle_protocol=proto): - e2 = pickle.loads(pickle.dumps(e, protocol=proto)) - self.assertEqual(str(e), str(e2)) - self.assertEqual(e.consumed, e2.consumed) - - def test_wait_closed_on_close(self): - with test_utils.run_test_server() as httpd: - with self.assertWarns(DeprecationWarning): - rd, wr = self.loop.run_until_complete( - asyncio.open_connection(*httpd.address, loop=self.loop)) - - wr.write(b'GET / HTTP/1.0\r\n\r\n') - f = rd.readline() - data = self.loop.run_until_complete(f) - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - f = rd.read() - data = self.loop.run_until_complete(f) - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - self.assertFalse(wr.is_closing()) - wr.close() - self.assertTrue(wr.is_closing()) - self.loop.run_until_complete(wr.wait_closed()) - - def test_wait_closed_on_close_with_unread_data(self): - with test_utils.run_test_server() as httpd: - with self.assertWarns(DeprecationWarning): - rd, wr = self.loop.run_until_complete( - asyncio.open_connection(*httpd.address, loop=self.loop)) - - wr.write(b'GET / HTTP/1.0\r\n\r\n') - f = rd.readline() - data = self.loop.run_until_complete(f) - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - wr.close() - self.loop.run_until_complete(wr.wait_closed()) - - def test_async_writer_api(self): - async def inner(httpd): - rd, wr = await asyncio.open_connection(*httpd.address) - - wr.write(b'GET / HTTP/1.0\r\n\r\n') - data = await rd.readline() - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - data = await rd.read() - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - wr.close() - await wr.wait_closed() - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - with test_utils.run_test_server() as httpd: - self.loop.run_until_complete(inner(httpd)) - - self.assertEqual(messages, []) - - def test_async_writer_api_exception_after_close(self): - async def inner(httpd): - rd, wr = await asyncio.open_connection(*httpd.address) - - wr.write(b'GET / HTTP/1.0\r\n\r\n') - data = await rd.readline() - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - data = await rd.read() - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) - wr.close() - with self.assertRaises(ConnectionResetError): - wr.write(b'data') - await wr.drain() - - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - with test_utils.run_test_server() as httpd: - self.loop.run_until_complete(inner(httpd)) - - self.assertEqual(messages, []) - - def test_eof_feed_when_closing_writer(self): - # See http://bugs.python.org/issue35065 - messages = [] - self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) - - with test_utils.run_test_server() as httpd: - with self.assertWarns(DeprecationWarning): - rd, wr = self.loop.run_until_complete( - asyncio.open_connection(*httpd.address, - loop=self.loop)) - - wr.close() - f = wr.wait_closed() - self.loop.run_until_complete(f) - assert rd.at_eof() - f = rd.read() - data = self.loop.run_until_complete(f) - assert data == b'' - - self.assertEqual(messages, []) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py deleted file mode 100644 index a6c3acc..0000000 --- a/Lib/test/test_asyncio/test_subprocess.py +++ /dev/null @@ -1,743 +0,0 @@ -import os -import signal -import sys -import unittest -import warnings -from unittest import mock - -import asyncio -from asyncio import base_subprocess -from asyncio import subprocess -from test.test_asyncio import utils as test_utils -from test import support - -if sys.platform != 'win32': - from asyncio import unix_events - -# Program blocking -PROGRAM_BLOCKED = [sys.executable, '-c', 'import time; time.sleep(3600)'] - -# Program copying input to output -PROGRAM_CAT = [ - sys.executable, '-c', - ';'.join(('import sys', - 'data = sys.stdin.buffer.read()', - 'sys.stdout.buffer.write(data)'))] - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class TestSubprocessTransport(base_subprocess.BaseSubprocessTransport): - def _start(self, *args, **kwargs): - self._proc = mock.Mock() - self._proc.stdin = None - self._proc.stdout = None - self._proc.stderr = None - self._proc.pid = -1 - - -class SubprocessTransportTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.set_event_loop(self.loop) - - def create_transport(self, waiter=None): - protocol = mock.Mock() - protocol.connection_made._is_coroutine = False - protocol.process_exited._is_coroutine = False - transport = TestSubprocessTransport( - self.loop, protocol, ['test'], False, - None, None, None, 0, waiter=waiter) - return (transport, protocol) - - def test_proc_exited(self): - waiter = self.loop.create_future() - transport, protocol = self.create_transport(waiter) - transport._process_exited(6) - self.loop.run_until_complete(waiter) - - self.assertEqual(transport.get_returncode(), 6) - - self.assertTrue(protocol.connection_made.called) - self.assertTrue(protocol.process_exited.called) - self.assertTrue(protocol.connection_lost.called) - self.assertEqual(protocol.connection_lost.call_args[0], (None,)) - - self.assertFalse(transport.is_closing()) - self.assertIsNone(transport._loop) - self.assertIsNone(transport._proc) - self.assertIsNone(transport._protocol) - - # methods must raise ProcessLookupError if the process exited - self.assertRaises(ProcessLookupError, - transport.send_signal, signal.SIGTERM) - self.assertRaises(ProcessLookupError, transport.terminate) - self.assertRaises(ProcessLookupError, transport.kill) - - transport.close() - - def test_subprocess_repr(self): - waiter = self.loop.create_future() - transport, protocol = self.create_transport(waiter) - transport._process_exited(6) - self.loop.run_until_complete(waiter) - - self.assertEqual( - repr(transport), - "<TestSubprocessTransport pid=-1 returncode=6>" - ) - transport._returncode = None - self.assertEqual( - repr(transport), - "<TestSubprocessTransport pid=-1 running>" - ) - transport._pid = None - transport._returncode = None - self.assertEqual( - repr(transport), - "<TestSubprocessTransport not started>" - ) - transport.close() - - -class SubprocessMixin: - - def test_stdin_stdout(self): - args = PROGRAM_CAT - - async def run(data): - proc = await asyncio.create_subprocess_exec( - *args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - - # feed data - proc.stdin.write(data) - await proc.stdin.drain() - proc.stdin.close() - - # get output and exitcode - data = await proc.stdout.read() - exitcode = await proc.wait() - return (exitcode, data) - - task = run(b'some data') - task = asyncio.wait_for(task, 60.0) - exitcode, stdout = self.loop.run_until_complete(task) - self.assertEqual(exitcode, 0) - self.assertEqual(stdout, b'some data') - - def test_communicate(self): - args = PROGRAM_CAT - - async def run(data): - proc = await asyncio.create_subprocess_exec( - *args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - stdout, stderr = await proc.communicate(data) - return proc.returncode, stdout - - task = run(b'some data') - task = asyncio.wait_for(task, support.LONG_TIMEOUT) - exitcode, stdout = self.loop.run_until_complete(task) - self.assertEqual(exitcode, 0) - self.assertEqual(stdout, b'some data') - - def test_shell(self): - proc = self.loop.run_until_complete( - asyncio.create_subprocess_shell('exit 7') - ) - exitcode = self.loop.run_until_complete(proc.wait()) - self.assertEqual(exitcode, 7) - - def test_start_new_session(self): - # start the new process in a new session - proc = self.loop.run_until_complete( - asyncio.create_subprocess_shell( - 'exit 8', - start_new_session=True, - ) - ) - exitcode = self.loop.run_until_complete(proc.wait()) - self.assertEqual(exitcode, 8) - - def test_kill(self): - args = PROGRAM_BLOCKED - proc = self.loop.run_until_complete( - asyncio.create_subprocess_exec(*args) - ) - proc.kill() - returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': - self.assertIsInstance(returncode, int) - # expect 1 but sometimes get 0 - else: - self.assertEqual(-signal.SIGKILL, returncode) - - def test_terminate(self): - args = PROGRAM_BLOCKED - proc = self.loop.run_until_complete( - asyncio.create_subprocess_exec(*args) - ) - proc.terminate() - returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': - self.assertIsInstance(returncode, int) - # expect 1 but sometimes get 0 - else: - self.assertEqual(-signal.SIGTERM, returncode) - - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") - def test_send_signal(self): - # bpo-31034: Make sure that we get the default signal handler (killing - # the process). The parent process may have decided to ignore SIGHUP, - # and signal handlers are inherited. - old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL) - try: - code = 'import time; print("sleeping", flush=True); time.sleep(3600)' - args = [sys.executable, '-c', code] - proc = self.loop.run_until_complete( - asyncio.create_subprocess_exec( - *args, - stdout=subprocess.PIPE, - ) - ) - - async def send_signal(proc): - # basic synchronization to wait until the program is sleeping - line = await proc.stdout.readline() - self.assertEqual(line, b'sleeping\n') - - proc.send_signal(signal.SIGHUP) - returncode = await proc.wait() - return returncode - - returncode = self.loop.run_until_complete(send_signal(proc)) - self.assertEqual(-signal.SIGHUP, returncode) - finally: - signal.signal(signal.SIGHUP, old_handler) - - def prepare_broken_pipe_test(self): - # buffer large enough to feed the whole pipe buffer - large_data = b'x' * support.PIPE_MAX_SIZE - - # the program ends before the stdin can be feeded - proc = self.loop.run_until_complete( - asyncio.create_subprocess_exec( - sys.executable, '-c', 'pass', - stdin=subprocess.PIPE, - ) - ) - - return (proc, large_data) - - def test_stdin_broken_pipe(self): - proc, large_data = self.prepare_broken_pipe_test() - - async def write_stdin(proc, data): - await asyncio.sleep(0.5) - proc.stdin.write(data) - await proc.stdin.drain() - - coro = write_stdin(proc, large_data) - # drain() must raise BrokenPipeError or ConnectionResetError - with test_utils.disable_logger(): - self.assertRaises((BrokenPipeError, ConnectionResetError), - self.loop.run_until_complete, coro) - self.loop.run_until_complete(proc.wait()) - - def test_communicate_ignore_broken_pipe(self): - proc, large_data = self.prepare_broken_pipe_test() - - # communicate() must ignore BrokenPipeError when feeding stdin - self.loop.set_exception_handler(lambda loop, msg: None) - self.loop.run_until_complete(proc.communicate(large_data)) - self.loop.run_until_complete(proc.wait()) - - def test_pause_reading(self): - limit = 10 - size = (limit * 2 + 1) - - async def test_pause_reading(): - code = '\n'.join(( - 'import sys', - 'sys.stdout.write("x" * %s)' % size, - 'sys.stdout.flush()', - )) - - connect_read_pipe = self.loop.connect_read_pipe - - async def connect_read_pipe_mock(*args, **kw): - transport, protocol = await connect_read_pipe(*args, **kw) - transport.pause_reading = mock.Mock() - transport.resume_reading = mock.Mock() - return (transport, protocol) - - self.loop.connect_read_pipe = connect_read_pipe_mock - - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.PIPE, - stdout=asyncio.subprocess.PIPE, - limit=limit, - ) - stdout_transport = proc._transport.get_pipe_transport(1) - - stdout, stderr = await proc.communicate() - - # The child process produced more than limit bytes of output, - # the stream reader transport should pause the protocol to not - # allocate too much memory. - return (stdout, stdout_transport) - - # Issue #22685: Ensure that the stream reader pauses the protocol - # when the child process produces too much data - stdout, transport = self.loop.run_until_complete(test_pause_reading()) - - self.assertEqual(stdout, b'x' * size) - self.assertTrue(transport.pause_reading.called) - self.assertTrue(transport.resume_reading.called) - - def test_stdin_not_inheritable(self): - # asyncio issue #209: stdin must not be inheritable, otherwise - # the Process.communicate() hangs - async def len_message(message): - code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.PIPE, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - close_fds=False, - ) - stdout, stderr = await proc.communicate(message) - exitcode = await proc.wait() - return (stdout, exitcode) - - output, exitcode = self.loop.run_until_complete(len_message(b'abc')) - self.assertEqual(output.rstrip(), b'3') - self.assertEqual(exitcode, 0) - - def test_empty_input(self): - - async def empty_input(): - code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.PIPE, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - close_fds=False, - ) - stdout, stderr = await proc.communicate(b'') - exitcode = await proc.wait() - return (stdout, exitcode) - - output, exitcode = self.loop.run_until_complete(empty_input()) - self.assertEqual(output.rstrip(), b'0') - self.assertEqual(exitcode, 0) - - def test_devnull_input(self): - - async def empty_input(): - code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.DEVNULL, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - close_fds=False, - ) - stdout, stderr = await proc.communicate() - exitcode = await proc.wait() - return (stdout, exitcode) - - output, exitcode = self.loop.run_until_complete(empty_input()) - self.assertEqual(output.rstrip(), b'0') - self.assertEqual(exitcode, 0) - - def test_devnull_output(self): - - async def empty_output(): - code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.PIPE, - stdout=asyncio.subprocess.DEVNULL, - stderr=asyncio.subprocess.PIPE, - close_fds=False, - ) - stdout, stderr = await proc.communicate(b"abc") - exitcode = await proc.wait() - return (stdout, exitcode) - - output, exitcode = self.loop.run_until_complete(empty_output()) - self.assertEqual(output, None) - self.assertEqual(exitcode, 0) - - def test_devnull_error(self): - - async def empty_error(): - code = 'import sys; data = sys.stdin.read(); print(len(data))' - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdin=asyncio.subprocess.PIPE, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.DEVNULL, - close_fds=False, - ) - stdout, stderr = await proc.communicate(b"abc") - exitcode = await proc.wait() - return (stderr, exitcode) - - output, exitcode = self.loop.run_until_complete(empty_error()) - self.assertEqual(output, None) - self.assertEqual(exitcode, 0) - - def test_cancel_process_wait(self): - # Issue #23140: cancel Process.wait() - - async def cancel_wait(): - proc = await asyncio.create_subprocess_exec(*PROGRAM_BLOCKED) - - # Create an internal future waiting on the process exit - task = self.loop.create_task(proc.wait()) - self.loop.call_soon(task.cancel) - try: - await task - except asyncio.CancelledError: - pass - - # Cancel the future - task.cancel() - - # Kill the process and wait until it is done - proc.kill() - await proc.wait() - - self.loop.run_until_complete(cancel_wait()) - - def test_cancel_make_subprocess_transport_exec(self): - - async def cancel_make_transport(): - coro = asyncio.create_subprocess_exec(*PROGRAM_BLOCKED) - task = self.loop.create_task(coro) - - self.loop.call_soon(task.cancel) - try: - await task - except asyncio.CancelledError: - pass - - # ignore the log: - # "Exception during subprocess creation, kill the subprocess" - with test_utils.disable_logger(): - self.loop.run_until_complete(cancel_make_transport()) - - def test_cancel_post_init(self): - - async def cancel_make_transport(): - coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, - *PROGRAM_BLOCKED) - task = self.loop.create_task(coro) - - self.loop.call_soon(task.cancel) - try: - await task - except asyncio.CancelledError: - pass - - # ignore the log: - # "Exception during subprocess creation, kill the subprocess" - with test_utils.disable_logger(): - self.loop.run_until_complete(cancel_make_transport()) - test_utils.run_briefly(self.loop) - - def test_close_kill_running(self): - - async def kill_running(): - create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, - *PROGRAM_BLOCKED) - transport, protocol = await create - - kill_called = False - def kill(): - nonlocal kill_called - kill_called = True - orig_kill() - - proc = transport.get_extra_info('subprocess') - orig_kill = proc.kill - proc.kill = kill - returncode = transport.get_returncode() - transport.close() - await transport._wait() - return (returncode, kill_called) - - # Ignore "Close running child process: kill ..." log - with test_utils.disable_logger(): - returncode, killed = self.loop.run_until_complete(kill_running()) - self.assertIsNone(returncode) - - # transport.close() must kill the process if it is still running - self.assertTrue(killed) - test_utils.run_briefly(self.loop) - - def test_close_dont_kill_finished(self): - - async def kill_running(): - create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, - *PROGRAM_BLOCKED) - transport, protocol = await create - proc = transport.get_extra_info('subprocess') - - # kill the process (but asyncio is not notified immediately) - proc.kill() - proc.wait() - - proc.kill = mock.Mock() - proc_returncode = proc.poll() - transport_returncode = transport.get_returncode() - transport.close() - return (proc_returncode, transport_returncode, proc.kill.called) - - # Ignore "Unknown child process pid ..." log of SafeChildWatcher, - # emitted because the test already consumes the exit status: - # proc.wait() - with test_utils.disable_logger(): - result = self.loop.run_until_complete(kill_running()) - test_utils.run_briefly(self.loop) - - proc_returncode, transport_return_code, killed = result - - self.assertIsNotNone(proc_returncode) - self.assertIsNone(transport_return_code) - - # transport.close() must not kill the process if it finished, even if - # the transport was not notified yet - self.assertFalse(killed) - - # Unlike SafeChildWatcher, FastChildWatcher does not pop the - # callbacks if waitpid() is called elsewhere. Let's clear them - # manually to avoid a warning when the watcher is detached. - if (sys.platform != 'win32' and - isinstance(self, SubprocessFastWatcherTests)): - asyncio.get_child_watcher()._callbacks.clear() - - async def _test_popen_error(self, stdin): - if sys.platform == 'win32': - target = 'asyncio.windows_utils.Popen' - else: - target = 'subprocess.Popen' - with mock.patch(target) as popen: - exc = ZeroDivisionError - popen.side_effect = exc - - with warnings.catch_warnings(record=True) as warns: - with self.assertRaises(exc): - await asyncio.create_subprocess_exec( - sys.executable, - '-c', - 'pass', - stdin=stdin - ) - self.assertEqual(warns, []) - - def test_popen_error(self): - # Issue #24763: check that the subprocess transport is closed - # when BaseSubprocessTransport fails - self.loop.run_until_complete(self._test_popen_error(stdin=None)) - - def test_popen_error_with_stdin_pipe(self): - # Issue #35721: check that newly created socket pair is closed when - # Popen fails - self.loop.run_until_complete( - self._test_popen_error(stdin=subprocess.PIPE)) - - def test_read_stdout_after_process_exit(self): - - async def execute(): - code = '\n'.join(['import sys', - 'for _ in range(64):', - ' sys.stdout.write("x" * 4096)', - 'sys.stdout.flush()', - 'sys.exit(1)']) - - process = await asyncio.create_subprocess_exec( - sys.executable, '-c', code, - stdout=asyncio.subprocess.PIPE, - ) - - while True: - data = await process.stdout.read(65536) - if data: - await asyncio.sleep(0.3) - else: - break - - self.loop.run_until_complete(execute()) - - def test_create_subprocess_exec_text_mode_fails(self): - async def execute(): - with self.assertRaises(ValueError): - await subprocess.create_subprocess_exec(sys.executable, - text=True) - - with self.assertRaises(ValueError): - await subprocess.create_subprocess_exec(sys.executable, - encoding="utf-8") - - with self.assertRaises(ValueError): - await subprocess.create_subprocess_exec(sys.executable, - errors="strict") - - self.loop.run_until_complete(execute()) - - def test_create_subprocess_shell_text_mode_fails(self): - - async def execute(): - with self.assertRaises(ValueError): - await subprocess.create_subprocess_shell(sys.executable, - text=True) - - with self.assertRaises(ValueError): - await subprocess.create_subprocess_shell(sys.executable, - encoding="utf-8") - - with self.assertRaises(ValueError): - await subprocess.create_subprocess_shell(sys.executable, - errors="strict") - - self.loop.run_until_complete(execute()) - - def test_create_subprocess_exec_with_path(self): - async def execute(): - p = await subprocess.create_subprocess_exec( - support.FakePath(sys.executable), '-c', 'pass') - await p.wait() - p = await subprocess.create_subprocess_exec( - sys.executable, '-c', 'pass', support.FakePath('.')) - await p.wait() - - self.assertIsNone(self.loop.run_until_complete(execute())) - - def test_exec_loop_deprecated(self): - async def go(): - with self.assertWarns(DeprecationWarning): - proc = await asyncio.create_subprocess_exec( - sys.executable, '-c', 'pass', - loop=self.loop, - ) - await proc.wait() - self.loop.run_until_complete(go()) - - def test_shell_loop_deprecated(self): - async def go(): - with self.assertWarns(DeprecationWarning): - proc = await asyncio.create_subprocess_shell( - "exit 0", - loop=self.loop, - ) - await proc.wait() - self.loop.run_until_complete(go()) - - -if sys.platform != 'win32': - # Unix - class SubprocessWatcherMixin(SubprocessMixin): - - Watcher = None - - def setUp(self): - super().setUp() - policy = asyncio.get_event_loop_policy() - self.loop = policy.new_event_loop() - self.set_event_loop(self.loop) - - watcher = self.Watcher() - watcher.attach_loop(self.loop) - policy.set_child_watcher(watcher) - - def tearDown(self): - super().tearDown() - policy = asyncio.get_event_loop_policy() - watcher = policy.get_child_watcher() - policy.set_child_watcher(None) - watcher.attach_loop(None) - watcher.close() - - class SubprocessThreadedWatcherTests(SubprocessWatcherMixin, - test_utils.TestCase): - - Watcher = unix_events.ThreadedChildWatcher - - class SubprocessMultiLoopWatcherTests(SubprocessWatcherMixin, - test_utils.TestCase): - - Watcher = unix_events.MultiLoopChildWatcher - - class SubprocessSafeWatcherTests(SubprocessWatcherMixin, - test_utils.TestCase): - - Watcher = unix_events.SafeChildWatcher - - class SubprocessFastWatcherTests(SubprocessWatcherMixin, - test_utils.TestCase): - - Watcher = unix_events.FastChildWatcher - - def has_pidfd_support(): - if not hasattr(os, 'pidfd_open'): - return False - try: - os.close(os.pidfd_open(os.getpid())) - except OSError: - return False - return True - - @unittest.skipUnless( - has_pidfd_support(), - "operating system does not support pidfds", - ) - class SubprocessPidfdWatcherTests(SubprocessWatcherMixin, - test_utils.TestCase): - Watcher = unix_events.PidfdChildWatcher - -else: - # Windows - class SubprocessProactorTests(SubprocessMixin, test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.ProactorEventLoop() - self.set_event_loop(self.loop) - - -class GenericWatcherTests: - - def test_create_subprocess_fails_with_inactive_watcher(self): - - async def execute(): - watcher = mock.create_authspec(asyncio.AbstractChildWatcher) - watcher.is_active.return_value = False - asyncio.set_child_watcher(watcher) - - with self.assertRaises(RuntimeError): - await subprocess.create_subprocess_exec( - support.FakePath(sys.executable), '-c', 'pass') - - watcher.add_child_handler.assert_not_called() - - self.assertIsNone(self.loop.run_until_complete(execute())) - - - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py deleted file mode 100644 index dde84b8..0000000 --- a/Lib/test/test_asyncio/test_tasks.py +++ /dev/null @@ -1,3375 +0,0 @@ -"""Tests for tasks.py.""" - -import collections -import contextlib -import contextvars -import functools -import gc -import io -import random -import re -import sys -import textwrap -import types -import unittest -import weakref -from unittest import mock - -import asyncio -from asyncio import coroutines -from asyncio import futures -from asyncio import tasks -from test.test_asyncio import utils as test_utils -from test import support -from test.support.script_helper import assert_python_ok - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -async def coroutine_function(): - pass - - -@contextlib.contextmanager -def set_coroutine_debug(enabled): - coroutines = asyncio.coroutines - - old_debug = coroutines._DEBUG - try: - coroutines._DEBUG = enabled - yield - finally: - coroutines._DEBUG = old_debug - - -def format_coroutine(qualname, state, src, source_traceback, generator=False): - if generator: - state = '%s' % state - else: - state = '%s, defined' % state - if source_traceback is not None: - frame = source_traceback[-1] - return ('coro=<%s() %s at %s> created at %s:%s' - % (qualname, state, src, frame[0], frame[1])) - else: - return 'coro=<%s() %s at %s>' % (qualname, state, src) - - -class Dummy: - - def __repr__(self): - return '<Dummy>' - - def __call__(self, *args): - pass - - -class CoroLikeObject: - def send(self, v): - raise StopIteration(42) - - def throw(self, *exc): - pass - - def close(self): - pass - - def __await__(self): - return self - - -class BaseTaskTests: - - Task = None - Future = None - - def new_task(self, loop, coro, name='TestTask'): - return self.__class__.Task(coro, loop=loop, name=name) - - def new_future(self, loop): - return self.__class__.Future(loop=loop) - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.loop.set_task_factory(self.new_task) - self.loop.create_future = lambda: self.new_future(self.loop) - - def test_task_del_collect(self): - class Evil: - def __del__(self): - gc.collect() - - async def run(): - return Evil() - - self.loop.run_until_complete( - asyncio.gather(*[ - self.new_task(self.loop, run()) for _ in range(100) - ], loop=self.loop)) - - def test_other_loop_future(self): - other_loop = asyncio.new_event_loop() - fut = self.new_future(other_loop) - - async def run(fut): - await fut - - try: - with self.assertRaisesRegex(RuntimeError, - r'Task .* got Future .* attached'): - self.loop.run_until_complete(run(fut)) - finally: - other_loop.close() - - def test_task_awaits_on_itself(self): - - async def test(): - await task - - task = asyncio.ensure_future(test(), loop=self.loop) - - with self.assertRaisesRegex(RuntimeError, - 'Task cannot await on itself'): - self.loop.run_until_complete(task) - - def test_task_class(self): - async def notmuch(): - return 'ok' - t = self.new_task(self.loop, notmuch()) - self.loop.run_until_complete(t) - self.assertTrue(t.done()) - self.assertEqual(t.result(), 'ok') - self.assertIs(t._loop, self.loop) - self.assertIs(t.get_loop(), self.loop) - - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - t = self.new_task(loop, notmuch()) - self.assertIs(t._loop, loop) - loop.run_until_complete(t) - loop.close() - - def test_ensure_future_coroutine(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def notmuch(): - return 'ok' - t = asyncio.ensure_future(notmuch(), loop=self.loop) - self.loop.run_until_complete(t) - self.assertTrue(t.done()) - self.assertEqual(t.result(), 'ok') - self.assertIs(t._loop, self.loop) - - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - t = asyncio.ensure_future(notmuch(), loop=loop) - self.assertIs(t._loop, loop) - loop.run_until_complete(t) - loop.close() - - def test_ensure_future_future(self): - f_orig = self.new_future(self.loop) - f_orig.set_result('ko') - - f = asyncio.ensure_future(f_orig) - self.loop.run_until_complete(f) - self.assertTrue(f.done()) - self.assertEqual(f.result(), 'ko') - self.assertIs(f, f_orig) - - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - - with self.assertRaises(ValueError): - f = asyncio.ensure_future(f_orig, loop=loop) - - loop.close() - - f = asyncio.ensure_future(f_orig, loop=self.loop) - self.assertIs(f, f_orig) - - def test_ensure_future_task(self): - async def notmuch(): - return 'ok' - t_orig = self.new_task(self.loop, notmuch()) - t = asyncio.ensure_future(t_orig) - self.loop.run_until_complete(t) - self.assertTrue(t.done()) - self.assertEqual(t.result(), 'ok') - self.assertIs(t, t_orig) - - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - - with self.assertRaises(ValueError): - t = asyncio.ensure_future(t_orig, loop=loop) - - loop.close() - - t = asyncio.ensure_future(t_orig, loop=self.loop) - self.assertIs(t, t_orig) - - def test_ensure_future_awaitable(self): - class Aw: - def __init__(self, coro): - self.coro = coro - def __await__(self): - return (yield from self.coro) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - return 'ok' - - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - fut = asyncio.ensure_future(Aw(coro()), loop=loop) - loop.run_until_complete(fut) - assert fut.result() == 'ok' - - def test_ensure_future_neither(self): - with self.assertRaises(TypeError): - asyncio.ensure_future('ok') - - def test_ensure_future_error_msg(self): - loop = asyncio.new_event_loop() - f = self.new_future(self.loop) - with self.assertRaisesRegex(ValueError, 'The future belongs to a ' - 'different loop than the one specified as ' - 'the loop argument'): - asyncio.ensure_future(f, loop=loop) - loop.close() - - def test_get_stack(self): - T = None - - async def foo(): - await bar() - - async def bar(): - # test get_stack() - f = T.get_stack(limit=1) - try: - self.assertEqual(f[0].f_code.co_name, 'foo') - finally: - f = None - - # test print_stack() - file = io.StringIO() - T.print_stack(limit=1, file=file) - file.seek(0) - tb = file.read() - self.assertRegex(tb, r'foo\(\) running') - - async def runner(): - nonlocal T - T = asyncio.ensure_future(foo(), loop=self.loop) - await T - - self.loop.run_until_complete(runner()) - - def test_task_repr(self): - self.loop.set_debug(False) - - async def notmuch(): - return 'abc' - - # test coroutine function - self.assertEqual(notmuch.__name__, 'notmuch') - self.assertRegex(notmuch.__qualname__, - r'\w+.test_task_repr.<locals>.notmuch') - self.assertEqual(notmuch.__module__, __name__) - - filename, lineno = test_utils.get_function_source(notmuch) - src = "%s:%s" % (filename, lineno) - - # test coroutine object - gen = notmuch() - coro_qualname = 'BaseTaskTests.test_task_repr.<locals>.notmuch' - self.assertEqual(gen.__name__, 'notmuch') - self.assertEqual(gen.__qualname__, coro_qualname) - - # test pending Task - t = self.new_task(self.loop, gen) - t.add_done_callback(Dummy()) - - coro = format_coroutine(coro_qualname, 'running', src, - t._source_traceback, generator=True) - self.assertEqual(repr(t), - "<Task pending name='TestTask' %s cb=[<Dummy>()]>" % coro) - - # test cancelling Task - t.cancel() # Does not take immediate effect! - self.assertEqual(repr(t), - "<Task cancelling name='TestTask' %s cb=[<Dummy>()]>" % coro) - - # test cancelled Task - self.assertRaises(asyncio.CancelledError, - self.loop.run_until_complete, t) - coro = format_coroutine(coro_qualname, 'done', src, - t._source_traceback) - self.assertEqual(repr(t), - "<Task cancelled name='TestTask' %s>" % coro) - - # test finished Task - t = self.new_task(self.loop, notmuch()) - self.loop.run_until_complete(t) - coro = format_coroutine(coro_qualname, 'done', src, - t._source_traceback) - self.assertEqual(repr(t), - "<Task finished name='TestTask' %s result='abc'>" % coro) - - def test_task_repr_autogenerated(self): - async def notmuch(): - return 123 - - t1 = self.new_task(self.loop, notmuch(), None) - t2 = self.new_task(self.loop, notmuch(), None) - self.assertNotEqual(repr(t1), repr(t2)) - - match1 = re.match(r"^<Task pending name='Task-(\d+)'", repr(t1)) - self.assertIsNotNone(match1) - match2 = re.match(r"^<Task pending name='Task-(\d+)'", repr(t2)) - self.assertIsNotNone(match2) - - # Autogenerated task names should have monotonically increasing numbers - self.assertLess(int(match1.group(1)), int(match2.group(1))) - self.loop.run_until_complete(t1) - self.loop.run_until_complete(t2) - - def test_task_repr_name_not_str(self): - async def notmuch(): - return 123 - - t = self.new_task(self.loop, notmuch()) - t.set_name({6}) - self.assertEqual(t.get_name(), '{6}') - self.loop.run_until_complete(t) - - def test_task_repr_coro_decorator(self): - self.loop.set_debug(False) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def notmuch(): - # notmuch() function doesn't use yield from: it will be wrapped by - # @coroutine decorator - return 123 - - # test coroutine function - self.assertEqual(notmuch.__name__, 'notmuch') - self.assertRegex(notmuch.__qualname__, - r'\w+.test_task_repr_coro_decorator' - r'\.<locals>\.notmuch') - self.assertEqual(notmuch.__module__, __name__) - - # test coroutine object - gen = notmuch() - # On Python >= 3.5, generators now inherit the name of the - # function, as expected, and have a qualified name (__qualname__ - # attribute). - coro_name = 'notmuch' - coro_qualname = ('BaseTaskTests.test_task_repr_coro_decorator' - '.<locals>.notmuch') - self.assertEqual(gen.__name__, coro_name) - self.assertEqual(gen.__qualname__, coro_qualname) - - # test repr(CoroWrapper) - if coroutines._DEBUG: - # format the coroutine object - if coroutines._DEBUG: - filename, lineno = test_utils.get_function_source(notmuch) - frame = gen._source_traceback[-1] - coro = ('%s() running, defined at %s:%s, created at %s:%s' - % (coro_qualname, filename, lineno, - frame[0], frame[1])) - else: - code = gen.gi_code - coro = ('%s() running at %s:%s' - % (coro_qualname, code.co_filename, - code.co_firstlineno)) - - self.assertEqual(repr(gen), '<CoroWrapper %s>' % coro) - - # test pending Task - t = self.new_task(self.loop, gen) - t.add_done_callback(Dummy()) - - # format the coroutine object - if coroutines._DEBUG: - src = '%s:%s' % test_utils.get_function_source(notmuch) - else: - code = gen.gi_code - src = '%s:%s' % (code.co_filename, code.co_firstlineno) - coro = format_coroutine(coro_qualname, 'running', src, - t._source_traceback, - generator=not coroutines._DEBUG) - self.assertEqual(repr(t), - "<Task pending name='TestTask' %s cb=[<Dummy>()]>" % coro) - self.loop.run_until_complete(t) - - def test_task_repr_wait_for(self): - self.loop.set_debug(False) - - async def wait_for(fut): - return await fut - - fut = self.new_future(self.loop) - task = self.new_task(self.loop, wait_for(fut)) - test_utils.run_briefly(self.loop) - self.assertRegex(repr(task), - '<Task .* wait_for=%s>' % re.escape(repr(fut))) - - fut.set_result(None) - self.loop.run_until_complete(task) - - def test_task_repr_partial_corowrapper(self): - # Issue #222: repr(CoroWrapper) must not fail in debug mode if the - # coroutine is a partial function - with set_coroutine_debug(True): - self.loop.set_debug(True) - - async def func(x, y): - await asyncio.sleep(0) - - with self.assertWarns(DeprecationWarning): - partial_func = asyncio.coroutine(functools.partial(func, 1)) - task = self.loop.create_task(partial_func(2)) - - # make warnings quiet - task._log_destroy_pending = False - self.addCleanup(task._coro.close) - - coro_repr = repr(task._coro) - expected = ( - r'<coroutine object \w+\.test_task_repr_partial_corowrapper' - r'\.<locals>\.func at' - ) - self.assertRegex(coro_repr, expected) - - def test_task_basics(self): - - async def outer(): - a = await inner1() - b = await inner2() - return a+b - - async def inner1(): - return 42 - - async def inner2(): - return 1000 - - t = outer() - self.assertEqual(self.loop.run_until_complete(t), 1042) - - def test_cancel(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - yield 0 - - loop = self.new_test_loop(gen) - - async def task(): - await asyncio.sleep(10.0) - return 12 - - t = self.new_task(loop, task()) - loop.call_soon(t.cancel) - with self.assertRaises(asyncio.CancelledError): - loop.run_until_complete(t) - self.assertTrue(t.done()) - self.assertTrue(t.cancelled()) - self.assertFalse(t.cancel()) - - def test_cancel_yield(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def task(): - yield - yield - return 12 - - t = self.new_task(self.loop, task()) - test_utils.run_briefly(self.loop) # start coro - t.cancel() - self.assertRaises( - asyncio.CancelledError, self.loop.run_until_complete, t) - self.assertTrue(t.done()) - self.assertTrue(t.cancelled()) - self.assertFalse(t.cancel()) - - def test_cancel_inner_future(self): - f = self.new_future(self.loop) - - async def task(): - await f - return 12 - - t = self.new_task(self.loop, task()) - test_utils.run_briefly(self.loop) # start task - f.cancel() - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(t) - self.assertTrue(f.cancelled()) - self.assertTrue(t.cancelled()) - - def test_cancel_both_task_and_inner_future(self): - f = self.new_future(self.loop) - - async def task(): - await f - return 12 - - t = self.new_task(self.loop, task()) - test_utils.run_briefly(self.loop) - - f.cancel() - t.cancel() - - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(t) - - self.assertTrue(t.done()) - self.assertTrue(f.cancelled()) - self.assertTrue(t.cancelled()) - - def test_cancel_task_catching(self): - fut1 = self.new_future(self.loop) - fut2 = self.new_future(self.loop) - - async def task(): - await fut1 - try: - await fut2 - except asyncio.CancelledError: - return 42 - - t = self.new_task(self.loop, task()) - test_utils.run_briefly(self.loop) - self.assertIs(t._fut_waiter, fut1) # White-box test. - fut1.set_result(None) - test_utils.run_briefly(self.loop) - self.assertIs(t._fut_waiter, fut2) # White-box test. - t.cancel() - self.assertTrue(fut2.cancelled()) - res = self.loop.run_until_complete(t) - self.assertEqual(res, 42) - self.assertFalse(t.cancelled()) - - def test_cancel_task_ignoring(self): - fut1 = self.new_future(self.loop) - fut2 = self.new_future(self.loop) - fut3 = self.new_future(self.loop) - - async def task(): - await fut1 - try: - await fut2 - except asyncio.CancelledError: - pass - res = await fut3 - return res - - t = self.new_task(self.loop, task()) - test_utils.run_briefly(self.loop) - self.assertIs(t._fut_waiter, fut1) # White-box test. - fut1.set_result(None) - test_utils.run_briefly(self.loop) - self.assertIs(t._fut_waiter, fut2) # White-box test. - t.cancel() - self.assertTrue(fut2.cancelled()) - test_utils.run_briefly(self.loop) - self.assertIs(t._fut_waiter, fut3) # White-box test. - fut3.set_result(42) - res = self.loop.run_until_complete(t) - self.assertEqual(res, 42) - self.assertFalse(fut3.cancelled()) - self.assertFalse(t.cancelled()) - - def test_cancel_current_task(self): - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - - async def task(): - t.cancel() - self.assertTrue(t._must_cancel) # White-box test. - # The sleep should be cancelled immediately. - await asyncio.sleep(100) - return 12 - - t = self.new_task(loop, task()) - self.assertFalse(t.cancelled()) - self.assertRaises( - asyncio.CancelledError, loop.run_until_complete, t) - self.assertTrue(t.done()) - self.assertTrue(t.cancelled()) - self.assertFalse(t._must_cancel) # White-box test. - self.assertFalse(t.cancel()) - - def test_cancel_at_end(self): - """coroutine end right after task is cancelled""" - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - - async def task(): - t.cancel() - self.assertTrue(t._must_cancel) # White-box test. - return 12 - - t = self.new_task(loop, task()) - self.assertFalse(t.cancelled()) - self.assertRaises( - asyncio.CancelledError, loop.run_until_complete, t) - self.assertTrue(t.done()) - self.assertTrue(t.cancelled()) - self.assertFalse(t._must_cancel) # White-box test. - self.assertFalse(t.cancel()) - - def test_cancel_awaited_task(self): - # This tests for a relatively rare condition when - # a task cancellation is requested for a task which is not - # currently blocked, such as a task cancelling itself. - # In this situation we must ensure that whatever next future - # or task the cancelled task blocks on is cancelled correctly - # as well. See also bpo-34872. - loop = asyncio.new_event_loop() - self.addCleanup(lambda: loop.close()) - - task = nested_task = None - fut = self.new_future(loop) - - async def nested(): - await fut - - async def coro(): - nonlocal nested_task - # Create a sub-task and wait for it to run. - nested_task = self.new_task(loop, nested()) - await asyncio.sleep(0) - - # Request the current task to be cancelled. - task.cancel() - # Block on the nested task, which should be immediately - # cancelled. - await nested_task - - task = self.new_task(loop, coro()) - with self.assertRaises(asyncio.CancelledError): - loop.run_until_complete(task) - - self.assertTrue(task.cancelled()) - self.assertTrue(nested_task.cancelled()) - self.assertTrue(fut.cancelled()) - - def test_stop_while_run_in_complete(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0.1 - self.assertAlmostEqual(0.2, when) - when = yield 0.1 - self.assertAlmostEqual(0.3, when) - yield 0.1 - - loop = self.new_test_loop(gen) - - x = 0 - - async def task(): - nonlocal x - while x < 10: - await asyncio.sleep(0.1) - x += 1 - if x == 2: - loop.stop() - - t = self.new_task(loop, task()) - with self.assertRaises(RuntimeError) as cm: - loop.run_until_complete(t) - self.assertEqual(str(cm.exception), - 'Event loop stopped before Future completed.') - self.assertFalse(t.done()) - self.assertEqual(x, 2) - self.assertAlmostEqual(0.3, loop.time()) - - t.cancel() - self.assertRaises(asyncio.CancelledError, loop.run_until_complete, t) - - def test_log_traceback(self): - async def coro(): - pass - - task = self.new_task(self.loop, coro()) - with self.assertRaisesRegex(ValueError, 'can only be set to False'): - task._log_traceback = True - self.loop.run_until_complete(task) - - def test_wait_for_timeout_less_then_0_or_0_future_done(self): - def gen(): - when = yield - self.assertAlmostEqual(0, when) - - loop = self.new_test_loop(gen) - - fut = self.new_future(loop) - fut.set_result('done') - - ret = loop.run_until_complete(asyncio.wait_for(fut, 0)) - - self.assertEqual(ret, 'done') - self.assertTrue(fut.done()) - self.assertAlmostEqual(0, loop.time()) - - def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self): - def gen(): - when = yield - self.assertAlmostEqual(0, when) - - loop = self.new_test_loop(gen) - - foo_started = False - - async def foo(): - nonlocal foo_started - foo_started = True - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(asyncio.wait_for(foo(), 0)) - - self.assertAlmostEqual(0, loop.time()) - self.assertEqual(foo_started, False) - - def test_wait_for_timeout_less_then_0_or_0(self): - def gen(): - when = yield - self.assertAlmostEqual(0.2, when) - when = yield 0 - self.assertAlmostEqual(0, when) - - for timeout in [0, -1]: - with self.subTest(timeout=timeout): - loop = self.new_test_loop(gen) - - foo_running = None - - async def foo(): - nonlocal foo_running - foo_running = True - try: - await asyncio.sleep(0.2) - finally: - foo_running = False - return 'done' - - fut = self.new_task(loop, foo()) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(asyncio.wait_for(fut, timeout)) - self.assertTrue(fut.done()) - # it should have been cancelled due to the timeout - self.assertTrue(fut.cancelled()) - self.assertAlmostEqual(0, loop.time()) - self.assertEqual(foo_running, False) - - def test_wait_for(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.2, when) - when = yield 0 - self.assertAlmostEqual(0.1, when) - when = yield 0.1 - - loop = self.new_test_loop(gen) - - foo_running = None - - async def foo(): - nonlocal foo_running - foo_running = True - try: - await asyncio.sleep(0.2) - finally: - foo_running = False - return 'done' - - fut = self.new_task(loop, foo()) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(asyncio.wait_for(fut, 0.1)) - self.assertTrue(fut.done()) - # it should have been cancelled due to the timeout - self.assertTrue(fut.cancelled()) - self.assertAlmostEqual(0.1, loop.time()) - self.assertEqual(foo_running, False) - - def test_wait_for_blocking(self): - loop = self.new_test_loop() - - async def coro(): - return 'done' - - res = loop.run_until_complete(asyncio.wait_for(coro(), timeout=None)) - self.assertEqual(res, 'done') - - def test_wait_for_with_global_loop(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.2, when) - when = yield 0 - self.assertAlmostEqual(0.01, when) - yield 0.01 - - loop = self.new_test_loop(gen) - - async def foo(): - await asyncio.sleep(0.2) - return 'done' - - asyncio.set_event_loop(loop) - try: - fut = self.new_task(loop, foo()) - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(asyncio.wait_for(fut, 0.01)) - finally: - asyncio.set_event_loop(None) - - self.assertAlmostEqual(0.01, loop.time()) - self.assertTrue(fut.done()) - self.assertTrue(fut.cancelled()) - - def test_wait_for_race_condition(self): - - def gen(): - yield 0.1 - yield 0.1 - yield 0.1 - - loop = self.new_test_loop(gen) - - fut = self.new_future(loop) - task = asyncio.wait_for(fut, timeout=0.2) - loop.call_later(0.1, fut.set_result, "ok") - res = loop.run_until_complete(task) - self.assertEqual(res, "ok") - - def test_wait_for_waits_for_task_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - task_done = False - - async def foo(): - async def inner(): - nonlocal task_done - try: - await asyncio.sleep(0.2) - finally: - task_done = True - - inner_task = self.new_task(loop, inner()) - - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(inner_task, timeout=0.1) - - self.assertTrue(task_done) - - loop.run_until_complete(foo()) - - def test_wait_for_self_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def foo(): - async def inner(): - try: - await asyncio.sleep(0.3) - except asyncio.CancelledError: - try: - await asyncio.sleep(0.3) - except asyncio.CancelledError: - await asyncio.sleep(0.3) - - return 42 - - inner_task = self.new_task(loop, inner()) - - wait = asyncio.wait_for(inner_task, timeout=0.1) - - # Test that wait_for itself is properly cancellable - # even when the initial task holds up the initial cancellation. - task = self.new_task(loop, wait) - await asyncio.sleep(0.2) - task.cancel() - - with self.assertRaises(asyncio.CancelledError): - await task - - self.assertEqual(await inner_task, 42) - - loop.run_until_complete(foo()) - - def test_wait(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(0.15, when) - yield 0.15 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(0.1)) - b = self.new_task(loop, asyncio.sleep(0.15)) - - async def foo(): - done, pending = await asyncio.wait([b, a]) - self.assertEqual(done, set([a, b])) - self.assertEqual(pending, set()) - return 42 - - res = loop.run_until_complete(self.new_task(loop, foo())) - self.assertEqual(res, 42) - self.assertAlmostEqual(0.15, loop.time()) - - # Doing it again should take no time and exercise a different path. - res = loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.15, loop.time()) - self.assertEqual(res, 42) - - def test_wait_with_global_loop(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.01, when) - when = yield 0 - self.assertAlmostEqual(0.015, when) - yield 0.015 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(0.01)) - b = self.new_task(loop, asyncio.sleep(0.015)) - - async def foo(): - done, pending = await asyncio.wait([b, a]) - self.assertEqual(done, set([a, b])) - self.assertEqual(pending, set()) - return 42 - - asyncio.set_event_loop(loop) - res = loop.run_until_complete( - self.new_task(loop, foo())) - - self.assertEqual(res, 42) - - def test_wait_duplicate_coroutines(self): - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(s): - return s - c = coro('test') - - task =self.new_task( - self.loop, - asyncio.wait([c, c, coro('spam')])) - - done, pending = self.loop.run_until_complete(task) - - self.assertFalse(pending) - self.assertEqual(set(f.result() for f in done), {'test', 'spam'}) - - def test_wait_errors(self): - self.assertRaises( - ValueError, self.loop.run_until_complete, - asyncio.wait(set())) - - # -1 is an invalid return_when value - sleep_coro = asyncio.sleep(10.0) - wait_coro = asyncio.wait([sleep_coro], return_when=-1) - self.assertRaises(ValueError, - self.loop.run_until_complete, wait_coro) - - sleep_coro.close() - - def test_wait_first_completed(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - when = yield 0 - self.assertAlmostEqual(0.1, when) - yield 0.1 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(10.0)) - b = self.new_task(loop, asyncio.sleep(0.1)) - task = self.new_task( - loop, - asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED)) - - done, pending = loop.run_until_complete(task) - self.assertEqual({b}, done) - self.assertEqual({a}, pending) - self.assertFalse(a.done()) - self.assertTrue(b.done()) - self.assertIsNone(b.result()) - self.assertAlmostEqual(0.1, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_wait_really_done(self): - # there is possibility that some tasks in the pending list - # became done but their callbacks haven't all been called yet - - async def coro1(): - await asyncio.sleep(0) - - async def coro2(): - await asyncio.sleep(0) - await asyncio.sleep(0) - - a = self.new_task(self.loop, coro1()) - b = self.new_task(self.loop, coro2()) - task = self.new_task( - self.loop, - asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED)) - - done, pending = self.loop.run_until_complete(task) - self.assertEqual({a, b}, done) - self.assertTrue(a.done()) - self.assertIsNone(a.result()) - self.assertTrue(b.done()) - self.assertIsNone(b.result()) - - def test_wait_first_exception(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - yield 0 - - loop = self.new_test_loop(gen) - - # first_exception, task already has exception - a = self.new_task(loop, asyncio.sleep(10.0)) - - async def exc(): - raise ZeroDivisionError('err') - - b = self.new_task(loop, exc()) - task = self.new_task( - loop, - asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION)) - - done, pending = loop.run_until_complete(task) - self.assertEqual({b}, done) - self.assertEqual({a}, pending) - self.assertAlmostEqual(0, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_wait_first_exception_in_wait(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - when = yield 0 - self.assertAlmostEqual(0.01, when) - yield 0.01 - - loop = self.new_test_loop(gen) - - # first_exception, exception during waiting - a = self.new_task(loop, asyncio.sleep(10.0)) - - async def exc(): - await asyncio.sleep(0.01) - raise ZeroDivisionError('err') - - b = self.new_task(loop, exc()) - task = asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION) - - done, pending = loop.run_until_complete(task) - self.assertEqual({b}, done) - self.assertEqual({a}, pending) - self.assertAlmostEqual(0.01, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_wait_with_exception(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(0.15, when) - yield 0.15 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(0.1)) - - async def sleeper(): - await asyncio.sleep(0.15) - raise ZeroDivisionError('really') - - b = self.new_task(loop, sleeper()) - - async def foo(): - done, pending = await asyncio.wait([b, a]) - self.assertEqual(len(done), 2) - self.assertEqual(pending, set()) - errors = set(f for f in done if f.exception() is not None) - self.assertEqual(len(errors), 1) - - loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.15, loop.time()) - - loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.15, loop.time()) - - def test_wait_with_timeout(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(0.15, when) - when = yield 0 - self.assertAlmostEqual(0.11, when) - yield 0.11 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(0.1)) - b = self.new_task(loop, asyncio.sleep(0.15)) - - async def foo(): - done, pending = await asyncio.wait([b, a], timeout=0.11) - self.assertEqual(done, set([a])) - self.assertEqual(pending, set([b])) - - loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.11, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_wait_concurrent_complete(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(0.15, when) - when = yield 0 - self.assertAlmostEqual(0.1, when) - yield 0.1 - - loop = self.new_test_loop(gen) - - a = self.new_task(loop, asyncio.sleep(0.1)) - b = self.new_task(loop, asyncio.sleep(0.15)) - - done, pending = loop.run_until_complete( - asyncio.wait([b, a], timeout=0.1)) - - self.assertEqual(done, set([a])) - self.assertEqual(pending, set([b])) - self.assertAlmostEqual(0.1, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_as_completed(self): - - def gen(): - yield 0 - yield 0 - yield 0.01 - yield 0 - - loop = self.new_test_loop(gen) - # disable "slow callback" warning - loop.slow_callback_duration = 1.0 - completed = set() - time_shifted = False - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def sleeper(dt, x): - nonlocal time_shifted - yield from asyncio.sleep(dt) - completed.add(x) - if not time_shifted and 'a' in completed and 'b' in completed: - time_shifted = True - loop.advance_time(0.14) - return x - - a = sleeper(0.01, 'a') - b = sleeper(0.01, 'b') - c = sleeper(0.15, 'c') - - async def foo(): - values = [] - for f in asyncio.as_completed([b, c, a], loop=loop): - values.append(await f) - return values - with self.assertWarns(DeprecationWarning): - res = loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.15, loop.time()) - self.assertTrue('a' in res[:2]) - self.assertTrue('b' in res[:2]) - self.assertEqual(res[2], 'c') - - # Doing it again should take no time and exercise a different path. - with self.assertWarns(DeprecationWarning): - res = loop.run_until_complete(self.new_task(loop, foo())) - self.assertAlmostEqual(0.15, loop.time()) - - def test_as_completed_with_timeout(self): - - def gen(): - yield - yield 0 - yield 0 - yield 0.1 - - loop = self.new_test_loop(gen) - - a = loop.create_task(asyncio.sleep(0.1, 'a')) - b = loop.create_task(asyncio.sleep(0.15, 'b')) - - async def foo(): - values = [] - for f in asyncio.as_completed([a, b], timeout=0.12, loop=loop): - if values: - loop.advance_time(0.02) - try: - v = await f - values.append((1, v)) - except asyncio.TimeoutError as exc: - values.append((2, exc)) - return values - - with self.assertWarns(DeprecationWarning): - res = loop.run_until_complete(self.new_task(loop, foo())) - self.assertEqual(len(res), 2, res) - self.assertEqual(res[0], (1, 'a')) - self.assertEqual(res[1][0], 2) - self.assertIsInstance(res[1][1], asyncio.TimeoutError) - self.assertAlmostEqual(0.12, loop.time()) - - # move forward to close generator - loop.advance_time(10) - loop.run_until_complete(asyncio.wait([a, b])) - - def test_as_completed_with_unused_timeout(self): - - def gen(): - yield - yield 0 - yield 0.01 - - loop = self.new_test_loop(gen) - - a = asyncio.sleep(0.01, 'a') - - async def foo(): - for f in asyncio.as_completed([a], timeout=1, loop=loop): - v = await f - self.assertEqual(v, 'a') - - with self.assertWarns(DeprecationWarning): - loop.run_until_complete(self.new_task(loop, foo())) - - def test_as_completed_reverse_wait(self): - - def gen(): - yield 0 - yield 0.05 - yield 0 - - loop = self.new_test_loop(gen) - - a = asyncio.sleep(0.05, 'a') - b = asyncio.sleep(0.10, 'b') - fs = {a, b} - - with self.assertWarns(DeprecationWarning): - futs = list(asyncio.as_completed(fs, loop=loop)) - self.assertEqual(len(futs), 2) - - x = loop.run_until_complete(futs[1]) - self.assertEqual(x, 'a') - self.assertAlmostEqual(0.05, loop.time()) - loop.advance_time(0.05) - y = loop.run_until_complete(futs[0]) - self.assertEqual(y, 'b') - self.assertAlmostEqual(0.10, loop.time()) - - def test_as_completed_concurrent(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.05, when) - when = yield 0 - self.assertAlmostEqual(0.05, when) - yield 0.05 - - loop = self.new_test_loop(gen) - - a = asyncio.sleep(0.05, 'a') - b = asyncio.sleep(0.05, 'b') - fs = {a, b} - with self.assertWarns(DeprecationWarning): - futs = list(asyncio.as_completed(fs, loop=loop)) - self.assertEqual(len(futs), 2) - waiter = asyncio.wait(futs) - done, pending = loop.run_until_complete(waiter) - self.assertEqual(set(f.result() for f in done), {'a', 'b'}) - - def test_as_completed_duplicate_coroutines(self): - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(s): - return s - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def runner(): - result = [] - c = coro('ham') - for f in asyncio.as_completed([c, c, coro('spam')], - loop=self.loop): - result.append((yield from f)) - return result - - with self.assertWarns(DeprecationWarning): - fut = self.new_task(self.loop, runner()) - self.loop.run_until_complete(fut) - result = fut.result() - self.assertEqual(set(result), {'ham', 'spam'}) - self.assertEqual(len(result), 2) - - def test_sleep(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.05, when) - when = yield 0.05 - self.assertAlmostEqual(0.1, when) - yield 0.05 - - loop = self.new_test_loop(gen) - - async def sleeper(dt, arg): - await asyncio.sleep(dt/2) - res = await asyncio.sleep(dt/2, arg) - return res - - t = self.new_task(loop, sleeper(0.1, 'yeah')) - loop.run_until_complete(t) - self.assertTrue(t.done()) - self.assertEqual(t.result(), 'yeah') - self.assertAlmostEqual(0.1, loop.time()) - - def test_sleep_cancel(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - yield 0 - - loop = self.new_test_loop(gen) - - t = self.new_task(loop, asyncio.sleep(10.0, 'yeah')) - - handle = None - orig_call_later = loop.call_later - - def call_later(delay, callback, *args): - nonlocal handle - handle = orig_call_later(delay, callback, *args) - return handle - - loop.call_later = call_later - test_utils.run_briefly(loop) - - self.assertFalse(handle._cancelled) - - t.cancel() - test_utils.run_briefly(loop) - self.assertTrue(handle._cancelled) - - def test_task_cancel_sleeping_task(self): - - def gen(): - when = yield - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(5000, when) - yield 0.1 - - loop = self.new_test_loop(gen) - - async def sleep(dt): - await asyncio.sleep(dt) - - async def doit(): - sleeper = self.new_task(loop, sleep(5000)) - loop.call_later(0.1, sleeper.cancel) - try: - await sleeper - except asyncio.CancelledError: - return 'cancelled' - else: - return 'slept in' - - doer = doit() - self.assertEqual(loop.run_until_complete(doer), 'cancelled') - self.assertAlmostEqual(0.1, loop.time()) - - def test_task_cancel_waiter_future(self): - fut = self.new_future(self.loop) - - async def coro(): - await fut - - task = self.new_task(self.loop, coro()) - test_utils.run_briefly(self.loop) - self.assertIs(task._fut_waiter, fut) - - task.cancel() - test_utils.run_briefly(self.loop) - self.assertRaises( - asyncio.CancelledError, self.loop.run_until_complete, task) - self.assertIsNone(task._fut_waiter) - self.assertTrue(fut.cancelled()) - - def test_task_set_methods(self): - async def notmuch(): - return 'ko' - - gen = notmuch() - task = self.new_task(self.loop, gen) - - with self.assertRaisesRegex(RuntimeError, 'not support set_result'): - task.set_result('ok') - - with self.assertRaisesRegex(RuntimeError, 'not support set_exception'): - task.set_exception(ValueError()) - - self.assertEqual( - self.loop.run_until_complete(task), - 'ko') - - def test_step_result(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def notmuch(): - yield None - yield 1 - return 'ko' - - self.assertRaises( - RuntimeError, self.loop.run_until_complete, notmuch()) - - def test_step_result_future(self): - # If coroutine returns future, task waits on this future. - - class Fut(asyncio.Future): - def __init__(self, *args, **kwds): - self.cb_added = False - super().__init__(*args, **kwds) - - def add_done_callback(self, *args, **kwargs): - self.cb_added = True - super().add_done_callback(*args, **kwargs) - - fut = Fut(loop=self.loop) - result = None - - async def wait_for_future(): - nonlocal result - result = await fut - - t = self.new_task(self.loop, wait_for_future()) - test_utils.run_briefly(self.loop) - self.assertTrue(fut.cb_added) - - res = object() - fut.set_result(res) - test_utils.run_briefly(self.loop) - self.assertIs(res, result) - self.assertTrue(t.done()) - self.assertIsNone(t.result()) - - def test_baseexception_during_cancel(self): - - def gen(): - when = yield - self.assertAlmostEqual(10.0, when) - yield 0 - - loop = self.new_test_loop(gen) - - async def sleeper(): - await asyncio.sleep(10) - - base_exc = SystemExit() - - async def notmutch(): - try: - await sleeper() - except asyncio.CancelledError: - raise base_exc - - task = self.new_task(loop, notmutch()) - test_utils.run_briefly(loop) - - task.cancel() - self.assertFalse(task.done()) - - self.assertRaises(SystemExit, test_utils.run_briefly, loop) - - self.assertTrue(task.done()) - self.assertFalse(task.cancelled()) - self.assertIs(task.exception(), base_exc) - - def test_iscoroutinefunction(self): - def fn(): - pass - - self.assertFalse(asyncio.iscoroutinefunction(fn)) - - def fn1(): - yield - self.assertFalse(asyncio.iscoroutinefunction(fn1)) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def fn2(): - yield - self.assertTrue(asyncio.iscoroutinefunction(fn2)) - - self.assertFalse(asyncio.iscoroutinefunction(mock.Mock())) - - def test_yield_vs_yield_from(self): - fut = self.new_future(self.loop) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def wait_for_future(): - yield fut - - task = wait_for_future() - with self.assertRaises(RuntimeError): - self.loop.run_until_complete(task) - - self.assertFalse(fut.done()) - - def test_yield_vs_yield_from_generator(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - yield - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def wait_for_future(): - gen = coro() - try: - yield gen - finally: - gen.close() - - task = wait_for_future() - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, task) - - def test_coroutine_non_gen_function(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def func(): - return 'test' - - self.assertTrue(asyncio.iscoroutinefunction(func)) - - coro = func() - self.assertTrue(asyncio.iscoroutine(coro)) - - res = self.loop.run_until_complete(coro) - self.assertEqual(res, 'test') - - def test_coroutine_non_gen_function_return_future(self): - fut = self.new_future(self.loop) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def func(): - return fut - - async def coro(): - fut.set_result('test') - - t1 = self.new_task(self.loop, func()) - t2 = self.new_task(self.loop, coro()) - res = self.loop.run_until_complete(t1) - self.assertEqual(res, 'test') - self.assertIsNone(t2.result()) - - - def test_current_task_deprecated(self): - Task = self.__class__.Task - - with self.assertWarns(DeprecationWarning): - self.assertIsNone(Task.current_task(loop=self.loop)) - - async def coro(loop): - with self.assertWarns(DeprecationWarning): - self.assertIs(Task.current_task(loop=loop), task) - - # See http://bugs.python.org/issue29271 for details: - asyncio.set_event_loop(loop) - try: - with self.assertWarns(DeprecationWarning): - self.assertIs(Task.current_task(None), task) - with self.assertWarns(DeprecationWarning): - self.assertIs(Task.current_task(), task) - finally: - asyncio.set_event_loop(None) - - task = self.new_task(self.loop, coro(self.loop)) - self.loop.run_until_complete(task) - with self.assertWarns(DeprecationWarning): - self.assertIsNone(Task.current_task(loop=self.loop)) - - def test_current_task(self): - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - async def coro(loop): - self.assertIs(asyncio.current_task(loop=loop), task) - - self.assertIs(asyncio.current_task(None), task) - self.assertIs(asyncio.current_task(), task) - - task = self.new_task(self.loop, coro(self.loop)) - self.loop.run_until_complete(task) - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - def test_current_task_with_interleaving_tasks(self): - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - fut1 = self.new_future(self.loop) - fut2 = self.new_future(self.loop) - - async def coro1(loop): - self.assertTrue(asyncio.current_task(loop=loop) is task1) - await fut1 - self.assertTrue(asyncio.current_task(loop=loop) is task1) - fut2.set_result(True) - - async def coro2(loop): - self.assertTrue(asyncio.current_task(loop=loop) is task2) - fut1.set_result(True) - await fut2 - self.assertTrue(asyncio.current_task(loop=loop) is task2) - - task1 = self.new_task(self.loop, coro1(self.loop)) - task2 = self.new_task(self.loop, coro2(self.loop)) - - self.loop.run_until_complete(asyncio.wait((task1, task2))) - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - # Some thorough tests for cancellation propagation through - # coroutines, tasks and wait(). - - def test_yield_future_passes_cancel(self): - # Cancelling outer() cancels inner() cancels waiter. - proof = 0 - waiter = self.new_future(self.loop) - - async def inner(): - nonlocal proof - try: - await waiter - except asyncio.CancelledError: - proof += 1 - raise - else: - self.fail('got past sleep() in inner()') - - async def outer(): - nonlocal proof - try: - await inner() - except asyncio.CancelledError: - proof += 100 # Expect this path. - else: - proof += 10 - - f = asyncio.ensure_future(outer(), loop=self.loop) - test_utils.run_briefly(self.loop) - f.cancel() - self.loop.run_until_complete(f) - self.assertEqual(proof, 101) - self.assertTrue(waiter.cancelled()) - - def test_yield_wait_does_not_shield_cancel(self): - # Cancelling outer() makes wait() return early, leaves inner() - # running. - proof = 0 - waiter = self.new_future(self.loop) - - async def inner(): - nonlocal proof - await waiter - proof += 1 - - async def outer(): - nonlocal proof - d, p = await asyncio.wait([inner()]) - proof += 100 - - f = asyncio.ensure_future(outer(), loop=self.loop) - test_utils.run_briefly(self.loop) - f.cancel() - self.assertRaises( - asyncio.CancelledError, self.loop.run_until_complete, f) - waiter.set_result(None) - test_utils.run_briefly(self.loop) - self.assertEqual(proof, 1) - - def test_shield_result(self): - inner = self.new_future(self.loop) - outer = asyncio.shield(inner) - inner.set_result(42) - res = self.loop.run_until_complete(outer) - self.assertEqual(res, 42) - - def test_shield_exception(self): - inner = self.new_future(self.loop) - outer = asyncio.shield(inner) - test_utils.run_briefly(self.loop) - exc = RuntimeError('expected') - inner.set_exception(exc) - test_utils.run_briefly(self.loop) - self.assertIs(outer.exception(), exc) - - def test_shield_cancel_inner(self): - inner = self.new_future(self.loop) - outer = asyncio.shield(inner) - test_utils.run_briefly(self.loop) - inner.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(outer.cancelled()) - - def test_shield_cancel_outer(self): - inner = self.new_future(self.loop) - outer = asyncio.shield(inner) - test_utils.run_briefly(self.loop) - outer.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(outer.cancelled()) - self.assertEqual(0, 0 if outer._callbacks is None else len(outer._callbacks)) - - def test_shield_shortcut(self): - fut = self.new_future(self.loop) - fut.set_result(42) - res = self.loop.run_until_complete(asyncio.shield(fut)) - self.assertEqual(res, 42) - - def test_shield_effect(self): - # Cancelling outer() does not affect inner(). - proof = 0 - waiter = self.new_future(self.loop) - - async def inner(): - nonlocal proof - await waiter - proof += 1 - - async def outer(): - nonlocal proof - await asyncio.shield(inner()) - proof += 100 - - f = asyncio.ensure_future(outer(), loop=self.loop) - test_utils.run_briefly(self.loop) - f.cancel() - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(f) - waiter.set_result(None) - test_utils.run_briefly(self.loop) - self.assertEqual(proof, 1) - - def test_shield_gather(self): - child1 = self.new_future(self.loop) - child2 = self.new_future(self.loop) - parent = asyncio.gather(child1, child2) - outer = asyncio.shield(parent) - test_utils.run_briefly(self.loop) - outer.cancel() - test_utils.run_briefly(self.loop) - self.assertTrue(outer.cancelled()) - child1.set_result(1) - child2.set_result(2) - test_utils.run_briefly(self.loop) - self.assertEqual(parent.result(), [1, 2]) - - def test_gather_shield(self): - child1 = self.new_future(self.loop) - child2 = self.new_future(self.loop) - inner1 = asyncio.shield(child1) - inner2 = asyncio.shield(child2) - parent = asyncio.gather(inner1, inner2) - test_utils.run_briefly(self.loop) - parent.cancel() - # This should cancel inner1 and inner2 but bot child1 and child2. - test_utils.run_briefly(self.loop) - self.assertIsInstance(parent.exception(), asyncio.CancelledError) - self.assertTrue(inner1.cancelled()) - self.assertTrue(inner2.cancelled()) - child1.set_result(1) - child2.set_result(2) - test_utils.run_briefly(self.loop) - - def test_as_completed_invalid_args(self): - fut = self.new_future(self.loop) - - # as_completed() expects a list of futures, not a future instance - self.assertRaises(TypeError, self.loop.run_until_complete, - asyncio.as_completed(fut, loop=self.loop)) - coro = coroutine_function() - self.assertRaises(TypeError, self.loop.run_until_complete, - asyncio.as_completed(coro, loop=self.loop)) - coro.close() - - def test_wait_invalid_args(self): - fut = self.new_future(self.loop) - - # wait() expects a list of futures, not a future instance - self.assertRaises(TypeError, self.loop.run_until_complete, - asyncio.wait(fut)) - coro = coroutine_function() - self.assertRaises(TypeError, self.loop.run_until_complete, - asyncio.wait(coro)) - coro.close() - - # wait() expects at least a future - self.assertRaises(ValueError, self.loop.run_until_complete, - asyncio.wait([])) - - def test_corowrapper_mocks_generator(self): - - def check(): - # A function that asserts various things. - # Called twice, with different debug flag values. - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - # The actual coroutine. - self.assertTrue(gen.gi_running) - yield from fut - - # A completed Future used to run the coroutine. - fut = self.new_future(self.loop) - fut.set_result(None) - - # Call the coroutine. - gen = coro() - - # Check some properties. - self.assertTrue(asyncio.iscoroutine(gen)) - self.assertIsInstance(gen.gi_frame, types.FrameType) - self.assertFalse(gen.gi_running) - self.assertIsInstance(gen.gi_code, types.CodeType) - - # Run it. - self.loop.run_until_complete(gen) - - # The frame should have changed. - self.assertIsNone(gen.gi_frame) - - # Test with debug flag cleared. - with set_coroutine_debug(False): - check() - - # Test with debug flag set. - with set_coroutine_debug(True): - check() - - def test_yield_from_corowrapper(self): - with set_coroutine_debug(True): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def t1(): - return (yield from t2()) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def t2(): - f = self.new_future(self.loop) - self.new_task(self.loop, t3(f)) - return (yield from f) - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def t3(f): - f.set_result((1, 2, 3)) - - task = self.new_task(self.loop, t1()) - val = self.loop.run_until_complete(task) - self.assertEqual(val, (1, 2, 3)) - - def test_yield_from_corowrapper_send(self): - def foo(): - a = yield - return a - - def call(arg): - cw = asyncio.coroutines.CoroWrapper(foo()) - cw.send(None) - try: - cw.send(arg) - except StopIteration as ex: - return ex.args[0] - else: - raise AssertionError('StopIteration was expected') - - self.assertEqual(call((1, 2)), (1, 2)) - self.assertEqual(call('spam'), 'spam') - - def test_corowrapper_weakref(self): - wd = weakref.WeakValueDictionary() - def foo(): yield from [] - cw = asyncio.coroutines.CoroWrapper(foo()) - wd['cw'] = cw # Would fail without __weakref__ slot. - cw.gen = None # Suppress warning from __del__. - - def test_corowrapper_throw(self): - # Issue 429: CoroWrapper.throw must be compatible with gen.throw - def foo(): - value = None - while True: - try: - value = yield value - except Exception as e: - value = e - - exception = Exception("foo") - cw = asyncio.coroutines.CoroWrapper(foo()) - cw.send(None) - self.assertIs(exception, cw.throw(exception)) - - cw = asyncio.coroutines.CoroWrapper(foo()) - cw.send(None) - self.assertIs(exception, cw.throw(Exception, exception)) - - cw = asyncio.coroutines.CoroWrapper(foo()) - cw.send(None) - exception = cw.throw(Exception, "foo") - self.assertIsInstance(exception, Exception) - self.assertEqual(exception.args, ("foo", )) - - cw = asyncio.coroutines.CoroWrapper(foo()) - cw.send(None) - exception = cw.throw(Exception, "foo", None) - self.assertIsInstance(exception, Exception) - self.assertEqual(exception.args, ("foo", )) - - def test_all_tasks_deprecated(self): - Task = self.__class__.Task - - async def coro(): - with self.assertWarns(DeprecationWarning): - assert Task.all_tasks(self.loop) == {t} - - t = self.new_task(self.loop, coro()) - self.loop.run_until_complete(t) - - def test_log_destroyed_pending_task(self): - Task = self.__class__.Task - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def kill_me(loop): - future = self.new_future(loop) - yield from future - # at this point, the only reference to kill_me() task is - # the Task._wakeup() method in future._callbacks - raise Exception("code never reached") - - mock_handler = mock.Mock() - self.loop.set_debug(True) - self.loop.set_exception_handler(mock_handler) - - # schedule the task - coro = kill_me(self.loop) - task = asyncio.ensure_future(coro, loop=self.loop) - - self.assertEqual(asyncio.all_tasks(loop=self.loop), {task}) - - # See http://bugs.python.org/issue29271 for details: - asyncio.set_event_loop(self.loop) - try: - with self.assertWarns(DeprecationWarning): - self.assertEqual(Task.all_tasks(), {task}) - with self.assertWarns(DeprecationWarning): - self.assertEqual(Task.all_tasks(None), {task}) - finally: - asyncio.set_event_loop(None) - - # execute the task so it waits for future - self.loop._run_once() - self.assertEqual(len(self.loop._ready), 0) - - # remove the future used in kill_me(), and references to the task - del coro.gi_frame.f_locals['future'] - coro = None - source_traceback = task._source_traceback - task = None - - # no more reference to kill_me() task: the task is destroyed by the GC - support.gc_collect() - - self.assertEqual(asyncio.all_tasks(loop=self.loop), set()) - - mock_handler.assert_called_with(self.loop, { - 'message': 'Task was destroyed but it is pending!', - 'task': mock.ANY, - 'source_traceback': source_traceback, - }) - mock_handler.reset_mock() - - @mock.patch('asyncio.base_events.logger') - def test_tb_logger_not_called_after_cancel(self, m_log): - loop = asyncio.new_event_loop() - self.set_event_loop(loop) - - async def coro(): - raise TypeError - - async def runner(): - task = self.new_task(loop, coro()) - await asyncio.sleep(0.05) - task.cancel() - task = None - - loop.run_until_complete(runner()) - self.assertFalse(m_log.error.called) - - @mock.patch('asyncio.coroutines.logger') - def test_coroutine_never_yielded(self, m_log): - with set_coroutine_debug(True): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro_noop(): - pass - - tb_filename = __file__ - tb_lineno = sys._getframe().f_lineno + 2 - # create a coroutine object but don't use it - coro_noop() - support.gc_collect() - - self.assertTrue(m_log.error.called) - message = m_log.error.call_args[0][0] - func_filename, func_lineno = test_utils.get_function_source(coro_noop) - - regex = (r'^<CoroWrapper %s\(?\)? .* at %s:%s, .*> ' - r'was never yielded from\n' - r'Coroutine object created at \(most recent call last, truncated to \d+ last lines\):\n' - r'.*\n' - r' File "%s", line %s, in test_coroutine_never_yielded\n' - r' coro_noop\(\)$' - % (re.escape(coro_noop.__qualname__), - re.escape(func_filename), func_lineno, - re.escape(tb_filename), tb_lineno)) - - self.assertRegex(message, re.compile(regex, re.DOTALL)) - - def test_return_coroutine_from_coroutine(self): - """Return of @asyncio.coroutine()-wrapped function generator object - from @asyncio.coroutine()-wrapped function should have same effect as - returning generator object or Future.""" - def check(): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def outer_coro(): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def inner_coro(): - return 1 - - return inner_coro() - - result = self.loop.run_until_complete(outer_coro()) - self.assertEqual(result, 1) - - # Test with debug flag cleared. - with set_coroutine_debug(False): - check() - - # Test with debug flag set. - with set_coroutine_debug(True): - check() - - def test_task_source_traceback(self): - self.loop.set_debug(True) - - task = self.new_task(self.loop, coroutine_function()) - lineno = sys._getframe().f_lineno - 1 - self.assertIsInstance(task._source_traceback, list) - self.assertEqual(task._source_traceback[-2][:3], - (__file__, - lineno, - 'test_task_source_traceback')) - self.loop.run_until_complete(task) - - def _test_cancel_wait_for(self, timeout): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def blocking_coroutine(): - fut = self.new_future(loop) - # Block: fut result is never set - await fut - - task = loop.create_task(blocking_coroutine()) - - wait = loop.create_task(asyncio.wait_for(task, timeout)) - loop.call_soon(wait.cancel) - - self.assertRaises(asyncio.CancelledError, - loop.run_until_complete, wait) - - # Python issue #23219: cancelling the wait must also cancel the task - self.assertTrue(task.cancelled()) - - def test_cancel_blocking_wait_for(self): - self._test_cancel_wait_for(None) - - def test_cancel_wait_for(self): - self._test_cancel_wait_for(60.0) - - def test_cancel_gather_1(self): - """Ensure that a gathering future refuses to be cancelled once all - children are done""" - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - fut = self.new_future(loop) - # The indirection fut->child_coro is needed since otherwise the - # gathering task is done at the same time as the child future - def child_coro(): - return (yield from fut) - gather_future = asyncio.gather(child_coro(), loop=loop) - gather_task = asyncio.ensure_future(gather_future, loop=loop) - - cancel_result = None - def cancelling_callback(_): - nonlocal cancel_result - cancel_result = gather_task.cancel() - fut.add_done_callback(cancelling_callback) - - fut.set_result(42) # calls the cancelling_callback after fut is done() - - # At this point the task should complete. - loop.run_until_complete(gather_task) - - # Python issue #26923: asyncio.gather drops cancellation - self.assertEqual(cancel_result, False) - self.assertFalse(gather_task.cancelled()) - self.assertEqual(gather_task.result(), [42]) - - def test_cancel_gather_2(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def test(): - time = 0 - while True: - time += 0.05 - await asyncio.gather(asyncio.sleep(0.05), - return_exceptions=True, - loop=loop) - if time > 1: - return - - async def main(): - qwe = self.new_task(loop, test()) - await asyncio.sleep(0.2) - qwe.cancel() - try: - await qwe - except asyncio.CancelledError: - pass - else: - self.fail('gather did not propagate the cancellation request') - - loop.run_until_complete(main()) - - def test_exception_traceback(self): - # See http://bugs.python.org/issue28843 - - async def foo(): - 1 / 0 - - async def main(): - task = self.new_task(self.loop, foo()) - await asyncio.sleep(0) # skip one loop iteration - self.assertIsNotNone(task.exception().__traceback__) - - self.loop.run_until_complete(main()) - - @mock.patch('asyncio.base_events.logger') - def test_error_in_call_soon(self, m_log): - def call_soon(callback, *args, **kwargs): - raise ValueError - self.loop.call_soon = call_soon - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - pass - - self.assertFalse(m_log.error.called) - - with self.assertRaises(ValueError): - gen = coro() - try: - self.new_task(self.loop, gen) - finally: - gen.close() - - self.assertTrue(m_log.error.called) - message = m_log.error.call_args[0][0] - self.assertIn('Task was destroyed but it is pending', message) - - self.assertEqual(asyncio.all_tasks(self.loop), set()) - - def test_create_task_with_noncoroutine(self): - with self.assertRaisesRegex(TypeError, - "a coroutine was expected, got 123"): - self.new_task(self.loop, 123) - - # test it for the second time to ensure that caching - # in asyncio.iscoroutine() doesn't break things. - with self.assertRaisesRegex(TypeError, - "a coroutine was expected, got 123"): - self.new_task(self.loop, 123) - - def test_create_task_with_oldstyle_coroutine(self): - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - pass - - task = self.new_task(self.loop, coro()) - self.assertIsInstance(task, self.Task) - self.loop.run_until_complete(task) - - # test it for the second time to ensure that caching - # in asyncio.iscoroutine() doesn't break things. - task = self.new_task(self.loop, coro()) - self.assertIsInstance(task, self.Task) - self.loop.run_until_complete(task) - - def test_create_task_with_async_function(self): - - async def coro(): - pass - - task = self.new_task(self.loop, coro()) - self.assertIsInstance(task, self.Task) - self.loop.run_until_complete(task) - - # test it for the second time to ensure that caching - # in asyncio.iscoroutine() doesn't break things. - task = self.new_task(self.loop, coro()) - self.assertIsInstance(task, self.Task) - self.loop.run_until_complete(task) - - def test_create_task_with_asynclike_function(self): - task = self.new_task(self.loop, CoroLikeObject()) - self.assertIsInstance(task, self.Task) - self.assertEqual(self.loop.run_until_complete(task), 42) - - # test it for the second time to ensure that caching - # in asyncio.iscoroutine() doesn't break things. - task = self.new_task(self.loop, CoroLikeObject()) - self.assertIsInstance(task, self.Task) - self.assertEqual(self.loop.run_until_complete(task), 42) - - def test_bare_create_task(self): - - async def inner(): - return 1 - - async def coro(): - task = asyncio.create_task(inner()) - self.assertIsInstance(task, self.Task) - ret = await task - self.assertEqual(1, ret) - - self.loop.run_until_complete(coro()) - - def test_bare_create_named_task(self): - - async def coro_noop(): - pass - - async def coro(): - task = asyncio.create_task(coro_noop(), name='No-op') - self.assertEqual(task.get_name(), 'No-op') - await task - - self.loop.run_until_complete(coro()) - - def test_context_1(self): - cvar = contextvars.ContextVar('cvar', default='nope') - - async def sub(): - await asyncio.sleep(0.01) - self.assertEqual(cvar.get(), 'nope') - cvar.set('something else') - - async def main(): - self.assertEqual(cvar.get(), 'nope') - subtask = self.new_task(loop, sub()) - cvar.set('yes') - self.assertEqual(cvar.get(), 'yes') - await subtask - self.assertEqual(cvar.get(), 'yes') - - loop = asyncio.new_event_loop() - try: - task = self.new_task(loop, main()) - loop.run_until_complete(task) - finally: - loop.close() - - def test_context_2(self): - cvar = contextvars.ContextVar('cvar', default='nope') - - async def main(): - def fut_on_done(fut): - # This change must not pollute the context - # of the "main()" task. - cvar.set('something else') - - self.assertEqual(cvar.get(), 'nope') - - for j in range(2): - fut = self.new_future(loop) - fut.add_done_callback(fut_on_done) - cvar.set(f'yes{j}') - loop.call_soon(fut.set_result, None) - await fut - self.assertEqual(cvar.get(), f'yes{j}') - - for i in range(3): - # Test that task passed its context to add_done_callback: - cvar.set(f'yes{i}-{j}') - await asyncio.sleep(0.001) - self.assertEqual(cvar.get(), f'yes{i}-{j}') - - loop = asyncio.new_event_loop() - try: - task = self.new_task(loop, main()) - loop.run_until_complete(task) - finally: - loop.close() - - self.assertEqual(cvar.get(), 'nope') - - def test_context_3(self): - # Run 100 Tasks in parallel, each modifying cvar. - - cvar = contextvars.ContextVar('cvar', default=-1) - - async def sub(num): - for i in range(10): - cvar.set(num + i) - await asyncio.sleep(random.uniform(0.001, 0.05)) - self.assertEqual(cvar.get(), num + i) - - async def main(): - tasks = [] - for i in range(100): - task = loop.create_task(sub(random.randint(0, 10))) - tasks.append(task) - - await asyncio.gather(*tasks, loop=loop) - - loop = asyncio.new_event_loop() - try: - loop.run_until_complete(main()) - finally: - loop.close() - - self.assertEqual(cvar.get(), -1) - - def test_get_coro(self): - loop = asyncio.new_event_loop() - coro = coroutine_function() - try: - task = self.new_task(loop, coro) - loop.run_until_complete(task) - self.assertIs(task.get_coro(), coro) - finally: - loop.close() - - -def add_subclass_tests(cls): - BaseTask = cls.Task - BaseFuture = cls.Future - - if BaseTask is None or BaseFuture is None: - return cls - - class CommonFuture: - def __init__(self, *args, **kwargs): - self.calls = collections.defaultdict(lambda: 0) - super().__init__(*args, **kwargs) - - def add_done_callback(self, *args, **kwargs): - self.calls['add_done_callback'] += 1 - return super().add_done_callback(*args, **kwargs) - - class Task(CommonFuture, BaseTask): - pass - - class Future(CommonFuture, BaseFuture): - pass - - def test_subclasses_ctask_cfuture(self): - fut = self.Future(loop=self.loop) - - async def func(): - self.loop.call_soon(lambda: fut.set_result('spam')) - return await fut - - task = self.Task(func(), loop=self.loop) - - result = self.loop.run_until_complete(task) - - self.assertEqual(result, 'spam') - - self.assertEqual( - dict(task.calls), - {'add_done_callback': 1}) - - self.assertEqual( - dict(fut.calls), - {'add_done_callback': 1}) - - # Add patched Task & Future back to the test case - cls.Task = Task - cls.Future = Future - - # Add an extra unit-test - cls.test_subclasses_ctask_cfuture = test_subclasses_ctask_cfuture - - # Disable the "test_task_source_traceback" test - # (the test is hardcoded for a particular call stack, which - # is slightly different for Task subclasses) - cls.test_task_source_traceback = None - - return cls - - -class SetMethodsTest: - - def test_set_result_causes_invalid_state(self): - Future = type(self).Future - self.loop.call_exception_handler = exc_handler = mock.Mock() - - async def foo(): - await asyncio.sleep(0.1) - return 10 - - coro = foo() - task = self.new_task(self.loop, coro) - Future.set_result(task, 'spam') - - self.assertEqual( - self.loop.run_until_complete(task), - 'spam') - - exc_handler.assert_called_once() - exc = exc_handler.call_args[0][0]['exception'] - with self.assertRaisesRegex(asyncio.InvalidStateError, - r'step\(\): already done'): - raise exc - - coro.close() - - def test_set_exception_causes_invalid_state(self): - class MyExc(Exception): - pass - - Future = type(self).Future - self.loop.call_exception_handler = exc_handler = mock.Mock() - - async def foo(): - await asyncio.sleep(0.1) - return 10 - - coro = foo() - task = self.new_task(self.loop, coro) - Future.set_exception(task, MyExc()) - - with self.assertRaises(MyExc): - self.loop.run_until_complete(task) - - exc_handler.assert_called_once() - exc = exc_handler.call_args[0][0]['exception'] - with self.assertRaisesRegex(asyncio.InvalidStateError, - r'step\(\): already done'): - raise exc - - coro.close() - - -@unittest.skipUnless(hasattr(futures, '_CFuture') and - hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest, - test_utils.TestCase): - - Task = getattr(tasks, '_CTask', None) - Future = getattr(futures, '_CFuture', None) - - @support.refcount_test - def test_refleaks_in_task___init__(self): - gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') - async def coro(): - pass - task = self.new_task(self.loop, coro()) - self.loop.run_until_complete(task) - refs_before = gettotalrefcount() - for i in range(100): - task.__init__(coro(), loop=self.loop) - self.loop.run_until_complete(task) - self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) - - def test_del__log_destroy_pending_segfault(self): - async def coro(): - pass - task = self.new_task(self.loop, coro()) - self.loop.run_until_complete(task) - with self.assertRaises(AttributeError): - del task._log_destroy_pending - - -@unittest.skipUnless(hasattr(futures, '_CFuture') and - hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -@add_subclass_tests -class CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - - Task = getattr(tasks, '_CTask', None) - Future = getattr(futures, '_CFuture', None) - - -@unittest.skipUnless(hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -@add_subclass_tests -class CTaskSubclass_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): - - Task = getattr(tasks, '_CTask', None) - Future = futures._PyFuture - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -@add_subclass_tests -class PyTask_CFutureSubclass_Tests(BaseTaskTests, test_utils.TestCase): - - Future = getattr(futures, '_CFuture', None) - Task = tasks._PyTask - - -@unittest.skipUnless(hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase): - - Task = getattr(tasks, '_CTask', None) - Future = futures._PyFuture - - -@unittest.skipUnless(hasattr(futures, '_CFuture'), - 'requires the C _asyncio module') -class PyTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): - - Task = tasks._PyTask - Future = getattr(futures, '_CFuture', None) - - -class PyTask_PyFuture_Tests(BaseTaskTests, SetMethodsTest, - test_utils.TestCase): - - Task = tasks._PyTask - Future = futures._PyFuture - - -@add_subclass_tests -class PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase): - Task = tasks._PyTask - Future = futures._PyFuture - - -@unittest.skipUnless(hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -class CTask_Future_Tests(test_utils.TestCase): - - def test_foobar(self): - class Fut(asyncio.Future): - @property - def get_loop(self): - raise AttributeError - - async def coro(): - await fut - return 'spam' - - self.loop = asyncio.new_event_loop() - try: - fut = Fut(loop=self.loop) - self.loop.call_later(0.1, fut.set_result, 1) - task = self.loop.create_task(coro()) - res = self.loop.run_until_complete(task) - finally: - self.loop.close() - - self.assertEqual(res, 'spam') - - -class BaseTaskIntrospectionTests: - _register_task = None - _unregister_task = None - _enter_task = None - _leave_task = None - - def test__register_task_1(self): - class TaskLike: - @property - def _loop(self): - return loop - - def done(self): - return False - - task = TaskLike() - loop = mock.Mock() - - self.assertEqual(asyncio.all_tasks(loop), set()) - self._register_task(task) - self.assertEqual(asyncio.all_tasks(loop), {task}) - self._unregister_task(task) - - def test__register_task_2(self): - class TaskLike: - def get_loop(self): - return loop - - def done(self): - return False - - task = TaskLike() - loop = mock.Mock() - - self.assertEqual(asyncio.all_tasks(loop), set()) - self._register_task(task) - self.assertEqual(asyncio.all_tasks(loop), {task}) - self._unregister_task(task) - - def test__register_task_3(self): - class TaskLike: - def get_loop(self): - return loop - - def done(self): - return True - - task = TaskLike() - loop = mock.Mock() - - self.assertEqual(asyncio.all_tasks(loop), set()) - self._register_task(task) - self.assertEqual(asyncio.all_tasks(loop), set()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(asyncio.Task.all_tasks(loop), {task}) - self._unregister_task(task) - - def test__enter_task(self): - task = mock.Mock() - loop = mock.Mock() - self.assertIsNone(asyncio.current_task(loop)) - self._enter_task(loop, task) - self.assertIs(asyncio.current_task(loop), task) - self._leave_task(loop, task) - - def test__enter_task_failure(self): - task1 = mock.Mock() - task2 = mock.Mock() - loop = mock.Mock() - self._enter_task(loop, task1) - with self.assertRaises(RuntimeError): - self._enter_task(loop, task2) - self.assertIs(asyncio.current_task(loop), task1) - self._leave_task(loop, task1) - - def test__leave_task(self): - task = mock.Mock() - loop = mock.Mock() - self._enter_task(loop, task) - self._leave_task(loop, task) - self.assertIsNone(asyncio.current_task(loop)) - - def test__leave_task_failure1(self): - task1 = mock.Mock() - task2 = mock.Mock() - loop = mock.Mock() - self._enter_task(loop, task1) - with self.assertRaises(RuntimeError): - self._leave_task(loop, task2) - self.assertIs(asyncio.current_task(loop), task1) - self._leave_task(loop, task1) - - def test__leave_task_failure2(self): - task = mock.Mock() - loop = mock.Mock() - with self.assertRaises(RuntimeError): - self._leave_task(loop, task) - self.assertIsNone(asyncio.current_task(loop)) - - def test__unregister_task(self): - task = mock.Mock() - loop = mock.Mock() - task.get_loop = lambda: loop - self._register_task(task) - self._unregister_task(task) - self.assertEqual(asyncio.all_tasks(loop), set()) - - def test__unregister_task_not_registered(self): - task = mock.Mock() - loop = mock.Mock() - self._unregister_task(task) - self.assertEqual(asyncio.all_tasks(loop), set()) - - -class PyIntrospectionTests(test_utils.TestCase, BaseTaskIntrospectionTests): - _register_task = staticmethod(tasks._py_register_task) - _unregister_task = staticmethod(tasks._py_unregister_task) - _enter_task = staticmethod(tasks._py_enter_task) - _leave_task = staticmethod(tasks._py_leave_task) - - -@unittest.skipUnless(hasattr(tasks, '_c_register_task'), - 'requires the C _asyncio module') -class CIntrospectionTests(test_utils.TestCase, BaseTaskIntrospectionTests): - if hasattr(tasks, '_c_register_task'): - _register_task = staticmethod(tasks._c_register_task) - _unregister_task = staticmethod(tasks._c_unregister_task) - _enter_task = staticmethod(tasks._c_enter_task) - _leave_task = staticmethod(tasks._c_leave_task) - else: - _register_task = _unregister_task = _enter_task = _leave_task = None - - -class BaseCurrentLoopTests: - - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def new_task(self, coro): - raise NotImplementedError - - def test_current_task_no_running_loop(self): - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - def test_current_task_no_running_loop_implicit(self): - with self.assertRaises(RuntimeError): - asyncio.current_task() - - def test_current_task_with_implicit_loop(self): - async def coro(): - self.assertIs(asyncio.current_task(loop=self.loop), task) - - self.assertIs(asyncio.current_task(None), task) - self.assertIs(asyncio.current_task(), task) - - task = self.new_task(coro()) - self.loop.run_until_complete(task) - self.assertIsNone(asyncio.current_task(loop=self.loop)) - - -class PyCurrentLoopTests(BaseCurrentLoopTests, test_utils.TestCase): - - def new_task(self, coro): - return tasks._PyTask(coro, loop=self.loop) - - -@unittest.skipUnless(hasattr(tasks, '_CTask'), - 'requires the C _asyncio module') -class CCurrentLoopTests(BaseCurrentLoopTests, test_utils.TestCase): - - def new_task(self, coro): - return getattr(tasks, '_CTask')(coro, loop=self.loop) - - -class GenericTaskTests(test_utils.TestCase): - - def test_future_subclass(self): - self.assertTrue(issubclass(asyncio.Task, asyncio.Future)) - - def test_asyncio_module_compiled(self): - # Because of circular imports it's easy to make _asyncio - # module non-importable. This is a simple test that will - # fail on systems where C modules were successfully compiled - # (hence the test for _functools), but _asyncio somehow didn't. - try: - import _functools - except ImportError: - pass - else: - try: - import _asyncio - except ImportError: - self.fail('_asyncio module is missing') - - -class GatherTestsBase: - - def setUp(self): - super().setUp() - self.one_loop = self.new_test_loop() - self.other_loop = self.new_test_loop() - self.set_event_loop(self.one_loop, cleanup=False) - - def _run_loop(self, loop): - while loop._ready: - test_utils.run_briefly(loop) - - def _check_success(self, **kwargs): - a, b, c = [self.one_loop.create_future() for i in range(3)] - fut = asyncio.gather(*self.wrap_futures(a, b, c), **kwargs) - cb = test_utils.MockCallback() - fut.add_done_callback(cb) - b.set_result(1) - a.set_result(2) - self._run_loop(self.one_loop) - self.assertEqual(cb.called, False) - self.assertFalse(fut.done()) - c.set_result(3) - self._run_loop(self.one_loop) - cb.assert_called_once_with(fut) - self.assertEqual(fut.result(), [2, 1, 3]) - - def test_success(self): - self._check_success() - self._check_success(return_exceptions=False) - - def test_result_exception_success(self): - self._check_success(return_exceptions=True) - - def test_one_exception(self): - a, b, c, d, e = [self.one_loop.create_future() for i in range(5)] - fut = asyncio.gather(*self.wrap_futures(a, b, c, d, e)) - cb = test_utils.MockCallback() - fut.add_done_callback(cb) - exc = ZeroDivisionError() - a.set_result(1) - b.set_exception(exc) - self._run_loop(self.one_loop) - self.assertTrue(fut.done()) - cb.assert_called_once_with(fut) - self.assertIs(fut.exception(), exc) - # Does nothing - c.set_result(3) - d.cancel() - e.set_exception(RuntimeError()) - e.exception() - - def test_return_exceptions(self): - a, b, c, d = [self.one_loop.create_future() for i in range(4)] - fut = asyncio.gather(*self.wrap_futures(a, b, c, d), - return_exceptions=True) - cb = test_utils.MockCallback() - fut.add_done_callback(cb) - exc = ZeroDivisionError() - exc2 = RuntimeError() - b.set_result(1) - c.set_exception(exc) - a.set_result(3) - self._run_loop(self.one_loop) - self.assertFalse(fut.done()) - d.set_exception(exc2) - self._run_loop(self.one_loop) - self.assertTrue(fut.done()) - cb.assert_called_once_with(fut) - self.assertEqual(fut.result(), [3, 1, exc, exc2]) - - def test_env_var_debug(self): - code = '\n'.join(( - 'import asyncio.coroutines', - 'print(asyncio.coroutines._DEBUG)')) - - # Test with -E to not fail if the unit test was run with - # PYTHONASYNCIODEBUG set to a non-empty string - sts, stdout, stderr = assert_python_ok('-E', '-c', code) - self.assertEqual(stdout.rstrip(), b'False') - - sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='', - PYTHONDEVMODE='') - self.assertEqual(stdout.rstrip(), b'False') - - sts, stdout, stderr = assert_python_ok('-c', code, - PYTHONASYNCIODEBUG='1', - PYTHONDEVMODE='') - self.assertEqual(stdout.rstrip(), b'True') - - sts, stdout, stderr = assert_python_ok('-E', '-c', code, - PYTHONASYNCIODEBUG='1', - PYTHONDEVMODE='') - self.assertEqual(stdout.rstrip(), b'False') - - # -X dev - sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev', - '-c', code) - self.assertEqual(stdout.rstrip(), b'True') - - -class FutureGatherTests(GatherTestsBase, test_utils.TestCase): - - def wrap_futures(self, *futures): - return futures - - def _check_empty_sequence(self, seq_or_iter): - asyncio.set_event_loop(self.one_loop) - self.addCleanup(asyncio.set_event_loop, None) - fut = asyncio.gather(*seq_or_iter) - self.assertIsInstance(fut, asyncio.Future) - self.assertIs(fut._loop, self.one_loop) - self._run_loop(self.one_loop) - self.assertTrue(fut.done()) - self.assertEqual(fut.result(), []) - with self.assertWarns(DeprecationWarning): - fut = asyncio.gather(*seq_or_iter, loop=self.other_loop) - self.assertIs(fut._loop, self.other_loop) - - def test_constructor_empty_sequence(self): - self._check_empty_sequence([]) - self._check_empty_sequence(()) - self._check_empty_sequence(set()) - self._check_empty_sequence(iter("")) - - def test_constructor_heterogenous_futures(self): - fut1 = self.one_loop.create_future() - fut2 = self.other_loop.create_future() - with self.assertRaises(ValueError): - asyncio.gather(fut1, fut2) - with self.assertRaises(ValueError): - asyncio.gather(fut1, loop=self.other_loop) - - def test_constructor_homogenous_futures(self): - children = [self.other_loop.create_future() for i in range(3)] - fut = asyncio.gather(*children) - self.assertIs(fut._loop, self.other_loop) - self._run_loop(self.other_loop) - self.assertFalse(fut.done()) - fut = asyncio.gather(*children, loop=self.other_loop) - self.assertIs(fut._loop, self.other_loop) - self._run_loop(self.other_loop) - self.assertFalse(fut.done()) - - def test_one_cancellation(self): - a, b, c, d, e = [self.one_loop.create_future() for i in range(5)] - fut = asyncio.gather(a, b, c, d, e) - cb = test_utils.MockCallback() - fut.add_done_callback(cb) - a.set_result(1) - b.cancel() - self._run_loop(self.one_loop) - self.assertTrue(fut.done()) - cb.assert_called_once_with(fut) - self.assertFalse(fut.cancelled()) - self.assertIsInstance(fut.exception(), asyncio.CancelledError) - # Does nothing - c.set_result(3) - d.cancel() - e.set_exception(RuntimeError()) - e.exception() - - def test_result_exception_one_cancellation(self): - a, b, c, d, e, f = [self.one_loop.create_future() - for i in range(6)] - fut = asyncio.gather(a, b, c, d, e, f, return_exceptions=True) - cb = test_utils.MockCallback() - fut.add_done_callback(cb) - a.set_result(1) - zde = ZeroDivisionError() - b.set_exception(zde) - c.cancel() - self._run_loop(self.one_loop) - self.assertFalse(fut.done()) - d.set_result(3) - e.cancel() - rte = RuntimeError() - f.set_exception(rte) - res = self.one_loop.run_until_complete(fut) - self.assertIsInstance(res[2], asyncio.CancelledError) - self.assertIsInstance(res[4], asyncio.CancelledError) - res[2] = res[4] = None - self.assertEqual(res, [1, zde, None, 3, None, rte]) - cb.assert_called_once_with(fut) - - -class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase): - - def setUp(self): - super().setUp() - asyncio.set_event_loop(self.one_loop) - - def wrap_futures(self, *futures): - coros = [] - for fut in futures: - async def coro(fut=fut): - return await fut - coros.append(coro()) - return coros - - def test_constructor_loop_selection(self): - async def coro(): - return 'abc' - gen1 = coro() - gen2 = coro() - fut = asyncio.gather(gen1, gen2) - self.assertIs(fut._loop, self.one_loop) - self.one_loop.run_until_complete(fut) - - self.set_event_loop(self.other_loop, cleanup=False) - gen3 = coro() - gen4 = coro() - fut2 = asyncio.gather(gen3, gen4, loop=self.other_loop) - self.assertIs(fut2._loop, self.other_loop) - self.other_loop.run_until_complete(fut2) - - def test_duplicate_coroutines(self): - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(s): - return s - c = coro('abc') - fut = asyncio.gather(c, c, coro('def'), c, loop=self.one_loop) - self._run_loop(self.one_loop) - self.assertEqual(fut.result(), ['abc', 'abc', 'def', 'abc']) - - def test_cancellation_broadcast(self): - # Cancelling outer() cancels all children. - proof = 0 - waiter = self.one_loop.create_future() - - async def inner(): - nonlocal proof - await waiter - proof += 1 - - child1 = asyncio.ensure_future(inner(), loop=self.one_loop) - child2 = asyncio.ensure_future(inner(), loop=self.one_loop) - gatherer = None - - async def outer(): - nonlocal proof, gatherer - gatherer = asyncio.gather(child1, child2, loop=self.one_loop) - await gatherer - proof += 100 - - f = asyncio.ensure_future(outer(), loop=self.one_loop) - test_utils.run_briefly(self.one_loop) - self.assertTrue(f.cancel()) - with self.assertRaises(asyncio.CancelledError): - self.one_loop.run_until_complete(f) - self.assertFalse(gatherer.cancel()) - self.assertTrue(waiter.cancelled()) - self.assertTrue(child1.cancelled()) - self.assertTrue(child2.cancelled()) - test_utils.run_briefly(self.one_loop) - self.assertEqual(proof, 0) - - def test_exception_marking(self): - # Test for the first line marked "Mark exception retrieved." - - async def inner(f): - await f - raise RuntimeError('should not be ignored') - - a = self.one_loop.create_future() - b = self.one_loop.create_future() - - async def outer(): - await asyncio.gather(inner(a), inner(b), loop=self.one_loop) - - f = asyncio.ensure_future(outer(), loop=self.one_loop) - test_utils.run_briefly(self.one_loop) - a.set_result(None) - test_utils.run_briefly(self.one_loop) - b.set_result(None) - test_utils.run_briefly(self.one_loop) - self.assertIsInstance(f.exception(), RuntimeError) - - -class RunCoroutineThreadsafeTests(test_utils.TestCase): - """Test case for asyncio.run_coroutine_threadsafe.""" - - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) # Will cleanup properly - - async def add(self, a, b, fail=False, cancel=False): - """Wait 0.05 second and return a + b.""" - await asyncio.sleep(0.05) - if fail: - raise RuntimeError("Fail!") - if cancel: - asyncio.current_task(self.loop).cancel() - await asyncio.sleep(0) - return a + b - - def target(self, fail=False, cancel=False, timeout=None, - advance_coro=False): - """Run add coroutine in the event loop.""" - coro = self.add(1, 2, fail=fail, cancel=cancel) - future = asyncio.run_coroutine_threadsafe(coro, self.loop) - if advance_coro: - # this is for test_run_coroutine_threadsafe_task_factory_exception; - # otherwise it spills errors and breaks **other** unittests, since - # 'target' is interacting with threads. - - # With this call, `coro` will be advanced, so that - # CoroWrapper.__del__ won't do anything when asyncio tests run - # in debug mode. - self.loop.call_soon_threadsafe(coro.send, None) - try: - return future.result(timeout) - finally: - future.done() or future.cancel() - - def test_run_coroutine_threadsafe(self): - """Test coroutine submission from a thread to an event loop.""" - future = self.loop.run_in_executor(None, self.target) - result = self.loop.run_until_complete(future) - self.assertEqual(result, 3) - - def test_run_coroutine_threadsafe_with_exception(self): - """Test coroutine submission from a thread to an event loop - when an exception is raised.""" - future = self.loop.run_in_executor(None, self.target, True) - with self.assertRaises(RuntimeError) as exc_context: - self.loop.run_until_complete(future) - self.assertIn("Fail!", exc_context.exception.args) - - def test_run_coroutine_threadsafe_with_timeout(self): - """Test coroutine submission from a thread to an event loop - when a timeout is raised.""" - callback = lambda: self.target(timeout=0) - future = self.loop.run_in_executor(None, callback) - with self.assertRaises(asyncio.TimeoutError): - self.loop.run_until_complete(future) - test_utils.run_briefly(self.loop) - # Check that there's no pending task (add has been cancelled) - for task in asyncio.all_tasks(self.loop): - self.assertTrue(task.done()) - - def test_run_coroutine_threadsafe_task_cancelled(self): - """Test coroutine submission from a tread to an event loop - when the task is cancelled.""" - callback = lambda: self.target(cancel=True) - future = self.loop.run_in_executor(None, callback) - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(future) - - def test_run_coroutine_threadsafe_task_factory_exception(self): - """Test coroutine submission from a tread to an event loop - when the task factory raise an exception.""" - - def task_factory(loop, coro): - raise NameError - - run = self.loop.run_in_executor( - None, lambda: self.target(advance_coro=True)) - - # Set exception handler - callback = test_utils.MockCallback() - self.loop.set_exception_handler(callback) - - # Set corrupted task factory - self.addCleanup(self.loop.set_task_factory, - self.loop.get_task_factory()) - self.loop.set_task_factory(task_factory) - - # Run event loop - with self.assertRaises(NameError) as exc_context: - self.loop.run_until_complete(run) - - # Check exceptions - self.assertEqual(len(callback.call_args_list), 1) - (loop, context), kwargs = callback.call_args - self.assertEqual(context['exception'], exc_context.exception) - - -class SleepTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def tearDown(self): - self.loop.close() - self.loop = None - super().tearDown() - - def test_sleep_zero(self): - result = 0 - - def inc_result(num): - nonlocal result - result += num - - async def coro(): - self.loop.call_soon(inc_result, 1) - self.assertEqual(result, 0) - num = await asyncio.sleep(0, result=10) - self.assertEqual(result, 1) # inc'ed by call_soon - inc_result(num) # num should be 11 - - self.loop.run_until_complete(coro()) - self.assertEqual(result, 11) - - def test_loop_argument_is_deprecated(self): - # Remove test when loop argument is removed in Python 3.10 - with self.assertWarns(DeprecationWarning): - self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop)) - - -class WaitTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def tearDown(self): - self.loop.close() - self.loop = None - super().tearDown() - - def test_loop_argument_is_deprecated_in_wait(self): - # Remove test when loop argument is removed in Python 3.10 - with self.assertWarns(DeprecationWarning): - self.loop.run_until_complete( - asyncio.wait([coroutine_function()], loop=self.loop)) - - def test_loop_argument_is_deprecated_in_wait_for(self): - # Remove test when loop argument is removed in Python 3.10 - with self.assertWarns(DeprecationWarning): - self.loop.run_until_complete( - asyncio.wait_for(coroutine_function(), 0.01, loop=self.loop)) - - -class CompatibilityTests(test_utils.TestCase): - # Tests for checking a bridge between old-styled coroutines - # and async/await syntax - - def setUp(self): - super().setUp() - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - - def tearDown(self): - self.loop.close() - self.loop = None - super().tearDown() - - def test_yield_from_awaitable(self): - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro(): - yield from asyncio.sleep(0) - return 'ok' - - result = self.loop.run_until_complete(coro()) - self.assertEqual('ok', result) - - def test_await_old_style_coro(self): - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro1(): - return 'ok1' - - with self.assertWarns(DeprecationWarning): - @asyncio.coroutine - def coro2(): - yield from asyncio.sleep(0) - return 'ok2' - - async def inner(): - return await asyncio.gather(coro1(), coro2(), loop=self.loop) - - result = self.loop.run_until_complete(inner()) - self.assertEqual(['ok1', 'ok2'], result) - - def test_debug_mode_interop(self): - # https://bugs.python.org/issue32636 - code = textwrap.dedent(""" - import asyncio - - async def native_coro(): - pass - - @asyncio.coroutine - def old_style_coro(): - yield from native_coro() - - asyncio.run(old_style_coro()) - """) - - assert_python_ok("-Wignore::DeprecationWarning", "-c", code, - PYTHONASYNCIODEBUG="1") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_transports.py b/Lib/test/test_asyncio/test_transports.py deleted file mode 100644 index df44855..0000000 --- a/Lib/test/test_asyncio/test_transports.py +++ /dev/null @@ -1,97 +0,0 @@ -"""Tests for transports.py.""" - -import unittest -from unittest import mock - -import asyncio -from asyncio import transports - - -class TransportTests(unittest.TestCase): - - def test_ctor_extra_is_none(self): - transport = asyncio.Transport() - self.assertEqual(transport._extra, {}) - - def test_get_extra_info(self): - transport = asyncio.Transport({'extra': 'info'}) - self.assertEqual('info', transport.get_extra_info('extra')) - self.assertIsNone(transport.get_extra_info('unknown')) - - default = object() - self.assertIs(default, transport.get_extra_info('unknown', default)) - - def test_writelines(self): - writer = mock.Mock() - - class MyTransport(asyncio.Transport): - def write(self, data): - writer(data) - - transport = MyTransport() - - transport.writelines([b'line1', - bytearray(b'line2'), - memoryview(b'line3')]) - self.assertEqual(1, writer.call_count) - writer.assert_called_with(b'line1line2line3') - - def test_not_implemented(self): - transport = asyncio.Transport() - - self.assertRaises(NotImplementedError, - transport.set_write_buffer_limits) - self.assertRaises(NotImplementedError, transport.get_write_buffer_size) - self.assertRaises(NotImplementedError, transport.write, 'data') - self.assertRaises(NotImplementedError, transport.write_eof) - self.assertRaises(NotImplementedError, transport.can_write_eof) - self.assertRaises(NotImplementedError, transport.pause_reading) - self.assertRaises(NotImplementedError, transport.resume_reading) - self.assertRaises(NotImplementedError, transport.is_reading) - self.assertRaises(NotImplementedError, transport.close) - self.assertRaises(NotImplementedError, transport.abort) - - def test_dgram_not_implemented(self): - transport = asyncio.DatagramTransport() - - self.assertRaises(NotImplementedError, transport.sendto, 'data') - self.assertRaises(NotImplementedError, transport.abort) - - def test_subprocess_transport_not_implemented(self): - transport = asyncio.SubprocessTransport() - - self.assertRaises(NotImplementedError, transport.get_pid) - self.assertRaises(NotImplementedError, transport.get_returncode) - self.assertRaises(NotImplementedError, transport.get_pipe_transport, 1) - self.assertRaises(NotImplementedError, transport.send_signal, 1) - self.assertRaises(NotImplementedError, transport.terminate) - self.assertRaises(NotImplementedError, transport.kill) - - def test_flowcontrol_mixin_set_write_limits(self): - - class MyTransport(transports._FlowControlMixin, - transports.Transport): - - def get_write_buffer_size(self): - return 512 - - loop = mock.Mock() - transport = MyTransport(loop=loop) - transport._protocol = mock.Mock() - - self.assertFalse(transport._protocol_paused) - - with self.assertRaisesRegex(ValueError, 'high.*must be >= low'): - transport.set_write_buffer_limits(high=0, low=1) - - transport.set_write_buffer_limits(high=1024, low=128) - self.assertFalse(transport._protocol_paused) - self.assertEqual(transport.get_write_buffer_limits(), (128, 1024)) - - transport.set_write_buffer_limits(high=256, low=128) - self.assertTrue(transport._protocol_paused) - self.assertEqual(transport.get_write_buffer_limits(), (128, 256)) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py deleted file mode 100644 index 5487b7a..0000000 --- a/Lib/test/test_asyncio/test_unix_events.py +++ /dev/null @@ -1,1966 +0,0 @@ -"""Tests for unix_events.py.""" - -import collections -import contextlib -import errno -import io -import os -import pathlib -import signal -import socket -import stat -import sys -import tempfile -import threading -import unittest -from unittest import mock -from test import support - -if sys.platform == 'win32': - raise unittest.SkipTest('UNIX only') - - -import asyncio -from asyncio import log -from asyncio import unix_events -from test.test_asyncio import utils as test_utils - - -MOCK_ANY = mock.ANY - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -def close_pipe_transport(transport): - # Don't call transport.close() because the event loop and the selector - # are mocked - if transport._pipe is None: - return - transport._pipe.close() - transport._pipe = None - - -@unittest.skipUnless(signal, 'Signals are not supported') -class SelectorEventLoopSignalTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.SelectorEventLoop() - self.set_event_loop(self.loop) - - def test_check_signal(self): - self.assertRaises( - TypeError, self.loop._check_signal, '1') - self.assertRaises( - ValueError, self.loop._check_signal, signal.NSIG + 1) - - def test_handle_signal_no_handler(self): - self.loop._handle_signal(signal.NSIG + 1) - - def test_handle_signal_cancelled_handler(self): - h = asyncio.Handle(mock.Mock(), (), - loop=mock.Mock()) - h.cancel() - self.loop._signal_handlers[signal.NSIG + 1] = h - self.loop.remove_signal_handler = mock.Mock() - self.loop._handle_signal(signal.NSIG + 1) - self.loop.remove_signal_handler.assert_called_with(signal.NSIG + 1) - - @mock.patch('asyncio.unix_events.signal') - def test_add_signal_handler_setup_error(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - m_signal.set_wakeup_fd.side_effect = ValueError - - self.assertRaises( - RuntimeError, - self.loop.add_signal_handler, - signal.SIGINT, lambda: True) - - @mock.patch('asyncio.unix_events.signal') - def test_add_signal_handler_coroutine_error(self, m_signal): - m_signal.NSIG = signal.NSIG - - async def simple_coroutine(): - pass - - # callback must not be a coroutine function - coro_func = simple_coroutine - coro_obj = coro_func() - self.addCleanup(coro_obj.close) - for func in (coro_func, coro_obj): - self.assertRaisesRegex( - TypeError, 'coroutines cannot be used with add_signal_handler', - self.loop.add_signal_handler, - signal.SIGINT, func) - - @mock.patch('asyncio.unix_events.signal') - def test_add_signal_handler(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - cb = lambda: True - self.loop.add_signal_handler(signal.SIGHUP, cb) - h = self.loop._signal_handlers.get(signal.SIGHUP) - self.assertIsInstance(h, asyncio.Handle) - self.assertEqual(h._callback, cb) - - @mock.patch('asyncio.unix_events.signal') - def test_add_signal_handler_install_error(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - def set_wakeup_fd(fd): - if fd == -1: - raise ValueError() - m_signal.set_wakeup_fd = set_wakeup_fd - - class Err(OSError): - errno = errno.EFAULT - m_signal.signal.side_effect = Err - - self.assertRaises( - Err, - self.loop.add_signal_handler, - signal.SIGINT, lambda: True) - - @mock.patch('asyncio.unix_events.signal') - @mock.patch('asyncio.base_events.logger') - def test_add_signal_handler_install_error2(self, m_logging, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - class Err(OSError): - errno = errno.EINVAL - m_signal.signal.side_effect = Err - - self.loop._signal_handlers[signal.SIGHUP] = lambda: True - self.assertRaises( - RuntimeError, - self.loop.add_signal_handler, - signal.SIGINT, lambda: True) - self.assertFalse(m_logging.info.called) - self.assertEqual(1, m_signal.set_wakeup_fd.call_count) - - @mock.patch('asyncio.unix_events.signal') - @mock.patch('asyncio.base_events.logger') - def test_add_signal_handler_install_error3(self, m_logging, m_signal): - class Err(OSError): - errno = errno.EINVAL - m_signal.signal.side_effect = Err - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - self.assertRaises( - RuntimeError, - self.loop.add_signal_handler, - signal.SIGINT, lambda: True) - self.assertFalse(m_logging.info.called) - self.assertEqual(2, m_signal.set_wakeup_fd.call_count) - - @mock.patch('asyncio.unix_events.signal') - def test_remove_signal_handler(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - - self.assertTrue( - self.loop.remove_signal_handler(signal.SIGHUP)) - self.assertTrue(m_signal.set_wakeup_fd.called) - self.assertTrue(m_signal.signal.called) - self.assertEqual( - (signal.SIGHUP, m_signal.SIG_DFL), m_signal.signal.call_args[0]) - - @mock.patch('asyncio.unix_events.signal') - def test_remove_signal_handler_2(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.SIGINT = signal.SIGINT - m_signal.valid_signals = signal.valid_signals - - self.loop.add_signal_handler(signal.SIGINT, lambda: True) - self.loop._signal_handlers[signal.SIGHUP] = object() - m_signal.set_wakeup_fd.reset_mock() - - self.assertTrue( - self.loop.remove_signal_handler(signal.SIGINT)) - self.assertFalse(m_signal.set_wakeup_fd.called) - self.assertTrue(m_signal.signal.called) - self.assertEqual( - (signal.SIGINT, m_signal.default_int_handler), - m_signal.signal.call_args[0]) - - @mock.patch('asyncio.unix_events.signal') - @mock.patch('asyncio.base_events.logger') - def test_remove_signal_handler_cleanup_error(self, m_logging, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - - m_signal.set_wakeup_fd.side_effect = ValueError - - self.loop.remove_signal_handler(signal.SIGHUP) - self.assertTrue(m_logging.info) - - @mock.patch('asyncio.unix_events.signal') - def test_remove_signal_handler_error(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - - m_signal.signal.side_effect = OSError - - self.assertRaises( - OSError, self.loop.remove_signal_handler, signal.SIGHUP) - - @mock.patch('asyncio.unix_events.signal') - def test_remove_signal_handler_error2(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - - class Err(OSError): - errno = errno.EINVAL - m_signal.signal.side_effect = Err - - self.assertRaises( - RuntimeError, self.loop.remove_signal_handler, signal.SIGHUP) - - @mock.patch('asyncio.unix_events.signal') - def test_close(self, m_signal): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - self.loop.add_signal_handler(signal.SIGCHLD, lambda: True) - - self.assertEqual(len(self.loop._signal_handlers), 2) - - m_signal.set_wakeup_fd.reset_mock() - - self.loop.close() - - self.assertEqual(len(self.loop._signal_handlers), 0) - m_signal.set_wakeup_fd.assert_called_once_with(-1) - - @mock.patch('asyncio.unix_events.sys') - @mock.patch('asyncio.unix_events.signal') - def test_close_on_finalizing(self, m_signal, m_sys): - m_signal.NSIG = signal.NSIG - m_signal.valid_signals = signal.valid_signals - self.loop.add_signal_handler(signal.SIGHUP, lambda: True) - - self.assertEqual(len(self.loop._signal_handlers), 1) - m_sys.is_finalizing.return_value = True - m_signal.signal.reset_mock() - - with self.assertWarnsRegex(ResourceWarning, - "skipping signal handlers removal"): - self.loop.close() - - self.assertEqual(len(self.loop._signal_handlers), 0) - self.assertFalse(m_signal.signal.called) - - -@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), - 'UNIX Sockets are not supported') -class SelectorEventLoopUnixSocketTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.SelectorEventLoop() - self.set_event_loop(self.loop) - - @support.skip_unless_bind_unix_socket - def test_create_unix_server_existing_path_sock(self): - with test_utils.unix_socket_path() as path: - sock = socket.socket(socket.AF_UNIX) - sock.bind(path) - sock.listen(1) - sock.close() - - coro = self.loop.create_unix_server(lambda: None, path) - srv = self.loop.run_until_complete(coro) - srv.close() - self.loop.run_until_complete(srv.wait_closed()) - - @support.skip_unless_bind_unix_socket - def test_create_unix_server_pathlib(self): - with test_utils.unix_socket_path() as path: - path = pathlib.Path(path) - srv_coro = self.loop.create_unix_server(lambda: None, path) - srv = self.loop.run_until_complete(srv_coro) - srv.close() - self.loop.run_until_complete(srv.wait_closed()) - - def test_create_unix_connection_pathlib(self): - with test_utils.unix_socket_path() as path: - path = pathlib.Path(path) - coro = self.loop.create_unix_connection(lambda: None, path) - with self.assertRaises(FileNotFoundError): - # If pathlib.Path wasn't supported, the exception would be - # different. - self.loop.run_until_complete(coro) - - def test_create_unix_server_existing_path_nonsock(self): - with tempfile.NamedTemporaryFile() as file: - coro = self.loop.create_unix_server(lambda: None, file.name) - with self.assertRaisesRegex(OSError, - 'Address.*is already in use'): - self.loop.run_until_complete(coro) - - def test_create_unix_server_ssl_bool(self): - coro = self.loop.create_unix_server(lambda: None, path='spam', - ssl=True) - with self.assertRaisesRegex(TypeError, - 'ssl argument must be an SSLContext'): - self.loop.run_until_complete(coro) - - def test_create_unix_server_nopath_nosock(self): - coro = self.loop.create_unix_server(lambda: None, path=None) - with self.assertRaisesRegex(ValueError, - 'path was not specified, and no sock'): - self.loop.run_until_complete(coro) - - def test_create_unix_server_path_inetsock(self): - sock = socket.socket() - with sock: - coro = self.loop.create_unix_server(lambda: None, path=None, - sock=sock) - with self.assertRaisesRegex(ValueError, - 'A UNIX Domain Stream.*was expected'): - self.loop.run_until_complete(coro) - - def test_create_unix_server_path_dgram(self): - sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) - with sock: - coro = self.loop.create_unix_server(lambda: None, path=None, - sock=sock) - with self.assertRaisesRegex(ValueError, - 'A UNIX Domain Stream.*was expected'): - self.loop.run_until_complete(coro) - - @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), - 'no socket.SOCK_NONBLOCK (linux only)') - @support.skip_unless_bind_unix_socket - def test_create_unix_server_path_stream_bittype(self): - sock = socket.socket( - socket.AF_UNIX, socket.SOCK_STREAM | socket.SOCK_NONBLOCK) - with tempfile.NamedTemporaryFile() as file: - fn = file.name - try: - with sock: - sock.bind(fn) - coro = self.loop.create_unix_server(lambda: None, path=None, - sock=sock) - srv = self.loop.run_until_complete(coro) - srv.close() - self.loop.run_until_complete(srv.wait_closed()) - finally: - os.unlink(fn) - - def test_create_unix_server_ssl_timeout_with_plain_sock(self): - coro = self.loop.create_unix_server(lambda: None, path='spam', - ssl_handshake_timeout=1) - with self.assertRaisesRegex( - ValueError, - 'ssl_handshake_timeout is only meaningful with ssl'): - self.loop.run_until_complete(coro) - - def test_create_unix_connection_path_inetsock(self): - sock = socket.socket() - with sock: - coro = self.loop.create_unix_connection(lambda: None, - sock=sock) - with self.assertRaisesRegex(ValueError, - 'A UNIX Domain Stream.*was expected'): - self.loop.run_until_complete(coro) - - @mock.patch('asyncio.unix_events.socket') - def test_create_unix_server_bind_error(self, m_socket): - # Ensure that the socket is closed on any bind error - sock = mock.Mock() - m_socket.socket.return_value = sock - - sock.bind.side_effect = OSError - coro = self.loop.create_unix_server(lambda: None, path="/test") - with self.assertRaises(OSError): - self.loop.run_until_complete(coro) - self.assertTrue(sock.close.called) - - sock.bind.side_effect = MemoryError - coro = self.loop.create_unix_server(lambda: None, path="/test") - with self.assertRaises(MemoryError): - self.loop.run_until_complete(coro) - self.assertTrue(sock.close.called) - - def test_create_unix_connection_path_sock(self): - coro = self.loop.create_unix_connection( - lambda: None, os.devnull, sock=object()) - with self.assertRaisesRegex(ValueError, 'path and sock can not be'): - self.loop.run_until_complete(coro) - - def test_create_unix_connection_nopath_nosock(self): - coro = self.loop.create_unix_connection( - lambda: None, None) - with self.assertRaisesRegex(ValueError, - 'no path and sock were specified'): - self.loop.run_until_complete(coro) - - def test_create_unix_connection_nossl_serverhost(self): - coro = self.loop.create_unix_connection( - lambda: None, os.devnull, server_hostname='spam') - with self.assertRaisesRegex(ValueError, - 'server_hostname is only meaningful'): - self.loop.run_until_complete(coro) - - def test_create_unix_connection_ssl_noserverhost(self): - coro = self.loop.create_unix_connection( - lambda: None, os.devnull, ssl=True) - - with self.assertRaisesRegex( - ValueError, 'you have to pass server_hostname when using ssl'): - - self.loop.run_until_complete(coro) - - def test_create_unix_connection_ssl_timeout_with_plain_sock(self): - coro = self.loop.create_unix_connection(lambda: None, path='spam', - ssl_handshake_timeout=1) - with self.assertRaisesRegex( - ValueError, - 'ssl_handshake_timeout is only meaningful with ssl'): - self.loop.run_until_complete(coro) - - -@unittest.skipUnless(hasattr(os, 'sendfile'), - 'sendfile is not supported') -class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase): - DATA = b"12345abcde" * 16 * 1024 # 160 KiB - - class MyProto(asyncio.Protocol): - - def __init__(self, loop): - self.started = False - self.closed = False - self.data = bytearray() - self.fut = loop.create_future() - self.transport = None - self._ready = loop.create_future() - - def connection_made(self, transport): - self.started = True - self.transport = transport - self._ready.set_result(None) - - def data_received(self, data): - self.data.extend(data) - - def connection_lost(self, exc): - self.closed = True - self.fut.set_result(None) - - async def wait_closed(self): - await self.fut - - @classmethod - def setUpClass(cls): - with open(support.TESTFN, 'wb') as fp: - fp.write(cls.DATA) - super().setUpClass() - - @classmethod - def tearDownClass(cls): - support.unlink(support.TESTFN) - super().tearDownClass() - - def setUp(self): - self.loop = asyncio.new_event_loop() - self.set_event_loop(self.loop) - self.file = open(support.TESTFN, 'rb') - self.addCleanup(self.file.close) - super().setUp() - - def make_socket(self, cleanup=True): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(False) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) - if cleanup: - self.addCleanup(sock.close) - return sock - - def run_loop(self, coro): - return self.loop.run_until_complete(coro) - - def prepare(self): - sock = self.make_socket() - proto = self.MyProto(self.loop) - port = support.find_unused_port() - srv_sock = self.make_socket(cleanup=False) - srv_sock.bind((support.HOST, port)) - server = self.run_loop(self.loop.create_server( - lambda: proto, sock=srv_sock)) - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) - self.run_loop(proto._ready) - - def cleanup(): - proto.transport.close() - self.run_loop(proto.wait_closed()) - - server.close() - self.run_loop(server.wait_closed()) - - self.addCleanup(cleanup) - - return sock, proto - - def test_sock_sendfile_not_available(self): - sock, proto = self.prepare() - with mock.patch('asyncio.unix_events.os', spec=[]): - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "os[.]sendfile[(][)] is not available"): - self.run_loop(self.loop._sock_sendfile_native(sock, self.file, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_not_a_file(self): - sock, proto = self.prepare() - f = object() - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_iobuffer(self): - sock, proto = self.prepare() - f = io.BytesIO() - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_not_regular_file(self): - sock, proto = self.prepare() - f = mock.Mock() - f.fileno.return_value = -1 - with self.assertRaisesRegex(asyncio.SendfileNotAvailableError, - "not a regular file"): - self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_cancel1(self): - sock, proto = self.prepare() - - fut = self.loop.create_future() - fileno = self.file.fileno() - self.loop._sock_sendfile_native_impl(fut, None, sock, fileno, - 0, None, len(self.DATA), 0) - fut.cancel() - with contextlib.suppress(asyncio.CancelledError): - self.run_loop(fut) - with self.assertRaises(KeyError): - self.loop._selector.get_key(sock) - - def test_sock_sendfile_cancel2(self): - sock, proto = self.prepare() - - fut = self.loop.create_future() - fileno = self.file.fileno() - self.loop._sock_sendfile_native_impl(fut, None, sock, fileno, - 0, None, len(self.DATA), 0) - fut.cancel() - self.loop._sock_sendfile_native_impl(fut, sock.fileno(), sock, fileno, - 0, None, len(self.DATA), 0) - with self.assertRaises(KeyError): - self.loop._selector.get_key(sock) - - def test_sock_sendfile_blocking_error(self): - sock, proto = self.prepare() - - fileno = self.file.fileno() - fut = mock.Mock() - fut.cancelled.return_value = False - with mock.patch('os.sendfile', side_effect=BlockingIOError()): - self.loop._sock_sendfile_native_impl(fut, None, sock, fileno, - 0, None, len(self.DATA), 0) - key = self.loop._selector.get_key(sock) - self.assertIsNotNone(key) - fut.add_done_callback.assert_called_once_with(mock.ANY) - - def test_sock_sendfile_os_error_first_call(self): - sock, proto = self.prepare() - - fileno = self.file.fileno() - fut = self.loop.create_future() - with mock.patch('os.sendfile', side_effect=OSError()): - self.loop._sock_sendfile_native_impl(fut, None, sock, fileno, - 0, None, len(self.DATA), 0) - with self.assertRaises(KeyError): - self.loop._selector.get_key(sock) - exc = fut.exception() - self.assertIsInstance(exc, asyncio.SendfileNotAvailableError) - self.assertEqual(0, self.file.tell()) - - def test_sock_sendfile_os_error_next_call(self): - sock, proto = self.prepare() - - fileno = self.file.fileno() - fut = self.loop.create_future() - err = OSError() - with mock.patch('os.sendfile', side_effect=err): - self.loop._sock_sendfile_native_impl(fut, sock.fileno(), - sock, fileno, - 1000, None, len(self.DATA), - 1000) - with self.assertRaises(KeyError): - self.loop._selector.get_key(sock) - exc = fut.exception() - self.assertIs(exc, err) - self.assertEqual(1000, self.file.tell()) - - def test_sock_sendfile_exception(self): - sock, proto = self.prepare() - - fileno = self.file.fileno() - fut = self.loop.create_future() - err = asyncio.SendfileNotAvailableError() - with mock.patch('os.sendfile', side_effect=err): - self.loop._sock_sendfile_native_impl(fut, sock.fileno(), - sock, fileno, - 1000, None, len(self.DATA), - 1000) - with self.assertRaises(KeyError): - self.loop._selector.get_key(sock) - exc = fut.exception() - self.assertIs(exc, err) - self.assertEqual(1000, self.file.tell()) - - -class UnixReadPipeTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.pipe = mock.Mock(spec_set=io.RawIOBase) - self.pipe.fileno.return_value = 5 - - blocking_patcher = mock.patch('os.set_blocking') - blocking_patcher.start() - self.addCleanup(blocking_patcher.stop) - - fstat_patcher = mock.patch('os.fstat') - m_fstat = fstat_patcher.start() - st = mock.Mock() - st.st_mode = stat.S_IFIFO - m_fstat.return_value = st - self.addCleanup(fstat_patcher.stop) - - def read_pipe_transport(self, waiter=None): - transport = unix_events._UnixReadPipeTransport(self.loop, self.pipe, - self.protocol, - waiter=waiter) - self.addCleanup(close_pipe_transport, transport) - return transport - - def test_ctor(self): - waiter = self.loop.create_future() - tr = self.read_pipe_transport(waiter=waiter) - self.loop.run_until_complete(waiter) - - self.protocol.connection_made.assert_called_with(tr) - self.loop.assert_reader(5, tr._read_ready) - self.assertIsNone(waiter.result()) - - @mock.patch('os.read') - def test__read_ready(self, m_read): - tr = self.read_pipe_transport() - m_read.return_value = b'data' - tr._read_ready() - - m_read.assert_called_with(5, tr.max_size) - self.protocol.data_received.assert_called_with(b'data') - - @mock.patch('os.read') - def test__read_ready_eof(self, m_read): - tr = self.read_pipe_transport() - m_read.return_value = b'' - tr._read_ready() - - m_read.assert_called_with(5, tr.max_size) - self.assertFalse(self.loop.readers) - test_utils.run_briefly(self.loop) - self.protocol.eof_received.assert_called_with() - self.protocol.connection_lost.assert_called_with(None) - - @mock.patch('os.read') - def test__read_ready_blocked(self, m_read): - tr = self.read_pipe_transport() - m_read.side_effect = BlockingIOError - tr._read_ready() - - m_read.assert_called_with(5, tr.max_size) - test_utils.run_briefly(self.loop) - self.assertFalse(self.protocol.data_received.called) - - @mock.patch('asyncio.log.logger.error') - @mock.patch('os.read') - def test__read_ready_error(self, m_read, m_logexc): - tr = self.read_pipe_transport() - err = OSError() - m_read.side_effect = err - tr._close = mock.Mock() - tr._read_ready() - - m_read.assert_called_with(5, tr.max_size) - tr._close.assert_called_with(err) - m_logexc.assert_called_with( - test_utils.MockPattern( - 'Fatal read error on pipe transport' - '\nprotocol:.*\ntransport:.*'), - exc_info=(OSError, MOCK_ANY, MOCK_ANY)) - - @mock.patch('os.read') - def test_pause_reading(self, m_read): - tr = self.read_pipe_transport() - m = mock.Mock() - self.loop.add_reader(5, m) - tr.pause_reading() - self.assertFalse(self.loop.readers) - - @mock.patch('os.read') - def test_resume_reading(self, m_read): - tr = self.read_pipe_transport() - tr.pause_reading() - tr.resume_reading() - self.loop.assert_reader(5, tr._read_ready) - - @mock.patch('os.read') - def test_close(self, m_read): - tr = self.read_pipe_transport() - tr._close = mock.Mock() - tr.close() - tr._close.assert_called_with(None) - - @mock.patch('os.read') - def test_close_already_closing(self, m_read): - tr = self.read_pipe_transport() - tr._closing = True - tr._close = mock.Mock() - tr.close() - self.assertFalse(tr._close.called) - - @mock.patch('os.read') - def test__close(self, m_read): - tr = self.read_pipe_transport() - err = object() - tr._close(err) - self.assertTrue(tr.is_closing()) - self.assertFalse(self.loop.readers) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(err) - - def test__call_connection_lost(self): - tr = self.read_pipe_transport() - self.assertIsNotNone(tr._protocol) - self.assertIsNotNone(tr._loop) - - err = None - tr._call_connection_lost(err) - self.protocol.connection_lost.assert_called_with(err) - self.pipe.close.assert_called_with() - - self.assertIsNone(tr._protocol) - self.assertIsNone(tr._loop) - - def test__call_connection_lost_with_err(self): - tr = self.read_pipe_transport() - self.assertIsNotNone(tr._protocol) - self.assertIsNotNone(tr._loop) - - err = OSError() - tr._call_connection_lost(err) - self.protocol.connection_lost.assert_called_with(err) - self.pipe.close.assert_called_with() - - self.assertIsNone(tr._protocol) - self.assertIsNone(tr._loop) - - def test_pause_reading_on_closed_pipe(self): - tr = self.read_pipe_transport() - tr.close() - test_utils.run_briefly(self.loop) - self.assertIsNone(tr._loop) - tr.pause_reading() - - def test_pause_reading_on_paused_pipe(self): - tr = self.read_pipe_transport() - tr.pause_reading() - # the second call should do nothing - tr.pause_reading() - - def test_resume_reading_on_closed_pipe(self): - tr = self.read_pipe_transport() - tr.close() - test_utils.run_briefly(self.loop) - self.assertIsNone(tr._loop) - tr.resume_reading() - - def test_resume_reading_on_paused_pipe(self): - tr = self.read_pipe_transport() - # the pipe is not paused - # resuming should do nothing - tr.resume_reading() - - -class UnixWritePipeTransportTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.protocol = test_utils.make_test_protocol(asyncio.BaseProtocol) - self.pipe = mock.Mock(spec_set=io.RawIOBase) - self.pipe.fileno.return_value = 5 - - blocking_patcher = mock.patch('os.set_blocking') - blocking_patcher.start() - self.addCleanup(blocking_patcher.stop) - - fstat_patcher = mock.patch('os.fstat') - m_fstat = fstat_patcher.start() - st = mock.Mock() - st.st_mode = stat.S_IFSOCK - m_fstat.return_value = st - self.addCleanup(fstat_patcher.stop) - - def write_pipe_transport(self, waiter=None): - transport = unix_events._UnixWritePipeTransport(self.loop, self.pipe, - self.protocol, - waiter=waiter) - self.addCleanup(close_pipe_transport, transport) - return transport - - def test_ctor(self): - waiter = self.loop.create_future() - tr = self.write_pipe_transport(waiter=waiter) - self.loop.run_until_complete(waiter) - - self.protocol.connection_made.assert_called_with(tr) - self.loop.assert_reader(5, tr._read_ready) - self.assertEqual(None, waiter.result()) - - def test_can_write_eof(self): - tr = self.write_pipe_transport() - self.assertTrue(tr.can_write_eof()) - - @mock.patch('os.write') - def test_write(self, m_write): - tr = self.write_pipe_transport() - m_write.return_value = 4 - tr.write(b'data') - m_write.assert_called_with(5, b'data') - self.assertFalse(self.loop.writers) - self.assertEqual(bytearray(), tr._buffer) - - @mock.patch('os.write') - def test_write_no_data(self, m_write): - tr = self.write_pipe_transport() - tr.write(b'') - self.assertFalse(m_write.called) - self.assertFalse(self.loop.writers) - self.assertEqual(bytearray(b''), tr._buffer) - - @mock.patch('os.write') - def test_write_partial(self, m_write): - tr = self.write_pipe_transport() - m_write.return_value = 2 - tr.write(b'data') - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'ta'), tr._buffer) - - @mock.patch('os.write') - def test_write_buffer(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'previous') - tr.write(b'data') - self.assertFalse(m_write.called) - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'previousdata'), tr._buffer) - - @mock.patch('os.write') - def test_write_again(self, m_write): - tr = self.write_pipe_transport() - m_write.side_effect = BlockingIOError() - tr.write(b'data') - m_write.assert_called_with(5, bytearray(b'data')) - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'data'), tr._buffer) - - @mock.patch('asyncio.unix_events.logger') - @mock.patch('os.write') - def test_write_err(self, m_write, m_log): - tr = self.write_pipe_transport() - err = OSError() - m_write.side_effect = err - tr._fatal_error = mock.Mock() - tr.write(b'data') - m_write.assert_called_with(5, b'data') - self.assertFalse(self.loop.writers) - self.assertEqual(bytearray(), tr._buffer) - tr._fatal_error.assert_called_with( - err, - 'Fatal write error on pipe transport') - self.assertEqual(1, tr._conn_lost) - - tr.write(b'data') - self.assertEqual(2, tr._conn_lost) - tr.write(b'data') - tr.write(b'data') - tr.write(b'data') - tr.write(b'data') - # This is a bit overspecified. :-( - m_log.warning.assert_called_with( - 'pipe closed by peer or os.write(pipe, data) raised exception.') - tr.close() - - @mock.patch('os.write') - def test_write_close(self, m_write): - tr = self.write_pipe_transport() - tr._read_ready() # pipe was closed by peer - - tr.write(b'data') - self.assertEqual(tr._conn_lost, 1) - tr.write(b'data') - self.assertEqual(tr._conn_lost, 2) - - def test__read_ready(self): - tr = self.write_pipe_transport() - tr._read_ready() - self.assertFalse(self.loop.readers) - self.assertFalse(self.loop.writers) - self.assertTrue(tr.is_closing()) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - - @mock.patch('os.write') - def test__write_ready(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'data') - m_write.return_value = 4 - tr._write_ready() - self.assertFalse(self.loop.writers) - self.assertEqual(bytearray(), tr._buffer) - - @mock.patch('os.write') - def test__write_ready_partial(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'data') - m_write.return_value = 3 - tr._write_ready() - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'a'), tr._buffer) - - @mock.patch('os.write') - def test__write_ready_again(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'data') - m_write.side_effect = BlockingIOError() - tr._write_ready() - m_write.assert_called_with(5, bytearray(b'data')) - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'data'), tr._buffer) - - @mock.patch('os.write') - def test__write_ready_empty(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'data') - m_write.return_value = 0 - tr._write_ready() - m_write.assert_called_with(5, bytearray(b'data')) - self.loop.assert_writer(5, tr._write_ready) - self.assertEqual(bytearray(b'data'), tr._buffer) - - @mock.patch('asyncio.log.logger.error') - @mock.patch('os.write') - def test__write_ready_err(self, m_write, m_logexc): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._buffer = bytearray(b'data') - m_write.side_effect = err = OSError() - tr._write_ready() - self.assertFalse(self.loop.writers) - self.assertFalse(self.loop.readers) - self.assertEqual(bytearray(), tr._buffer) - self.assertTrue(tr.is_closing()) - m_logexc.assert_not_called() - self.assertEqual(1, tr._conn_lost) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(err) - - @mock.patch('os.write') - def test__write_ready_closing(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - tr._closing = True - tr._buffer = bytearray(b'data') - m_write.return_value = 4 - tr._write_ready() - self.assertFalse(self.loop.writers) - self.assertFalse(self.loop.readers) - self.assertEqual(bytearray(), tr._buffer) - self.protocol.connection_lost.assert_called_with(None) - self.pipe.close.assert_called_with() - - @mock.patch('os.write') - def test_abort(self, m_write): - tr = self.write_pipe_transport() - self.loop.add_writer(5, tr._write_ready) - self.loop.add_reader(5, tr._read_ready) - tr._buffer = [b'da', b'ta'] - tr.abort() - self.assertFalse(m_write.called) - self.assertFalse(self.loop.readers) - self.assertFalse(self.loop.writers) - self.assertEqual([], tr._buffer) - self.assertTrue(tr.is_closing()) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - - def test__call_connection_lost(self): - tr = self.write_pipe_transport() - self.assertIsNotNone(tr._protocol) - self.assertIsNotNone(tr._loop) - - err = None - tr._call_connection_lost(err) - self.protocol.connection_lost.assert_called_with(err) - self.pipe.close.assert_called_with() - - self.assertIsNone(tr._protocol) - self.assertIsNone(tr._loop) - - def test__call_connection_lost_with_err(self): - tr = self.write_pipe_transport() - self.assertIsNotNone(tr._protocol) - self.assertIsNotNone(tr._loop) - - err = OSError() - tr._call_connection_lost(err) - self.protocol.connection_lost.assert_called_with(err) - self.pipe.close.assert_called_with() - - self.assertIsNone(tr._protocol) - self.assertIsNone(tr._loop) - - def test_close(self): - tr = self.write_pipe_transport() - tr.write_eof = mock.Mock() - tr.close() - tr.write_eof.assert_called_with() - - # closing the transport twice must not fail - tr.close() - - def test_close_closing(self): - tr = self.write_pipe_transport() - tr.write_eof = mock.Mock() - tr._closing = True - tr.close() - self.assertFalse(tr.write_eof.called) - - def test_write_eof(self): - tr = self.write_pipe_transport() - tr.write_eof() - self.assertTrue(tr.is_closing()) - self.assertFalse(self.loop.readers) - test_utils.run_briefly(self.loop) - self.protocol.connection_lost.assert_called_with(None) - - def test_write_eof_pending(self): - tr = self.write_pipe_transport() - tr._buffer = [b'data'] - tr.write_eof() - self.assertTrue(tr.is_closing()) - self.assertFalse(self.protocol.connection_lost.called) - - -class AbstractChildWatcherTests(unittest.TestCase): - - def test_not_implemented(self): - f = mock.Mock() - watcher = asyncio.AbstractChildWatcher() - self.assertRaises( - NotImplementedError, watcher.add_child_handler, f, f) - self.assertRaises( - NotImplementedError, watcher.remove_child_handler, f) - self.assertRaises( - NotImplementedError, watcher.attach_loop, f) - self.assertRaises( - NotImplementedError, watcher.close) - self.assertRaises( - NotImplementedError, watcher.is_active) - self.assertRaises( - NotImplementedError, watcher.__enter__) - self.assertRaises( - NotImplementedError, watcher.__exit__, f, f, f) - - -class BaseChildWatcherTests(unittest.TestCase): - - def test_not_implemented(self): - f = mock.Mock() - watcher = unix_events.BaseChildWatcher() - self.assertRaises( - NotImplementedError, watcher._do_waitpid, f) - - -WaitPidMocks = collections.namedtuple("WaitPidMocks", - ("waitpid", - "WIFEXITED", - "WIFSIGNALED", - "WEXITSTATUS", - "WTERMSIG", - )) - - -class ChildWatcherTestsMixin: - - ignore_warnings = mock.patch.object(log.logger, "warning") - - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - self.running = False - self.zombies = {} - - with mock.patch.object( - self.loop, "add_signal_handler") as self.m_add_signal_handler: - self.watcher = self.create_watcher() - self.watcher.attach_loop(self.loop) - - def waitpid(self, pid, flags): - if isinstance(self.watcher, asyncio.SafeChildWatcher) or pid != -1: - self.assertGreater(pid, 0) - try: - if pid < 0: - return self.zombies.popitem() - else: - return pid, self.zombies.pop(pid) - except KeyError: - pass - if self.running: - return 0, 0 - else: - raise ChildProcessError() - - def add_zombie(self, pid, returncode): - self.zombies[pid] = returncode + 32768 - - def WIFEXITED(self, status): - return status >= 32768 - - def WIFSIGNALED(self, status): - return 32700 < status < 32768 - - def WEXITSTATUS(self, status): - self.assertTrue(self.WIFEXITED(status)) - return status - 32768 - - def WTERMSIG(self, status): - self.assertTrue(self.WIFSIGNALED(status)) - return 32768 - status - - def test_create_watcher(self): - self.m_add_signal_handler.assert_called_once_with( - signal.SIGCHLD, self.watcher._sig_chld) - - def waitpid_mocks(func): - def wrapped_func(self): - def patch(target, wrapper): - return mock.patch(target, wraps=wrapper, - new_callable=mock.Mock) - - with patch('os.WTERMSIG', self.WTERMSIG) as m_WTERMSIG, \ - patch('os.WEXITSTATUS', self.WEXITSTATUS) as m_WEXITSTATUS, \ - patch('os.WIFSIGNALED', self.WIFSIGNALED) as m_WIFSIGNALED, \ - patch('os.WIFEXITED', self.WIFEXITED) as m_WIFEXITED, \ - patch('os.waitpid', self.waitpid) as m_waitpid: - func(self, WaitPidMocks(m_waitpid, - m_WIFEXITED, m_WIFSIGNALED, - m_WEXITSTATUS, m_WTERMSIG, - )) - return wrapped_func - - @waitpid_mocks - def test_sigchld(self, m): - # register a child - callback = mock.Mock() - - with self.watcher: - self.running = True - self.watcher.add_child_handler(42, callback, 9, 10, 14) - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child is running - self.watcher._sig_chld() - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child terminates (returncode 12) - self.running = False - self.add_zombie(42, 12) - self.watcher._sig_chld() - - self.assertTrue(m.WIFEXITED.called) - self.assertTrue(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - callback.assert_called_once_with(42, 12, 9, 10, 14) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WEXITSTATUS.reset_mock() - callback.reset_mock() - - # ensure that the child is effectively reaped - self.add_zombie(42, 13) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback.called) - self.assertFalse(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WEXITSTATUS.reset_mock() - - # sigchld called again - self.zombies.clear() - self.watcher._sig_chld() - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - @waitpid_mocks - def test_sigchld_two_children(self, m): - callback1 = mock.Mock() - callback2 = mock.Mock() - - # register child 1 - with self.watcher: - self.running = True - self.watcher.add_child_handler(43, callback1, 7, 8) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # register child 2 - with self.watcher: - self.watcher.add_child_handler(44, callback2, 147, 18) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # children are running - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child 1 terminates (signal 3) - self.add_zombie(43, -3) - self.watcher._sig_chld() - - callback1.assert_called_once_with(43, -3, 7, 8) - self.assertFalse(callback2.called) - self.assertTrue(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertTrue(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WTERMSIG.reset_mock() - callback1.reset_mock() - - # child 2 still running - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child 2 terminates (code 108) - self.add_zombie(44, 108) - self.running = False - self.watcher._sig_chld() - - callback2.assert_called_once_with(44, 108, 147, 18) - self.assertFalse(callback1.called) - self.assertTrue(m.WIFEXITED.called) - self.assertTrue(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WEXITSTATUS.reset_mock() - callback2.reset_mock() - - # ensure that the children are effectively reaped - self.add_zombie(43, 14) - self.add_zombie(44, 15) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WEXITSTATUS.reset_mock() - - # sigchld called again - self.zombies.clear() - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - @waitpid_mocks - def test_sigchld_two_children_terminating_together(self, m): - callback1 = mock.Mock() - callback2 = mock.Mock() - - # register child 1 - with self.watcher: - self.running = True - self.watcher.add_child_handler(45, callback1, 17, 8) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # register child 2 - with self.watcher: - self.watcher.add_child_handler(46, callback2, 1147, 18) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # children are running - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child 1 terminates (code 78) - # child 2 terminates (signal 5) - self.add_zombie(45, 78) - self.add_zombie(46, -5) - self.running = False - self.watcher._sig_chld() - - callback1.assert_called_once_with(45, 78, 17, 8) - callback2.assert_called_once_with(46, -5, 1147, 18) - self.assertTrue(m.WIFSIGNALED.called) - self.assertTrue(m.WIFEXITED.called) - self.assertTrue(m.WEXITSTATUS.called) - self.assertTrue(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WTERMSIG.reset_mock() - m.WEXITSTATUS.reset_mock() - callback1.reset_mock() - callback2.reset_mock() - - # ensure that the children are effectively reaped - self.add_zombie(45, 14) - self.add_zombie(46, 15) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WTERMSIG.called) - - @waitpid_mocks - def test_sigchld_race_condition(self, m): - # register a child - callback = mock.Mock() - - with self.watcher: - # child terminates before being registered - self.add_zombie(50, 4) - self.watcher._sig_chld() - - self.watcher.add_child_handler(50, callback, 1, 12) - - callback.assert_called_once_with(50, 4, 1, 12) - callback.reset_mock() - - # ensure that the child is effectively reaped - self.add_zombie(50, -1) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback.called) - - @waitpid_mocks - def test_sigchld_replace_handler(self, m): - callback1 = mock.Mock() - callback2 = mock.Mock() - - # register a child - with self.watcher: - self.running = True - self.watcher.add_child_handler(51, callback1, 19) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # register the same child again - with self.watcher: - self.watcher.add_child_handler(51, callback2, 21) - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child terminates (signal 8) - self.running = False - self.add_zombie(51, -8) - self.watcher._sig_chld() - - callback2.assert_called_once_with(51, -8, 21) - self.assertFalse(callback1.called) - self.assertTrue(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertTrue(m.WTERMSIG.called) - - m.WIFSIGNALED.reset_mock() - m.WIFEXITED.reset_mock() - m.WTERMSIG.reset_mock() - callback2.reset_mock() - - # ensure that the child is effectively reaped - self.add_zombie(51, 13) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(m.WTERMSIG.called) - - @waitpid_mocks - def test_sigchld_remove_handler(self, m): - callback = mock.Mock() - - # register a child - with self.watcher: - self.running = True - self.watcher.add_child_handler(52, callback, 1984) - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # unregister the child - self.watcher.remove_child_handler(52) - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child terminates (code 99) - self.running = False - self.add_zombie(52, 99) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback.called) - - @waitpid_mocks - def test_sigchld_unknown_status(self, m): - callback = mock.Mock() - - # register a child - with self.watcher: - self.running = True - self.watcher.add_child_handler(53, callback, -19) - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # terminate with unknown status - self.zombies[53] = 1178 - self.running = False - self.watcher._sig_chld() - - callback.assert_called_once_with(53, 1178, -19) - self.assertTrue(m.WIFEXITED.called) - self.assertTrue(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - callback.reset_mock() - m.WIFEXITED.reset_mock() - m.WIFSIGNALED.reset_mock() - - # ensure that the child is effectively reaped - self.add_zombie(53, 101) - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback.called) - - @waitpid_mocks - def test_remove_child_handler(self, m): - callback1 = mock.Mock() - callback2 = mock.Mock() - callback3 = mock.Mock() - - # register children - with self.watcher: - self.running = True - self.watcher.add_child_handler(54, callback1, 1) - self.watcher.add_child_handler(55, callback2, 2) - self.watcher.add_child_handler(56, callback3, 3) - - # remove child handler 1 - self.assertTrue(self.watcher.remove_child_handler(54)) - - # remove child handler 2 multiple times - self.assertTrue(self.watcher.remove_child_handler(55)) - self.assertFalse(self.watcher.remove_child_handler(55)) - self.assertFalse(self.watcher.remove_child_handler(55)) - - # all children terminate - self.add_zombie(54, 0) - self.add_zombie(55, 1) - self.add_zombie(56, 2) - self.running = False - with self.ignore_warnings: - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - callback3.assert_called_once_with(56, 2, 3) - - @waitpid_mocks - def test_sigchld_unhandled_exception(self, m): - callback = mock.Mock() - - # register a child - with self.watcher: - self.running = True - self.watcher.add_child_handler(57, callback) - - # raise an exception - m.waitpid.side_effect = ValueError - - with mock.patch.object(log.logger, - 'error') as m_error: - - self.assertEqual(self.watcher._sig_chld(), None) - self.assertTrue(m_error.called) - - @waitpid_mocks - def test_sigchld_child_reaped_elsewhere(self, m): - # register a child - callback = mock.Mock() - - with self.watcher: - self.running = True - self.watcher.add_child_handler(58, callback) - - self.assertFalse(callback.called) - self.assertFalse(m.WIFEXITED.called) - self.assertFalse(m.WIFSIGNALED.called) - self.assertFalse(m.WEXITSTATUS.called) - self.assertFalse(m.WTERMSIG.called) - - # child terminates - self.running = False - self.add_zombie(58, 4) - - # waitpid is called elsewhere - os.waitpid(58, os.WNOHANG) - - m.waitpid.reset_mock() - - # sigchld - with self.ignore_warnings: - self.watcher._sig_chld() - - if isinstance(self.watcher, asyncio.FastChildWatcher): - # here the FastChildWatche enters a deadlock - # (there is no way to prevent it) - self.assertFalse(callback.called) - else: - callback.assert_called_once_with(58, 255) - - @waitpid_mocks - def test_sigchld_unknown_pid_during_registration(self, m): - # register two children - callback1 = mock.Mock() - callback2 = mock.Mock() - - with self.ignore_warnings, self.watcher: - self.running = True - # child 1 terminates - self.add_zombie(591, 7) - # an unknown child terminates - self.add_zombie(593, 17) - - self.watcher._sig_chld() - - self.watcher.add_child_handler(591, callback1) - self.watcher.add_child_handler(592, callback2) - - callback1.assert_called_once_with(591, 7) - self.assertFalse(callback2.called) - - @waitpid_mocks - def test_set_loop(self, m): - # register a child - callback = mock.Mock() - - with self.watcher: - self.running = True - self.watcher.add_child_handler(60, callback) - - # attach a new loop - old_loop = self.loop - self.loop = self.new_test_loop() - patch = mock.patch.object - - with patch(old_loop, "remove_signal_handler") as m_old_remove, \ - patch(self.loop, "add_signal_handler") as m_new_add: - - self.watcher.attach_loop(self.loop) - - m_old_remove.assert_called_once_with( - signal.SIGCHLD) - m_new_add.assert_called_once_with( - signal.SIGCHLD, self.watcher._sig_chld) - - # child terminates - self.running = False - self.add_zombie(60, 9) - self.watcher._sig_chld() - - callback.assert_called_once_with(60, 9) - - @waitpid_mocks - def test_set_loop_race_condition(self, m): - # register 3 children - callback1 = mock.Mock() - callback2 = mock.Mock() - callback3 = mock.Mock() - - with self.watcher: - self.running = True - self.watcher.add_child_handler(61, callback1) - self.watcher.add_child_handler(62, callback2) - self.watcher.add_child_handler(622, callback3) - - # detach the loop - old_loop = self.loop - self.loop = None - - with mock.patch.object( - old_loop, "remove_signal_handler") as m_remove_signal_handler: - - with self.assertWarnsRegex( - RuntimeWarning, 'A loop is being detached'): - self.watcher.attach_loop(None) - - m_remove_signal_handler.assert_called_once_with( - signal.SIGCHLD) - - # child 1 & 2 terminate - self.add_zombie(61, 11) - self.add_zombie(62, -5) - - # SIGCHLD was not caught - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - self.assertFalse(callback3.called) - - # attach a new loop - self.loop = self.new_test_loop() - - with mock.patch.object( - self.loop, "add_signal_handler") as m_add_signal_handler: - - self.watcher.attach_loop(self.loop) - - m_add_signal_handler.assert_called_once_with( - signal.SIGCHLD, self.watcher._sig_chld) - callback1.assert_called_once_with(61, 11) # race condition! - callback2.assert_called_once_with(62, -5) # race condition! - self.assertFalse(callback3.called) - - callback1.reset_mock() - callback2.reset_mock() - - # child 3 terminates - self.running = False - self.add_zombie(622, 19) - self.watcher._sig_chld() - - self.assertFalse(callback1.called) - self.assertFalse(callback2.called) - callback3.assert_called_once_with(622, 19) - - @waitpid_mocks - def test_close(self, m): - # register two children - callback1 = mock.Mock() - - with self.watcher: - self.running = True - # child 1 terminates - self.add_zombie(63, 9) - # other child terminates - self.add_zombie(65, 18) - self.watcher._sig_chld() - - self.watcher.add_child_handler(63, callback1) - self.watcher.add_child_handler(64, callback1) - - self.assertEqual(len(self.watcher._callbacks), 1) - if isinstance(self.watcher, asyncio.FastChildWatcher): - self.assertEqual(len(self.watcher._zombies), 1) - - with mock.patch.object( - self.loop, - "remove_signal_handler") as m_remove_signal_handler: - - self.watcher.close() - - m_remove_signal_handler.assert_called_once_with( - signal.SIGCHLD) - self.assertFalse(self.watcher._callbacks) - if isinstance(self.watcher, asyncio.FastChildWatcher): - self.assertFalse(self.watcher._zombies) - - -class SafeChildWatcherTests (ChildWatcherTestsMixin, test_utils.TestCase): - def create_watcher(self): - return asyncio.SafeChildWatcher() - - -class FastChildWatcherTests (ChildWatcherTestsMixin, test_utils.TestCase): - def create_watcher(self): - return asyncio.FastChildWatcher() - - -class PolicyTests(unittest.TestCase): - - def create_policy(self): - return asyncio.DefaultEventLoopPolicy() - - def test_get_default_child_watcher(self): - policy = self.create_policy() - self.assertIsNone(policy._watcher) - - watcher = policy.get_child_watcher() - self.assertIsInstance(watcher, asyncio.ThreadedChildWatcher) - - self.assertIs(policy._watcher, watcher) - - self.assertIs(watcher, policy.get_child_watcher()) - - def test_get_child_watcher_after_set(self): - policy = self.create_policy() - watcher = asyncio.FastChildWatcher() - - policy.set_child_watcher(watcher) - self.assertIs(policy._watcher, watcher) - self.assertIs(watcher, policy.get_child_watcher()) - - def test_get_child_watcher_thread(self): - - def f(): - policy.set_event_loop(policy.new_event_loop()) - - self.assertIsInstance(policy.get_event_loop(), - asyncio.AbstractEventLoop) - watcher = policy.get_child_watcher() - - self.assertIsInstance(watcher, asyncio.SafeChildWatcher) - self.assertIsNone(watcher._loop) - - policy.get_event_loop().close() - - policy = self.create_policy() - policy.set_child_watcher(asyncio.SafeChildWatcher()) - - th = threading.Thread(target=f) - th.start() - th.join() - - def test_child_watcher_replace_mainloop_existing(self): - policy = self.create_policy() - loop = policy.get_event_loop() - - # Explicitly setup SafeChildWatcher, - # default ThreadedChildWatcher has no _loop property - watcher = asyncio.SafeChildWatcher() - policy.set_child_watcher(watcher) - watcher.attach_loop(loop) - - self.assertIs(watcher._loop, loop) - - new_loop = policy.new_event_loop() - policy.set_event_loop(new_loop) - - self.assertIs(watcher._loop, new_loop) - - policy.set_event_loop(None) - - self.assertIs(watcher._loop, None) - - loop.close() - new_loop.close() - - -class TestFunctional(unittest.TestCase): - - def setUp(self): - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.loop) - - def tearDown(self): - self.loop.close() - asyncio.set_event_loop(None) - - def test_add_reader_invalid_argument(self): - def assert_raises(): - return self.assertRaisesRegex(ValueError, r'Invalid file object') - - cb = lambda: None - - with assert_raises(): - self.loop.add_reader(object(), cb) - with assert_raises(): - self.loop.add_writer(object(), cb) - - with assert_raises(): - self.loop.remove_reader(object()) - with assert_raises(): - self.loop.remove_writer(object()) - - def test_add_reader_or_writer_transport_fd(self): - def assert_raises(): - return self.assertRaisesRegex( - RuntimeError, - r'File descriptor .* is used by transport') - - async def runner(): - tr, pr = await self.loop.create_connection( - lambda: asyncio.Protocol(), sock=rsock) - - try: - cb = lambda: None - - with assert_raises(): - self.loop.add_reader(rsock, cb) - with assert_raises(): - self.loop.add_reader(rsock.fileno(), cb) - - with assert_raises(): - self.loop.remove_reader(rsock) - with assert_raises(): - self.loop.remove_reader(rsock.fileno()) - - with assert_raises(): - self.loop.add_writer(rsock, cb) - with assert_raises(): - self.loop.add_writer(rsock.fileno(), cb) - - with assert_raises(): - self.loop.remove_writer(rsock) - with assert_raises(): - self.loop.remove_writer(rsock.fileno()) - - finally: - tr.close() - - rsock, wsock = socket.socketpair() - try: - self.loop.run_until_complete(runner()) - finally: - rsock.close() - wsock.close() - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py deleted file mode 100644 index 6b00570..0000000 --- a/Lib/test/test_asyncio/test_windows_events.py +++ /dev/null @@ -1,247 +0,0 @@ -import os -import signal -import socket -import sys -import time -import threading -import unittest -from unittest import mock - -if sys.platform != 'win32': - raise unittest.SkipTest('Windows only') - -import _overlapped -import _winapi - -import asyncio -from asyncio import windows_events -from test.test_asyncio import utils as test_utils - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class UpperProto(asyncio.Protocol): - def __init__(self): - self.buf = [] - - def connection_made(self, trans): - self.trans = trans - - def data_received(self, data): - self.buf.append(data) - if b'\n' in data: - self.trans.write(b''.join(self.buf).upper()) - self.trans.close() - - -class ProactorLoopCtrlC(test_utils.TestCase): - - def test_ctrl_c(self): - - def SIGINT_after_delay(): - time.sleep(0.1) - signal.raise_signal(signal.SIGINT) - - thread = threading.Thread(target=SIGINT_after_delay) - loop = asyncio.get_event_loop() - try: - # only start the loop once the event loop is running - loop.call_soon(thread.start) - loop.run_forever() - self.fail("should not fall through 'run_forever'") - except KeyboardInterrupt: - pass - finally: - self.close_loop(loop) - thread.join() - - -class ProactorMultithreading(test_utils.TestCase): - def test_run_from_nonmain_thread(self): - finished = False - - async def coro(): - await asyncio.sleep(0) - - def func(): - nonlocal finished - loop = asyncio.new_event_loop() - loop.run_until_complete(coro()) - # close() must not call signal.set_wakeup_fd() - loop.close() - finished = True - - thread = threading.Thread(target=func) - thread.start() - thread.join() - self.assertTrue(finished) - - -class ProactorTests(test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.ProactorEventLoop() - self.set_event_loop(self.loop) - - def test_close(self): - a, b = socket.socketpair() - trans = self.loop._make_socket_transport(a, asyncio.Protocol()) - f = asyncio.ensure_future(self.loop.sock_recv(b, 100), loop=self.loop) - trans.close() - self.loop.run_until_complete(f) - self.assertEqual(f.result(), b'') - b.close() - - def test_double_bind(self): - ADDRESS = r'\\.\pipe\test_double_bind-%s' % os.getpid() - server1 = windows_events.PipeServer(ADDRESS) - with self.assertRaises(PermissionError): - windows_events.PipeServer(ADDRESS) - server1.close() - - def test_pipe(self): - res = self.loop.run_until_complete(self._test_pipe()) - self.assertEqual(res, 'done') - - async def _test_pipe(self): - ADDRESS = r'\\.\pipe\_test_pipe-%s' % os.getpid() - - with self.assertRaises(FileNotFoundError): - await self.loop.create_pipe_connection( - asyncio.Protocol, ADDRESS) - - [server] = await self.loop.start_serving_pipe( - UpperProto, ADDRESS) - self.assertIsInstance(server, windows_events.PipeServer) - - clients = [] - for i in range(5): - stream_reader = asyncio.StreamReader(loop=self.loop) - protocol = asyncio.StreamReaderProtocol(stream_reader, - loop=self.loop) - trans, proto = await self.loop.create_pipe_connection( - lambda: protocol, ADDRESS) - self.assertIsInstance(trans, asyncio.Transport) - self.assertEqual(protocol, proto) - clients.append((stream_reader, trans)) - - for i, (r, w) in enumerate(clients): - w.write('lower-{}\n'.format(i).encode()) - - for i, (r, w) in enumerate(clients): - response = await r.readline() - self.assertEqual(response, 'LOWER-{}\n'.format(i).encode()) - w.close() - - server.close() - - with self.assertRaises(FileNotFoundError): - await self.loop.create_pipe_connection( - asyncio.Protocol, ADDRESS) - - return 'done' - - def test_connect_pipe_cancel(self): - exc = OSError() - exc.winerror = _overlapped.ERROR_PIPE_BUSY - with mock.patch.object(_overlapped, 'ConnectPipe', - side_effect=exc) as connect: - coro = self.loop._proactor.connect_pipe('pipe_address') - task = self.loop.create_task(coro) - - # check that it's possible to cancel connect_pipe() - task.cancel() - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(task) - - def test_wait_for_handle(self): - event = _overlapped.CreateEvent(None, True, False, None) - self.addCleanup(_winapi.CloseHandle, event) - - # Wait for unset event with 0.5s timeout; - # result should be False at timeout - fut = self.loop._proactor.wait_for_handle(event, 0.5) - start = self.loop.time() - done = self.loop.run_until_complete(fut) - elapsed = self.loop.time() - start - - self.assertEqual(done, False) - self.assertFalse(fut.result()) - # bpo-31008: Tolerate only 450 ms (at least 500 ms expected), - # because of bad clock resolution on Windows - self.assertTrue(0.45 <= elapsed <= 0.9, elapsed) - - _overlapped.SetEvent(event) - - # Wait for set event; - # result should be True immediately - fut = self.loop._proactor.wait_for_handle(event, 10) - start = self.loop.time() - done = self.loop.run_until_complete(fut) - elapsed = self.loop.time() - start - - self.assertEqual(done, True) - self.assertTrue(fut.result()) - self.assertTrue(0 <= elapsed < 0.3, elapsed) - - # asyncio issue #195: cancelling a done _WaitHandleFuture - # must not crash - fut.cancel() - - def test_wait_for_handle_cancel(self): - event = _overlapped.CreateEvent(None, True, False, None) - self.addCleanup(_winapi.CloseHandle, event) - - # Wait for unset event with a cancelled future; - # CancelledError should be raised immediately - fut = self.loop._proactor.wait_for_handle(event, 10) - fut.cancel() - start = self.loop.time() - with self.assertRaises(asyncio.CancelledError): - self.loop.run_until_complete(fut) - elapsed = self.loop.time() - start - self.assertTrue(0 <= elapsed < 0.1, elapsed) - - # asyncio issue #195: cancelling a _WaitHandleFuture twice - # must not crash - fut = self.loop._proactor.wait_for_handle(event) - fut.cancel() - fut.cancel() - - -class WinPolicyTests(test_utils.TestCase): - - def test_selector_win_policy(self): - async def main(): - self.assertIsInstance( - asyncio.get_running_loop(), - asyncio.SelectorEventLoop) - - old_policy = asyncio.get_event_loop_policy() - try: - asyncio.set_event_loop_policy( - asyncio.WindowsSelectorEventLoopPolicy()) - asyncio.run(main()) - finally: - asyncio.set_event_loop_policy(old_policy) - - def test_proactor_win_policy(self): - async def main(): - self.assertIsInstance( - asyncio.get_running_loop(), - asyncio.ProactorEventLoop) - - old_policy = asyncio.get_event_loop_policy() - try: - asyncio.set_event_loop_policy( - asyncio.WindowsProactorEventLoopPolicy()) - asyncio.run(main()) - finally: - asyncio.set_event_loop_policy(old_policy) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py deleted file mode 100644 index 45c09bb..0000000 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ /dev/null @@ -1,132 +0,0 @@ -"""Tests for window_utils""" - -import sys -import unittest -import warnings - -if sys.platform != 'win32': - raise unittest.SkipTest('Windows only') - -import _overlapped -import _winapi - -import asyncio -from asyncio import windows_utils -from test import support - - -def tearDownModule(): - asyncio.set_event_loop_policy(None) - - -class PipeTests(unittest.TestCase): - - def test_pipe_overlapped(self): - h1, h2 = windows_utils.pipe(overlapped=(True, True)) - try: - ov1 = _overlapped.Overlapped() - self.assertFalse(ov1.pending) - self.assertEqual(ov1.error, 0) - - ov1.ReadFile(h1, 100) - self.assertTrue(ov1.pending) - self.assertEqual(ov1.error, _winapi.ERROR_IO_PENDING) - ERROR_IO_INCOMPLETE = 996 - try: - ov1.getresult() - except OSError as e: - self.assertEqual(e.winerror, ERROR_IO_INCOMPLETE) - else: - raise RuntimeError('expected ERROR_IO_INCOMPLETE') - - ov2 = _overlapped.Overlapped() - self.assertFalse(ov2.pending) - self.assertEqual(ov2.error, 0) - - ov2.WriteFile(h2, b"hello") - self.assertIn(ov2.error, {0, _winapi.ERROR_IO_PENDING}) - - res = _winapi.WaitForMultipleObjects([ov2.event], False, 100) - self.assertEqual(res, _winapi.WAIT_OBJECT_0) - - self.assertFalse(ov1.pending) - self.assertEqual(ov1.error, ERROR_IO_INCOMPLETE) - self.assertFalse(ov2.pending) - self.assertIn(ov2.error, {0, _winapi.ERROR_IO_PENDING}) - self.assertEqual(ov1.getresult(), b"hello") - finally: - _winapi.CloseHandle(h1) - _winapi.CloseHandle(h2) - - def test_pipe_handle(self): - h, _ = windows_utils.pipe(overlapped=(True, True)) - _winapi.CloseHandle(_) - p = windows_utils.PipeHandle(h) - self.assertEqual(p.fileno(), h) - self.assertEqual(p.handle, h) - - # check garbage collection of p closes handle - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", "", ResourceWarning) - del p - support.gc_collect() - try: - _winapi.CloseHandle(h) - except OSError as e: - self.assertEqual(e.winerror, 6) # ERROR_INVALID_HANDLE - else: - raise RuntimeError('expected ERROR_INVALID_HANDLE') - - -class PopenTests(unittest.TestCase): - - def test_popen(self): - command = r"""if 1: - import sys - s = sys.stdin.readline() - sys.stdout.write(s.upper()) - sys.stderr.write('stderr') - """ - msg = b"blah\n" - - p = windows_utils.Popen([sys.executable, '-c', command], - stdin=windows_utils.PIPE, - stdout=windows_utils.PIPE, - stderr=windows_utils.PIPE) - - for f in [p.stdin, p.stdout, p.stderr]: - self.assertIsInstance(f, windows_utils.PipeHandle) - - ovin = _overlapped.Overlapped() - ovout = _overlapped.Overlapped() - overr = _overlapped.Overlapped() - - ovin.WriteFile(p.stdin.handle, msg) - ovout.ReadFile(p.stdout.handle, 100) - overr.ReadFile(p.stderr.handle, 100) - - events = [ovin.event, ovout.event, overr.event] - # Super-long timeout for slow buildbots. - res = _winapi.WaitForMultipleObjects(events, True, 10000) - self.assertEqual(res, _winapi.WAIT_OBJECT_0) - self.assertFalse(ovout.pending) - self.assertFalse(overr.pending) - self.assertFalse(ovin.pending) - - self.assertEqual(ovin.getresult(), len(msg)) - out = ovout.getresult().rstrip() - err = overr.getresult().rstrip() - - self.assertGreater(len(out), 0) - self.assertGreater(len(err), 0) - # allow for partial reads... - self.assertTrue(msg.upper().rstrip().startswith(out)) - self.assertTrue(b"stderr".startswith(err)) - - # The context manager calls wait() and closes resources - with p: - pass - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py deleted file mode 100644 index 804db91..0000000 --- a/Lib/test/test_asyncio/utils.py +++ /dev/null @@ -1,587 +0,0 @@ -"""Utilities shared by tests.""" - -import asyncio -import collections -import contextlib -import io -import logging -import os -import re -import selectors -import socket -import socketserver -import sys -import tempfile -import threading -import time -import unittest -import weakref - -from unittest import mock - -from http.server import HTTPServer -from wsgiref.simple_server import WSGIRequestHandler, WSGIServer - -try: - import ssl -except ImportError: # pragma: no cover - ssl = None - -from asyncio import base_events -from asyncio import events -from asyncio import format_helpers -from asyncio import futures -from asyncio import tasks -from asyncio.log import logger -from test import support - - -def data_file(filename): - if hasattr(support, 'TEST_HOME_DIR'): - fullname = os.path.join(support.TEST_HOME_DIR, filename) - if os.path.isfile(fullname): - return fullname - fullname = os.path.join(os.path.dirname(__file__), '..', filename) - if os.path.isfile(fullname): - return fullname - raise FileNotFoundError(filename) - - -ONLYCERT = data_file('ssl_cert.pem') -ONLYKEY = data_file('ssl_key.pem') -SIGNED_CERTFILE = data_file('keycert3.pem') -SIGNING_CA = data_file('pycacert.pem') -PEERCERT = { - 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',), - 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',), - 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',), - 'issuer': ((('countryName', 'XY'),), - (('organizationName', 'Python Software Foundation CA'),), - (('commonName', 'our-ca-server'),)), - 'notAfter': 'Jul 7 14:23:16 2028 GMT', - 'notBefore': 'Aug 29 14:23:16 2018 GMT', - 'serialNumber': 'CB2D80995A69525C', - 'subject': ((('countryName', 'XY'),), - (('localityName', 'Castle Anthrax'),), - (('organizationName', 'Python Software Foundation'),), - (('commonName', 'localhost'),)), - 'subjectAltName': (('DNS', 'localhost'),), - 'version': 3 -} - - -def simple_server_sslcontext(): - server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - server_context.load_cert_chain(ONLYCERT, ONLYKEY) - server_context.check_hostname = False - server_context.verify_mode = ssl.CERT_NONE - return server_context - - -def simple_client_sslcontext(*, disable_verify=True): - client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - client_context.check_hostname = False - if disable_verify: - client_context.verify_mode = ssl.CERT_NONE - return client_context - - -def dummy_ssl_context(): - if ssl is None: - return None - else: - return ssl.SSLContext(ssl.PROTOCOL_TLS) - - -def run_briefly(loop): - async def once(): - pass - gen = once() - t = loop.create_task(gen) - # Don't log a warning if the task is not done after run_until_complete(). - # It occurs if the loop is stopped or if a task raises a BaseException. - t._log_destroy_pending = False - try: - loop.run_until_complete(t) - finally: - gen.close() - - -def run_until(loop, pred, timeout=support.SHORT_TIMEOUT): - deadline = time.monotonic() + timeout - while not pred(): - if timeout is not None: - timeout = deadline - time.monotonic() - if timeout <= 0: - raise futures.TimeoutError() - loop.run_until_complete(tasks.sleep(0.001)) - - -def run_once(loop): - """Legacy API to run once through the event loop. - - This is the recommended pattern for test code. It will poll the - selector once and run all callbacks scheduled in response to I/O - events. - """ - loop.call_soon(loop.stop) - loop.run_forever() - - -class SilentWSGIRequestHandler(WSGIRequestHandler): - - def get_stderr(self): - return io.StringIO() - - def log_message(self, format, *args): - pass - - -class SilentWSGIServer(WSGIServer): - - request_timeout = support.LOOPBACK_TIMEOUT - - def get_request(self): - request, client_addr = super().get_request() - request.settimeout(self.request_timeout) - return request, client_addr - - def handle_error(self, request, client_address): - pass - - -class SSLWSGIServerMixin: - - def finish_request(self, request, client_address): - # The relative location of our test directory (which - # contains the ssl key and certificate files) differs - # between the stdlib and stand-alone asyncio. - # Prefer our own if we can find it. - context = ssl.SSLContext() - context.load_cert_chain(ONLYCERT, ONLYKEY) - - ssock = context.wrap_socket(request, server_side=True) - try: - self.RequestHandlerClass(ssock, client_address, self) - ssock.close() - except OSError: - # maybe socket has been closed by peer - pass - - -class SSLWSGIServer(SSLWSGIServerMixin, SilentWSGIServer): - pass - - -def _run_test_server(*, address, use_ssl=False, server_cls, server_ssl_cls): - - def loop(environ): - size = int(environ['CONTENT_LENGTH']) - while size: - data = environ['wsgi.input'].read(min(size, 0x10000)) - yield data - size -= len(data) - - def app(environ, start_response): - status = '200 OK' - headers = [('Content-type', 'text/plain')] - start_response(status, headers) - if environ['PATH_INFO'] == '/loop': - return loop(environ) - else: - return [b'Test message'] - - # Run the test WSGI server in a separate thread in order not to - # interfere with event handling in the main thread - server_class = server_ssl_cls if use_ssl else server_cls - httpd = server_class(address, SilentWSGIRequestHandler) - httpd.set_app(app) - httpd.address = httpd.server_address - server_thread = threading.Thread( - target=lambda: httpd.serve_forever(poll_interval=0.05)) - server_thread.start() - try: - yield httpd - finally: - httpd.shutdown() - httpd.server_close() - server_thread.join() - - -if hasattr(socket, 'AF_UNIX'): - - class UnixHTTPServer(socketserver.UnixStreamServer, HTTPServer): - - def server_bind(self): - socketserver.UnixStreamServer.server_bind(self) - self.server_name = '127.0.0.1' - self.server_port = 80 - - - class UnixWSGIServer(UnixHTTPServer, WSGIServer): - - request_timeout = support.LOOPBACK_TIMEOUT - - def server_bind(self): - UnixHTTPServer.server_bind(self) - self.setup_environ() - - def get_request(self): - request, client_addr = super().get_request() - request.settimeout(self.request_timeout) - # Code in the stdlib expects that get_request - # will return a socket and a tuple (host, port). - # However, this isn't true for UNIX sockets, - # as the second return value will be a path; - # hence we return some fake data sufficient - # to get the tests going - return request, ('127.0.0.1', '') - - - class SilentUnixWSGIServer(UnixWSGIServer): - - def handle_error(self, request, client_address): - pass - - - class UnixSSLWSGIServer(SSLWSGIServerMixin, SilentUnixWSGIServer): - pass - - - def gen_unix_socket_path(): - with tempfile.NamedTemporaryFile() as file: - return file.name - - - @contextlib.contextmanager - def unix_socket_path(): - path = gen_unix_socket_path() - try: - yield path - finally: - try: - os.unlink(path) - except OSError: - pass - - - @contextlib.contextmanager - def run_test_unix_server(*, use_ssl=False): - with unix_socket_path() as path: - yield from _run_test_server(address=path, use_ssl=use_ssl, - server_cls=SilentUnixWSGIServer, - server_ssl_cls=UnixSSLWSGIServer) - - -@contextlib.contextmanager -def run_test_server(*, host='127.0.0.1', port=0, use_ssl=False): - yield from _run_test_server(address=(host, port), use_ssl=use_ssl, - server_cls=SilentWSGIServer, - server_ssl_cls=SSLWSGIServer) - - -def make_test_protocol(base): - dct = {} - for name in dir(base): - if name.startswith('__') and name.endswith('__'): - # skip magic names - continue - dct[name] = MockCallback(return_value=None) - return type('TestProtocol', (base,) + base.__bases__, dct)() - - -class TestSelector(selectors.BaseSelector): - - def __init__(self): - self.keys = {} - - def register(self, fileobj, events, data=None): - key = selectors.SelectorKey(fileobj, 0, events, data) - self.keys[fileobj] = key - return key - - def unregister(self, fileobj): - return self.keys.pop(fileobj) - - def select(self, timeout): - return [] - - def get_map(self): - return self.keys - - -class TestLoop(base_events.BaseEventLoop): - """Loop for unittests. - - It manages self time directly. - If something scheduled to be executed later then - on next loop iteration after all ready handlers done - generator passed to __init__ is calling. - - Generator should be like this: - - def gen(): - ... - when = yield ... - ... = yield time_advance - - Value returned by yield is absolute time of next scheduled handler. - Value passed to yield is time advance to move loop's time forward. - """ - - def __init__(self, gen=None): - super().__init__() - - if gen is None: - def gen(): - yield - self._check_on_close = False - else: - self._check_on_close = True - - self._gen = gen() - next(self._gen) - self._time = 0 - self._clock_resolution = 1e-9 - self._timers = [] - self._selector = TestSelector() - - self.readers = {} - self.writers = {} - self.reset_counters() - - self._transports = weakref.WeakValueDictionary() - - def time(self): - return self._time - - def advance_time(self, advance): - """Move test time forward.""" - if advance: - self._time += advance - - def close(self): - super().close() - if self._check_on_close: - try: - self._gen.send(0) - except StopIteration: - pass - else: # pragma: no cover - raise AssertionError("Time generator is not finished") - - def _add_reader(self, fd, callback, *args): - self.readers[fd] = events.Handle(callback, args, self, None) - - def _remove_reader(self, fd): - self.remove_reader_count[fd] += 1 - if fd in self.readers: - del self.readers[fd] - return True - else: - return False - - def assert_reader(self, fd, callback, *args): - if fd not in self.readers: - raise AssertionError(f'fd {fd} is not registered') - handle = self.readers[fd] - if handle._callback != callback: - raise AssertionError( - f'unexpected callback: {handle._callback} != {callback}') - if handle._args != args: - raise AssertionError( - f'unexpected callback args: {handle._args} != {args}') - - def assert_no_reader(self, fd): - if fd in self.readers: - raise AssertionError(f'fd {fd} is registered') - - def _add_writer(self, fd, callback, *args): - self.writers[fd] = events.Handle(callback, args, self, None) - - def _remove_writer(self, fd): - self.remove_writer_count[fd] += 1 - if fd in self.writers: - del self.writers[fd] - return True - else: - return False - - def assert_writer(self, fd, callback, *args): - assert fd in self.writers, 'fd {} is not registered'.format(fd) - handle = self.writers[fd] - assert handle._callback == callback, '{!r} != {!r}'.format( - handle._callback, callback) - assert handle._args == args, '{!r} != {!r}'.format( - handle._args, args) - - def _ensure_fd_no_transport(self, fd): - if not isinstance(fd, int): - try: - fd = int(fd.fileno()) - except (AttributeError, TypeError, ValueError): - # This code matches selectors._fileobj_to_fd function. - raise ValueError("Invalid file object: " - "{!r}".format(fd)) from None - try: - transport = self._transports[fd] - except KeyError: - pass - else: - raise RuntimeError( - 'File descriptor {!r} is used by transport {!r}'.format( - fd, transport)) - - def add_reader(self, fd, callback, *args): - """Add a reader callback.""" - self._ensure_fd_no_transport(fd) - return self._add_reader(fd, callback, *args) - - def remove_reader(self, fd): - """Remove a reader callback.""" - self._ensure_fd_no_transport(fd) - return self._remove_reader(fd) - - def add_writer(self, fd, callback, *args): - """Add a writer callback..""" - self._ensure_fd_no_transport(fd) - return self._add_writer(fd, callback, *args) - - def remove_writer(self, fd): - """Remove a writer callback.""" - self._ensure_fd_no_transport(fd) - return self._remove_writer(fd) - - def reset_counters(self): - self.remove_reader_count = collections.defaultdict(int) - self.remove_writer_count = collections.defaultdict(int) - - def _run_once(self): - super()._run_once() - for when in self._timers: - advance = self._gen.send(when) - self.advance_time(advance) - self._timers = [] - - def call_at(self, when, callback, *args, context=None): - self._timers.append(when) - return super().call_at(when, callback, *args, context=context) - - def _process_events(self, event_list): - return - - def _write_to_self(self): - pass - - -def MockCallback(**kwargs): - return mock.Mock(spec=['__call__'], **kwargs) - - -class MockPattern(str): - """A regex based str with a fuzzy __eq__. - - Use this helper with 'mock.assert_called_with', or anywhere - where a regex comparison between strings is needed. - - For instance: - mock_call.assert_called_with(MockPattern('spam.*ham')) - """ - def __eq__(self, other): - return bool(re.search(str(self), other, re.S)) - - -class MockInstanceOf: - def __init__(self, type): - self._type = type - - def __eq__(self, other): - return isinstance(other, self._type) - - -def get_function_source(func): - source = format_helpers._get_function_source(func) - if source is None: - raise ValueError("unable to get the source of %r" % (func,)) - return source - - -class TestCase(unittest.TestCase): - @staticmethod - def close_loop(loop): - if loop._default_executor is not None: - if not loop.is_closed(): - loop.run_until_complete(loop.shutdown_default_executor()) - else: - loop._default_executor.shutdown(wait=True) - loop.close() - policy = support.maybe_get_event_loop_policy() - if policy is not None: - try: - watcher = policy.get_child_watcher() - except NotImplementedError: - # watcher is not implemented by EventLoopPolicy, e.g. Windows - pass - else: - if isinstance(watcher, asyncio.ThreadedChildWatcher): - threads = list(watcher._threads.values()) - for thread in threads: - thread.join() - - def set_event_loop(self, loop, *, cleanup=True): - assert loop is not None - # ensure that the event loop is passed explicitly in asyncio - events.set_event_loop(None) - if cleanup: - self.addCleanup(self.close_loop, loop) - - def new_test_loop(self, gen=None): - loop = TestLoop(gen) - self.set_event_loop(loop) - return loop - - def unpatch_get_running_loop(self): - events._get_running_loop = self._get_running_loop - - def setUp(self): - self._get_running_loop = events._get_running_loop - events._get_running_loop = lambda: None - self._thread_cleanup = support.threading_setup() - - def tearDown(self): - self.unpatch_get_running_loop() - - events.set_event_loop(None) - - # Detect CPython bug #23353: ensure that yield/yield-from is not used - # in an except block of a generator - self.assertEqual(sys.exc_info(), (None, None, None)) - - self.doCleanups() - support.threading_cleanup(*self._thread_cleanup) - support.reap_children() - - -@contextlib.contextmanager -def disable_logger(): - """Context manager to disable asyncio logger. - - For example, it can be used to ignore warnings in debug mode. - """ - old_level = logger.level - try: - logger.setLevel(logging.CRITICAL+1) - yield - finally: - logger.setLevel(old_level) - - -def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM, - family=socket.AF_INET): - """Create a mock of a non-blocking socket.""" - sock = mock.MagicMock(socket.socket) - sock.proto = proto - sock.type = type - sock.family = family - sock.gettimeout.return_value = 0.0 - return sock |