summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_asyncio
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_asyncio')
-rw-r--r--Lib/test/test_asyncio/__init__.py8
-rw-r--r--Lib/test/test_asyncio/__main__.py4
-rw-r--r--Lib/test/test_asyncio/echo.py8
-rw-r--r--Lib/test/test_asyncio/echo2.py6
-rw-r--r--Lib/test/test_asyncio/echo3.py11
-rw-r--r--Lib/test/test_asyncio/functional.py274
-rw-r--r--Lib/test/test_asyncio/test_base_events.py2160
-rw-r--r--Lib/test/test_asyncio/test_buffered_proto.py89
-rw-r--r--Lib/test/test_asyncio/test_context.py33
-rw-r--r--Lib/test/test_asyncio/test_events.py2777
-rw-r--r--Lib/test/test_asyncio/test_futures.py865
-rw-r--r--Lib/test/test_asyncio/test_locks.py1101
-rw-r--r--Lib/test/test_asyncio/test_pep492.py223
-rw-r--r--Lib/test/test_asyncio/test_proactor_events.py1004
-rw-r--r--Lib/test/test_asyncio/test_protocols.py57
-rw-r--r--Lib/test/test_asyncio/test_queues.py718
-rw-r--r--Lib/test/test_asyncio/test_runners.py179
-rw-r--r--Lib/test/test_asyncio/test_selector_events.py1373
-rw-r--r--Lib/test/test_asyncio/test_sendfile.py555
-rw-r--r--Lib/test/test_asyncio/test_server.py133
-rw-r--r--Lib/test/test_asyncio/test_sock_lowlevel.py343
-rw-r--r--Lib/test/test_asyncio/test_sslproto.py778
-rw-r--r--Lib/test/test_asyncio/test_streams.py992
-rw-r--r--Lib/test/test_asyncio/test_subprocess.py743
-rw-r--r--Lib/test/test_asyncio/test_tasks.py3375
-rw-r--r--Lib/test/test_asyncio/test_transports.py97
-rw-r--r--Lib/test/test_asyncio/test_unix_events.py1966
-rw-r--r--Lib/test/test_asyncio/test_windows_events.py247
-rw-r--r--Lib/test/test_asyncio/test_windows_utils.py132
-rw-r--r--Lib/test/test_asyncio/utils.py587
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