mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
10
third_party/python/Lib/test/test_asyncio/__init__.py
vendored
Normal file
10
third_party/python/Lib/test/test_asyncio/__init__.py
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
import os
|
||||
from test.support import load_package_tests, import_module
|
||||
|
||||
# Skip tests if we don't have threading.
|
||||
import_module('threading')
|
||||
# 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)
|
4
third_party/python/Lib/test/test_asyncio/__main__.py
vendored
Normal file
4
third_party/python/Lib/test/test_asyncio/__main__.py
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
8
third_party/python/Lib/test/test_asyncio/echo.py
vendored
Normal file
8
third_party/python/Lib/test/test_asyncio/echo.py
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
while True:
|
||||
buf = os.read(0, 1024)
|
||||
if not buf:
|
||||
break
|
||||
os.write(1, buf)
|
6
third_party/python/Lib/test/test_asyncio/echo2.py
vendored
Normal file
6
third_party/python/Lib/test/test_asyncio/echo2.py
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
buf = os.read(0, 1024)
|
||||
os.write(1, b'OUT:'+buf)
|
||||
os.write(2, b'ERR:'+buf)
|
11
third_party/python/Lib/test/test_asyncio/echo3.py
vendored
Normal file
11
third_party/python/Lib/test/test_asyncio/echo3.py
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
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'))
|
1875
third_party/python/Lib/test/test_asyncio/test_base_events.py
vendored
Normal file
1875
third_party/python/Lib/test/test_asyncio/test_base_events.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
2832
third_party/python/Lib/test/test_asyncio/test_events.py
vendored
Normal file
2832
third_party/python/Lib/test/test_asyncio/test_events.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
692
third_party/python/Lib/test/test_asyncio/test_futures.py
vendored
Normal file
692
third_party/python/Lib/test/test_asyncio/test_futures.py
vendored
Normal file
|
@ -0,0 +1,692 @@
|
|||
"""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 test_utils
|
||||
from asyncio import futures
|
||||
try:
|
||||
from test import support
|
||||
except ImportError:
|
||||
from asyncio import test_support as support
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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):
|
||||
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)
|
||||
with self.assertRaises((RuntimeError, AttributeError)):
|
||||
fut._schedule_callbacks()
|
||||
fut = self.cls.__new__(self.cls, loop=self.loop)
|
||||
try:
|
||||
repr(fut)
|
||||
except AttributeError:
|
||||
pass
|
||||
fut = self.cls.__new__(self.cls, loop=self.loop)
|
||||
fut.cancelled()
|
||||
fut.done()
|
||||
iter(fut)
|
||||
|
||||
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),
|
||||
'<Future pending created at %s:%s>'
|
||||
% (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), '<Future pending>')
|
||||
f_pending.cancel()
|
||||
|
||||
f_cancelled = self._new_future(loop=self.loop)
|
||||
f_cancelled.cancel()
|
||||
self.assertEqual(repr(f_cancelled), '<Future cancelled>')
|
||||
|
||||
f_result = self._new_future(loop=self.loop)
|
||||
f_result.set_result(4)
|
||||
self.assertEqual(repr(f_result), '<Future 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),
|
||||
'<Future 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'<Future pending cb=\[%s\]>' % fake_repr)
|
||||
f_one_callbacks.cancel()
|
||||
self.assertEqual(repr(f_one_callbacks),
|
||||
'<Future 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'<Future 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'<Future pending cb=\[%s\]>' % cb_regex)
|
||||
f_many_callbacks.cancel()
|
||||
self.assertEqual(repr(f_many_callbacks),
|
||||
'<Future 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()
|
||||
|
||||
self.assertRaises(AssertionError, test)
|
||||
fut.cancel()
|
||||
|
||||
@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 = r'^Future 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):
|
||||
cls = getattr(futures, '_CFuture')
|
||||
|
||||
|
||||
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_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)
|
||||
|
||||
|
||||
class PyFutureDoneCallbackTests(BaseFutureDoneCallbackTests,
|
||||
test_utils.TestCase):
|
||||
|
||||
def _new_future(self):
|
||||
return futures._PyFuture(loop=self.loop)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
1016
third_party/python/Lib/test/test_asyncio/test_locks.py
vendored
Normal file
1016
third_party/python/Lib/test/test_asyncio/test_locks.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
232
third_party/python/Lib/test/test_asyncio/test_pep492.py
vendored
Normal file
232
third_party/python/Lib/test/test_asyncio/test_pep492.py
vendored
Normal file
|
@ -0,0 +1,232 @@
|
|||
"""Tests support for new syntax introduced by PEP 492."""
|
||||
|
||||
import collections.abc
|
||||
import types
|
||||
import unittest
|
||||
|
||||
try:
|
||||
from test import support
|
||||
except ImportError:
|
||||
from asyncio import test_support as support
|
||||
from unittest import mock
|
||||
|
||||
import asyncio
|
||||
from asyncio import test_utils
|
||||
|
||||
|
||||
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):
|
||||
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, loop=self.loop)
|
||||
self.assertFalse(lock.locked())
|
||||
async with lock as _lock:
|
||||
self.assertIs(_lock, None)
|
||||
self.assertTrue(lock.locked())
|
||||
await asyncio.sleep(0.01, loop=self.loop)
|
||||
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):
|
||||
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, loop=self.loop)
|
||||
self.assertFalse(lock.locked())
|
||||
with await lock as _lock:
|
||||
self.assertIs(_lock, None)
|
||||
self.assertTrue(lock.locked())
|
||||
await asyncio.sleep(0.01, loop=self.loop)
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
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',)
|
||||
|
||||
@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')
|
||||
|
||||
@mock.patch('asyncio.coroutines.logger')
|
||||
def test_async_def_wrapped(self, m_log):
|
||||
async def foo():
|
||||
pass
|
||||
async def start():
|
||||
foo_coro = foo()
|
||||
self.assertRegex(
|
||||
repr(foo_coro),
|
||||
r'<CoroWrapper .*\.foo\(\) running at .*pep492.*>')
|
||||
|
||||
with support.check_warnings((r'.*foo.*was never',
|
||||
RuntimeWarning)):
|
||||
foo_coro = None
|
||||
support.gc_collect()
|
||||
self.assertTrue(m_log.error.called)
|
||||
message = m_log.error.call_args[0][0]
|
||||
self.assertRegex(message,
|
||||
r'CoroWrapper.*foo.*was never')
|
||||
|
||||
self.loop.set_debug(True)
|
||||
self.loop.run_until_complete(start())
|
||||
|
||||
async def start():
|
||||
foo_coro = foo()
|
||||
task = asyncio.ensure_future(foo_coro, loop=self.loop)
|
||||
self.assertRegex(repr(task), r'Task.*foo.*running')
|
||||
|
||||
self.loop.run_until_complete(start())
|
||||
|
||||
|
||||
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, loop=self.loop)
|
||||
|
||||
async def runner():
|
||||
coro = afunc()
|
||||
t = asyncio.Task(coro, loop=self.loop)
|
||||
try:
|
||||
await asyncio.sleep(0, loop=self.loop)
|
||||
await coro
|
||||
finally:
|
||||
t.cancel()
|
||||
|
||||
self.loop.set_debug(True)
|
||||
with self.assertRaisesRegex(
|
||||
RuntimeError,
|
||||
r'Cannot await.*test_double_await.*\bafunc\b.*while.*\bsleep\b'):
|
||||
|
||||
self.loop.run_until_complete(runner())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
605
third_party/python/Lib/test/test_asyncio/test_proactor_events.py
vendored
Normal file
605
third_party/python/Lib/test/test_asyncio/test_proactor_events.py
vendored
Normal file
|
@ -0,0 +1,605 @@
|
|||
"""Tests for proactor_events.py"""
|
||||
|
||||
import socket
|
||||
import unittest
|
||||
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 import test_utils
|
||||
|
||||
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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, 4096)
|
||||
|
||||
def test_loop_reading(self):
|
||||
tr = self.socket_transport()
|
||||
tr._loop_reading()
|
||||
self.loop._proactor.recv.assert_called_with(self.sock, 4096)
|
||||
self.assertFalse(self.protocol.data_received.called)
|
||||
self.assertFalse(self.protocol.eof_received.called)
|
||||
|
||||
def test_loop_reading_data(self):
|
||||
res = asyncio.Future(loop=self.loop)
|
||||
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, 4096)
|
||||
self.protocol.data_received.assert_called_with(b'data')
|
||||
|
||||
def test_loop_reading_no_data(self):
|
||||
res = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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_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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
f.set_result(msg)
|
||||
futures.append(f)
|
||||
|
||||
self.loop._proactor.recv.side_effect = futures
|
||||
self.loop._run_once()
|
||||
self.assertFalse(tr._paused)
|
||||
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)
|
||||
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.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()
|
||||
|
||||
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 immedialty,
|
||||
# it should not pause writing
|
||||
fut = asyncio.Future(loop=self.loop)
|
||||
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 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()
|
||||
|
||||
class EventLoop(BaseProactorEventLoop):
|
||||
def _socketpair(s):
|
||||
return (self.ssock, self.csock)
|
||||
|
||||
self.loop = EventLoop(self.proactor)
|
||||
self.set_event_loop(self.loop)
|
||||
|
||||
@mock.patch.object(BaseProactorEventLoop, 'call_soon')
|
||||
@mock.patch.object(BaseProactorEventLoop, '_socketpair')
|
||||
def test_ctor(self, socketpair, call_soon):
|
||||
ssock, csock = socketpair.return_value = (
|
||||
mock.Mock(), mock.Mock())
|
||||
loop = BaseProactorEventLoop(self.proactor)
|
||||
self.assertIs(loop._ssock, ssock)
|
||||
self.assertIs(loop._csock, csock)
|
||||
self.assertEqual(loop._internal_fds, 1)
|
||||
call_soon.assert_called_with(loop._loop_self_reading)
|
||||
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_sock_recv(self):
|
||||
self.loop.sock_recv(self.sock, 1024)
|
||||
self.proactor.recv.assert_called_with(self.sock, 1024)
|
||||
|
||||
def test_sock_sendall(self):
|
||||
self.loop.sock_sendall(self.sock, b'data')
|
||||
self.proactor.send.assert_called_with(self.sock, b'data')
|
||||
|
||||
def test_sock_connect(self):
|
||||
self.loop.sock_connect(self.sock, ('1.2.3.4', 123))
|
||||
self.proactor.connect.assert_called_with(self.sock, ('1.2.3.4', 123))
|
||||
|
||||
def test_sock_accept(self):
|
||||
self.loop.sock_accept(self.sock)
|
||||
self.proactor.accept.assert_called_with(self.sock)
|
||||
|
||||
def test_socketpair(self):
|
||||
class EventLoop(BaseProactorEventLoop):
|
||||
# override the destructor to not log a ResourceWarning
|
||||
def __del__(self):
|
||||
pass
|
||||
self.assertRaises(
|
||||
NotImplementedError, EventLoop, self.proactor)
|
||||
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
fut.cancel()
|
||||
loop(fut)
|
||||
self.assertTrue(self.sock.close.called)
|
||||
|
||||
def test_stop_serving(self):
|
||||
sock = mock.Mock()
|
||||
self.loop._stop_serving(sock)
|
||||
self.assertTrue(sock.close.called)
|
||||
self.proactor._stop_serving.assert_called_with(sock)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
643
third_party/python/Lib/test/test_asyncio/test_queues.py
vendored
Normal file
643
third_party/python/Lib/test/test_asyncio/test_queues.py
vendored
Normal file
|
@ -0,0 +1,643 @@
|
|||
"""Tests for queues.py"""
|
||||
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import asyncio
|
||||
from asyncio import test_utils
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_getter():
|
||||
q = asyncio.Queue(loop=loop)
|
||||
# Start a task that waits to get.
|
||||
asyncio.Task(q.get(), loop=loop)
|
||||
# Let it start waiting.
|
||||
yield from asyncio.sleep(0.1, loop=loop)
|
||||
self.assertTrue('_getters[1]' in fn(q))
|
||||
# resume q.get coroutine to finish generator
|
||||
q.put_nowait(0)
|
||||
|
||||
loop.run_until_complete(add_getter())
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_putter():
|
||||
q = asyncio.Queue(maxsize=1, loop=loop)
|
||||
q.put_nowait(1)
|
||||
# Start a task that waits to put.
|
||||
asyncio.Task(q.put(2), loop=loop)
|
||||
# Let it start waiting.
|
||||
yield from asyncio.sleep(0.1, loop=loop)
|
||||
self.assertTrue('_putters[1]' in fn(q))
|
||||
# resume q.put coroutine to finish generator
|
||||
q.get_nowait()
|
||||
|
||||
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()
|
||||
q = asyncio.Queue(loop=loop)
|
||||
self.assertIs(q._loop, loop)
|
||||
|
||||
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):
|
||||
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):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
self.assertFalse(q.full())
|
||||
|
||||
q = asyncio.Queue(maxsize=1, loop=self.loop)
|
||||
q.put_nowait(1)
|
||||
self.assertTrue(q.full())
|
||||
|
||||
def test_order(self):
|
||||
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)
|
||||
|
||||
q = asyncio.Queue(maxsize=2, loop=loop)
|
||||
self.assertEqual(2, q.maxsize)
|
||||
have_been_put = []
|
||||
|
||||
@asyncio.coroutine
|
||||
def putter():
|
||||
for i in range(3):
|
||||
yield from q.put(i)
|
||||
have_been_put.append(i)
|
||||
return True
|
||||
|
||||
@asyncio.coroutine
|
||||
def test():
|
||||
t = asyncio.Task(putter(), loop=loop)
|
||||
yield from asyncio.sleep(0.01, loop=loop)
|
||||
|
||||
# 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.
|
||||
yield from asyncio.sleep(0.01, loop=loop)
|
||||
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):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
q.put_nowait(1)
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_get():
|
||||
return (yield from q.get())
|
||||
|
||||
res = self.loop.run_until_complete(queue_get())
|
||||
self.assertEqual(1, res)
|
||||
|
||||
def test_get_with_putters(self):
|
||||
q = asyncio.Queue(1, loop=self.loop)
|
||||
q.put_nowait(1)
|
||||
|
||||
waiter = asyncio.Future(loop=self.loop)
|
||||
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)
|
||||
|
||||
q = asyncio.Queue(loop=loop)
|
||||
started = asyncio.Event(loop=loop)
|
||||
finished = False
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_get():
|
||||
nonlocal finished
|
||||
started.set()
|
||||
res = yield from q.get()
|
||||
finished = True
|
||||
return res
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_put():
|
||||
loop.call_later(0.01, q.put_nowait, 1)
|
||||
queue_get_task = asyncio.Task(queue_get(), loop=loop)
|
||||
yield from started.wait()
|
||||
self.assertFalse(finished)
|
||||
res = yield from 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):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
q.put_nowait(1)
|
||||
self.assertEqual(1, q.get_nowait())
|
||||
|
||||
def test_nonblocking_get_exception(self):
|
||||
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)
|
||||
|
||||
q = asyncio.Queue(loop=loop)
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_get():
|
||||
return (yield from asyncio.wait_for(q.get(), 0.051, loop=loop))
|
||||
|
||||
@asyncio.coroutine
|
||||
def test():
|
||||
get_task = asyncio.Task(queue_get(), loop=loop)
|
||||
yield from asyncio.sleep(0.01, loop=loop) # let the task start
|
||||
q.put_nowait(1)
|
||||
return (yield from get_task)
|
||||
|
||||
self.assertEqual(1, loop.run_until_complete(test()))
|
||||
self.assertAlmostEqual(0.06, loop.time())
|
||||
|
||||
def test_get_cancelled_race(self):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
|
||||
t1 = asyncio.Task(q.get(), loop=self.loop)
|
||||
t2 = asyncio.Task(q.get(), loop=self.loop)
|
||||
|
||||
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):
|
||||
q = asyncio.Queue(loop=self.loop, maxsize=1)
|
||||
asyncio.Task(q.put('a'), loop=self.loop)
|
||||
asyncio.Task(q.put('b'), loop=self.loop)
|
||||
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.
|
||||
|
||||
@asyncio.coroutine
|
||||
def consumer(queue, num_expected):
|
||||
for _ in range(num_expected):
|
||||
yield from queue.get()
|
||||
|
||||
@asyncio.coroutine
|
||||
def producer(queue, num_items):
|
||||
for i in range(num_items):
|
||||
yield from queue.put(i)
|
||||
|
||||
queue_size = 1
|
||||
producer_num_items = 5
|
||||
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)
|
||||
@asyncio.coroutine
|
||||
def consumer(queue):
|
||||
try:
|
||||
item = yield from asyncio.wait_for(queue.get(), 0.1, loop=self.loop)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
|
||||
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):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_put():
|
||||
# No maxsize, won't block.
|
||||
yield from 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)
|
||||
|
||||
q = asyncio.Queue(maxsize=1, loop=loop)
|
||||
started = asyncio.Event(loop=loop)
|
||||
finished = False
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_put():
|
||||
nonlocal finished
|
||||
started.set()
|
||||
yield from q.put(1)
|
||||
yield from q.put(2)
|
||||
finished = True
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_get():
|
||||
loop.call_later(0.01, q.get_nowait)
|
||||
queue_put_task = asyncio.Task(queue_put(), loop=loop)
|
||||
yield from started.wait()
|
||||
self.assertFalse(finished)
|
||||
yield from queue_put_task
|
||||
self.assertTrue(finished)
|
||||
|
||||
loop.run_until_complete(queue_get())
|
||||
self.assertAlmostEqual(0.01, loop.time())
|
||||
|
||||
def test_nonblocking_put(self):
|
||||
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)
|
||||
|
||||
q = asyncio.Queue(loop=loop)
|
||||
|
||||
reader = loop.create_task(q.get())
|
||||
|
||||
loop.run_until_complete(asyncio.sleep(0.01, loop=loop))
|
||||
|
||||
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)
|
||||
|
||||
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, loop=loop))
|
||||
|
||||
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)
|
||||
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, loop=loop))
|
||||
|
||||
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):
|
||||
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):
|
||||
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)
|
||||
|
||||
q = asyncio.Queue(maxsize=1.3, loop=self.loop)
|
||||
@asyncio.coroutine
|
||||
def queue_put():
|
||||
yield from q.put(1)
|
||||
yield from q.put(2)
|
||||
self.assertTrue(q.full())
|
||||
self.loop.run_until_complete(queue_put())
|
||||
|
||||
def test_put_cancelled(self):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
|
||||
@asyncio.coroutine
|
||||
def queue_put():
|
||||
yield from q.put(1)
|
||||
return True
|
||||
|
||||
@asyncio.coroutine
|
||||
def test():
|
||||
return (yield from q.get())
|
||||
|
||||
t = asyncio.Task(queue_put(), loop=self.loop)
|
||||
self.assertEqual(1, self.loop.run_until_complete(test()))
|
||||
self.assertTrue(t.done())
|
||||
self.assertTrue(t.result())
|
||||
|
||||
def test_put_cancelled_race(self):
|
||||
q = asyncio.Queue(loop=self.loop, maxsize=1)
|
||||
|
||||
put_a = asyncio.Task(q.put('a'), loop=self.loop)
|
||||
put_b = asyncio.Task(q.put('b'), loop=self.loop)
|
||||
put_c = asyncio.Task(q.put('X'), loop=self.loop)
|
||||
|
||||
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):
|
||||
q = asyncio.Queue(loop=self.loop)
|
||||
t = asyncio.Task(q.get(), loop=self.loop)
|
||||
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.
|
||||
|
||||
queue = asyncio.Queue(2, loop=self.loop)
|
||||
|
||||
@asyncio.coroutine
|
||||
def putter(item):
|
||||
yield from queue.put(item)
|
||||
|
||||
@asyncio.coroutine
|
||||
def getter():
|
||||
yield
|
||||
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))
|
||||
|
||||
|
||||
class LifoQueueTests(_QueueTestBase):
|
||||
|
||||
def test_order(self):
|
||||
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):
|
||||
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):
|
||||
q = self.q_class(loop=self.loop)
|
||||
self.assertRaises(ValueError, q.task_done)
|
||||
|
||||
def test_task_done(self):
|
||||
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
|
||||
|
||||
@asyncio.coroutine
|
||||
def worker():
|
||||
nonlocal accumulator
|
||||
|
||||
while running:
|
||||
item = yield from q.get()
|
||||
accumulator += item
|
||||
q.task_done()
|
||||
|
||||
@asyncio.coroutine
|
||||
def test():
|
||||
tasks = [asyncio.Task(worker(), loop=self.loop)
|
||||
for index in range(2)]
|
||||
|
||||
yield from 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, loop=self.loop))
|
||||
|
||||
def test_join_empty_queue(self):
|
||||
q = self.q_class(loop=self.loop)
|
||||
|
||||
# Test that a queue join()s successfully, and before anything else
|
||||
# (done twice for insurance).
|
||||
|
||||
@asyncio.coroutine
|
||||
def join():
|
||||
yield from q.join()
|
||||
yield from q.join()
|
||||
|
||||
self.loop.run_until_complete(join())
|
||||
|
||||
def test_format(self):
|
||||
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()
|
1861
third_party/python/Lib/test/test_asyncio/test_selector_events.py
vendored
Normal file
1861
third_party/python/Lib/test/test_asyncio/test_selector_events.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
151
third_party/python/Lib/test/test_asyncio/test_sslproto.py
vendored
Normal file
151
third_party/python/Lib/test/test_asyncio/test_sslproto.py
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
"""Tests for asyncio/sslproto.py."""
|
||||
|
||||
import logging
|
||||
import unittest
|
||||
from unittest import mock
|
||||
try:
|
||||
import ssl
|
||||
except ImportError:
|
||||
ssl = None
|
||||
|
||||
import asyncio
|
||||
from asyncio import log
|
||||
from asyncio import sslproto
|
||||
from asyncio import test_utils
|
||||
|
||||
|
||||
@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)
|
||||
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_cancel_handshake(self):
|
||||
# Python issue #23197: cancelling a handshake must not raise an
|
||||
# exception or log an error, even if the handshake failed
|
||||
waiter = asyncio.Future(loop=self.loop)
|
||||
ssl_proto = self.ssl_protocol(waiter=waiter)
|
||||
handshake_fut = asyncio.Future(loop=self.loop)
|
||||
|
||||
def do_handshake(callback):
|
||||
exc = Exception()
|
||||
callback(exc)
|
||||
handshake_fut.set_result(None)
|
||||
return []
|
||||
|
||||
waiter.cancel()
|
||||
|
||||
with test_utils.disable_logger():
|
||||
self.connection_made(ssl_proto, do_handshake=do_handshake)
|
||||
self.loop.run_until_complete(handshake_fut)
|
||||
|
||||
def test_eof_received_waiter(self):
|
||||
waiter = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
868
third_party/python/Lib/test/test_asyncio/test_streams.py
vendored
Normal file
868
third_party/python/Lib/test/test_asyncio/test_streams.py
vendored
Normal file
|
@ -0,0 +1,868 @@
|
|||
"""Tests for streams.py."""
|
||||
|
||||
import gc
|
||||
import os
|
||||
import queue
|
||||
import pickle
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import unittest
|
||||
from unittest import mock
|
||||
try:
|
||||
import ssl
|
||||
except ImportError:
|
||||
ssl = None
|
||||
|
||||
import asyncio
|
||||
from asyncio import test_utils
|
||||
|
||||
|
||||
class StreamReaderTests(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):
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
|
||||
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):
|
||||
try:
|
||||
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()
|
||||
|
||||
@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)
|
||||
|
||||
@unittest.skipIf(ssl is None, 'No ssl module')
|
||||
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
|
||||
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):
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
|
||||
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 = asyncio.Task(stream.read(30), loop=self.loop)
|
||||
|
||||
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 = asyncio.Task(stream.read(1024), loop=self.loop)
|
||||
|
||||
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 = asyncio.Task(stream.read(-1), loop=self.loop)
|
||||
|
||||
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 = asyncio.Task(stream.readline(), loop=self.loop)
|
||||
|
||||
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 = asyncio.Task(stream.readexactly(n), loop=self.loop)
|
||||
|
||||
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 = asyncio.Task(stream.readexactly(n), loop=self.loop)
|
||||
|
||||
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)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_err():
|
||||
stream.set_exception(ValueError())
|
||||
|
||||
t1 = asyncio.Task(stream.readline(), loop=self.loop)
|
||||
t2 = asyncio.Task(set_err(), loop=self.loop)
|
||||
|
||||
self.loop.run_until_complete(asyncio.wait([t1, t2], loop=self.loop))
|
||||
|
||||
self.assertRaises(ValueError, t1.result)
|
||||
|
||||
def test_exception_cancel(self):
|
||||
stream = asyncio.StreamReader(loop=self.loop)
|
||||
|
||||
t = asyncio.Task(stream.readline(), loop=self.loop)
|
||||
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
|
||||
|
||||
@asyncio.coroutine
|
||||
def handle_client(self, client_reader, client_writer):
|
||||
data = yield from client_reader.readline()
|
||||
client_writer.write(data)
|
||||
yield from client_writer.drain()
|
||||
client_writer.close()
|
||||
|
||||
def start(self):
|
||||
sock = socket.socket()
|
||||
sock.bind(('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.socket()
|
||||
sock.bind(('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
|
||||
|
||||
@asyncio.coroutine
|
||||
def client(addr):
|
||||
reader, writer = yield from asyncio.open_connection(
|
||||
*addr, loop=self.loop)
|
||||
# send a line
|
||||
writer.write(b"hello world!\n")
|
||||
# read it back
|
||||
msgback = yield from reader.readline()
|
||||
writer.close()
|
||||
return msgback
|
||||
|
||||
# test the server variant with a coroutine as client handler
|
||||
server = MyServer(self.loop)
|
||||
addr = server.start()
|
||||
msg = self.loop.run_until_complete(asyncio.Task(client(addr),
|
||||
loop=self.loop))
|
||||
server.stop()
|
||||
self.assertEqual(msg, b"hello world!\n")
|
||||
|
||||
# test the server variant with a callback as client handler
|
||||
server = MyServer(self.loop)
|
||||
addr = server.start_callback()
|
||||
msg = self.loop.run_until_complete(asyncio.Task(client(addr),
|
||||
loop=self.loop))
|
||||
server.stop()
|
||||
self.assertEqual(msg, b"hello world!\n")
|
||||
|
||||
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
|
||||
def test_start_unix_server(self):
|
||||
|
||||
class MyServer:
|
||||
|
||||
def __init__(self, loop, path):
|
||||
self.server = None
|
||||
self.loop = loop
|
||||
self.path = path
|
||||
|
||||
@asyncio.coroutine
|
||||
def handle_client(self, client_reader, client_writer):
|
||||
data = yield from client_reader.readline()
|
||||
client_writer.write(data)
|
||||
yield from client_writer.drain()
|
||||
client_writer.close()
|
||||
|
||||
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
|
||||
|
||||
@asyncio.coroutine
|
||||
def client(path):
|
||||
reader, writer = yield from asyncio.open_unix_connection(
|
||||
path, loop=self.loop)
|
||||
# send a line
|
||||
writer.write(b"hello world!\n")
|
||||
# read it back
|
||||
msgback = yield from reader.readline()
|
||||
writer.close()
|
||||
return msgback
|
||||
|
||||
# test the server variant with a coroutine as client handler
|
||||
with test_utils.unix_socket_path() as path:
|
||||
server = MyServer(self.loop, path)
|
||||
server.start()
|
||||
msg = self.loop.run_until_complete(asyncio.Task(client(path),
|
||||
loop=self.loop))
|
||||
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)
|
||||
server.start_callback()
|
||||
msg = self.loop.run_until_complete(asyncio.Task(client(path),
|
||||
loop=self.loop))
|
||||
server.stop()
|
||||
self.assertEqual(msg, b"hello world!\n")
|
||||
|
||||
@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},
|
||||
loop=self.loop)
|
||||
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.
|
||||
|
||||
q = queue.Queue()
|
||||
|
||||
def server():
|
||||
# Runs in a separate thread.
|
||||
sock = socket.socket()
|
||||
with sock:
|
||||
sock.bind(('localhost', 0))
|
||||
sock.listen(1)
|
||||
addr = sock.getsockname()
|
||||
q.put(addr)
|
||||
clt, _ = sock.accept()
|
||||
clt.close()
|
||||
|
||||
@asyncio.coroutine
|
||||
def client(host, port):
|
||||
reader, writer = yield from asyncio.open_connection(
|
||||
host, port, loop=self.loop)
|
||||
|
||||
while True:
|
||||
writer.write(b"foo\n")
|
||||
yield from 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, 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()
|
||||
|
||||
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 l=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 e=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 w=<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 t=<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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
533
third_party/python/Lib/test/test_asyncio/test_subprocess.py
vendored
Normal file
533
third_party/python/Lib/test/test_asyncio/test_subprocess.py
vendored
Normal file
|
@ -0,0 +1,533 @@
|
|||
import signal
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
from unittest import mock
|
||||
|
||||
import asyncio
|
||||
from asyncio import base_subprocess
|
||||
from asyncio import subprocess
|
||||
from asyncio import test_utils
|
||||
try:
|
||||
from test import support
|
||||
except ImportError:
|
||||
from asyncio import test_support as 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)'))]
|
||||
|
||||
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
|
||||
|
||||
|
||||
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 = asyncio.Future(loop=self.loop)
|
||||
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()
|
||||
|
||||
|
||||
class SubprocessMixin:
|
||||
|
||||
def test_stdin_stdout(self):
|
||||
args = PROGRAM_CAT
|
||||
|
||||
@asyncio.coroutine
|
||||
def run(data):
|
||||
proc = yield from asyncio.create_subprocess_exec(
|
||||
*args,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
loop=self.loop)
|
||||
|
||||
# feed data
|
||||
proc.stdin.write(data)
|
||||
yield from proc.stdin.drain()
|
||||
proc.stdin.close()
|
||||
|
||||
# get output and exitcode
|
||||
data = yield from proc.stdout.read()
|
||||
exitcode = yield from proc.wait()
|
||||
return (exitcode, data)
|
||||
|
||||
task = run(b'some data')
|
||||
task = asyncio.wait_for(task, 60.0, loop=self.loop)
|
||||
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
|
||||
|
||||
@asyncio.coroutine
|
||||
def run(data):
|
||||
proc = yield from asyncio.create_subprocess_exec(
|
||||
*args,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
loop=self.loop)
|
||||
stdout, stderr = yield from proc.communicate(data)
|
||||
return proc.returncode, stdout
|
||||
|
||||
task = run(b'some data')
|
||||
task = asyncio.wait_for(task, 60.0, loop=self.loop)
|
||||
exitcode, stdout = self.loop.run_until_complete(task)
|
||||
self.assertEqual(exitcode, 0)
|
||||
self.assertEqual(stdout, b'some data')
|
||||
|
||||
def test_shell(self):
|
||||
create = asyncio.create_subprocess_shell('exit 7',
|
||||
loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
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
|
||||
create = asyncio.create_subprocess_shell('exit 8',
|
||||
start_new_session=True,
|
||||
loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
exitcode = self.loop.run_until_complete(proc.wait())
|
||||
self.assertEqual(exitcode, 8)
|
||||
|
||||
def test_kill(self):
|
||||
args = PROGRAM_BLOCKED
|
||||
create = asyncio.create_subprocess_exec(*args, loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
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
|
||||
create = asyncio.create_subprocess_exec(*args, loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
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]
|
||||
create = asyncio.create_subprocess_exec(*args,
|
||||
stdout=subprocess.PIPE,
|
||||
loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
|
||||
@asyncio.coroutine
|
||||
def send_signal(proc):
|
||||
# basic synchronization to wait until the program is sleeping
|
||||
line = yield from proc.stdout.readline()
|
||||
self.assertEqual(line, b'sleeping\n')
|
||||
|
||||
proc.send_signal(signal.SIGHUP)
|
||||
returncode = (yield from 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
|
||||
create = asyncio.create_subprocess_exec(
|
||||
sys.executable, '-c', 'pass',
|
||||
stdin=subprocess.PIPE,
|
||||
loop=self.loop)
|
||||
proc = self.loop.run_until_complete(create)
|
||||
return (proc, large_data)
|
||||
|
||||
def test_stdin_broken_pipe(self):
|
||||
proc, large_data = self.prepare_broken_pipe_test()
|
||||
|
||||
@asyncio.coroutine
|
||||
def write_stdin(proc, data):
|
||||
yield from asyncio.sleep(0.5, loop=self.loop)
|
||||
proc.stdin.write(data)
|
||||
yield from 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
|
||||
with test_utils.disable_logger():
|
||||
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)
|
||||
|
||||
@asyncio.coroutine
|
||||
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
|
||||
|
||||
@asyncio.coroutine
|
||||
def connect_read_pipe_mock(*args, **kw):
|
||||
transport, protocol = yield from 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 = yield from asyncio.create_subprocess_exec(
|
||||
sys.executable, '-c', code,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
limit=limit,
|
||||
loop=self.loop)
|
||||
stdout_transport = proc._transport.get_pipe_transport(1)
|
||||
|
||||
stdout, stderr = yield from 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
|
||||
@asyncio.coroutine
|
||||
def len_message(message):
|
||||
code = 'import sys; data = sys.stdin.read(); print(len(data))'
|
||||
proc = yield from asyncio.create_subprocess_exec(
|
||||
sys.executable, '-c', code,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
close_fds=False,
|
||||
loop=self.loop)
|
||||
stdout, stderr = yield from proc.communicate(message)
|
||||
exitcode = yield from 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):
|
||||
@asyncio.coroutine
|
||||
def empty_input():
|
||||
code = 'import sys; data = sys.stdin.read(); print(len(data))'
|
||||
proc = yield from asyncio.create_subprocess_exec(
|
||||
sys.executable, '-c', code,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
close_fds=False,
|
||||
loop=self.loop)
|
||||
stdout, stderr = yield from proc.communicate(b'')
|
||||
exitcode = yield from 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_cancel_process_wait(self):
|
||||
# Issue #23140: cancel Process.wait()
|
||||
|
||||
@asyncio.coroutine
|
||||
def cancel_wait():
|
||||
proc = yield from asyncio.create_subprocess_exec(
|
||||
*PROGRAM_BLOCKED,
|
||||
loop=self.loop)
|
||||
|
||||
# Create an internal future waiting on the process exit
|
||||
task = self.loop.create_task(proc.wait())
|
||||
self.loop.call_soon(task.cancel)
|
||||
try:
|
||||
yield from task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
# Cancel the future
|
||||
task.cancel()
|
||||
|
||||
# Kill the process and wait until it is done
|
||||
proc.kill()
|
||||
yield from proc.wait()
|
||||
|
||||
self.loop.run_until_complete(cancel_wait())
|
||||
|
||||
def test_cancel_make_subprocess_transport_exec(self):
|
||||
@asyncio.coroutine
|
||||
def cancel_make_transport():
|
||||
coro = asyncio.create_subprocess_exec(*PROGRAM_BLOCKED,
|
||||
loop=self.loop)
|
||||
task = self.loop.create_task(coro)
|
||||
|
||||
self.loop.call_soon(task.cancel)
|
||||
try:
|
||||
yield from 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):
|
||||
@asyncio.coroutine
|
||||
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:
|
||||
yield from 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):
|
||||
@asyncio.coroutine
|
||||
def kill_running():
|
||||
create = self.loop.subprocess_exec(asyncio.SubprocessProtocol,
|
||||
*PROGRAM_BLOCKED)
|
||||
transport, protocol = yield from 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()
|
||||
yield from 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):
|
||||
@asyncio.coroutine
|
||||
def kill_running():
|
||||
create = self.loop.subprocess_exec(asyncio.SubprocessProtocol,
|
||||
*PROGRAM_BLOCKED)
|
||||
transport, protocol = yield from 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()
|
||||
|
||||
def test_popen_error(self):
|
||||
# Issue #24763: check that the subprocess transport is closed
|
||||
# when BaseSubprocessTransport fails
|
||||
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
|
||||
|
||||
create = asyncio.create_subprocess_exec(sys.executable, '-c',
|
||||
'pass', loop=self.loop)
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
with self.assertRaises(exc):
|
||||
self.loop.run_until_complete(create)
|
||||
self.assertEqual(warns, [])
|
||||
|
||||
def test_read_stdout_after_process_exit(self):
|
||||
@asyncio.coroutine
|
||||
def execute():
|
||||
code = '\n'.join(['import sys',
|
||||
'for _ in range(64):',
|
||||
' sys.stdout.write("x" * 4096)',
|
||||
'sys.stdout.flush()',
|
||||
'sys.exit(1)'])
|
||||
|
||||
fut = asyncio.create_subprocess_exec(
|
||||
sys.executable, '-c', code,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
loop=self.loop)
|
||||
|
||||
process = yield from fut
|
||||
while True:
|
||||
data = yield from process.stdout.read(65536)
|
||||
if data:
|
||||
yield from asyncio.sleep(0.3, loop=self.loop)
|
||||
else:
|
||||
break
|
||||
|
||||
self.loop.run_until_complete(execute())
|
||||
|
||||
|
||||
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)
|
||||
self.addCleanup(policy.set_child_watcher, None)
|
||||
|
||||
class SubprocessSafeWatcherTests(SubprocessWatcherMixin,
|
||||
test_utils.TestCase):
|
||||
|
||||
Watcher = unix_events.SafeChildWatcher
|
||||
|
||||
class SubprocessFastWatcherTests(SubprocessWatcherMixin,
|
||||
test_utils.TestCase):
|
||||
|
||||
Watcher = unix_events.FastChildWatcher
|
||||
|
||||
else:
|
||||
# Windows
|
||||
class SubprocessProactorTests(SubprocessMixin, test_utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.loop = asyncio.ProactorEventLoop()
|
||||
self.set_event_loop(self.loop)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
2679
third_party/python/Lib/test/test_asyncio/test_tasks.py
vendored
Normal file
2679
third_party/python/Lib/test/test_asyncio/test_tasks.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
91
third_party/python/Lib/test/test_asyncio/test_transports.py
vendored
Normal file
91
third_party/python/Lib/test/test_asyncio/test_transports.py
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
"""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):
|
||||
transport = asyncio.Transport()
|
||||
transport.write = mock.Mock()
|
||||
|
||||
transport.writelines([b'line1',
|
||||
bytearray(b'line2'),
|
||||
memoryview(b'line3')])
|
||||
self.assertEqual(1, transport.write.call_count)
|
||||
transport.write.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.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()
|
1638
third_party/python/Lib/test/test_asyncio/test_unix_events.py
vendored
Normal file
1638
third_party/python/Lib/test/test_asyncio/test_unix_events.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
164
third_party/python/Lib/test/test_asyncio/test_windows_events.py
vendored
Normal file
164
third_party/python/Lib/test/test_asyncio/test_windows_events.py
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
if sys.platform != 'win32':
|
||||
raise unittest.SkipTest('Windows only')
|
||||
|
||||
import _winapi
|
||||
|
||||
import asyncio
|
||||
from asyncio import _overlapped
|
||||
from asyncio import test_utils
|
||||
from asyncio import windows_events
|
||||
|
||||
|
||||
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 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 = self.loop._socketpair()
|
||||
trans = self.loop._make_socket_transport(a, asyncio.Protocol())
|
||||
f = asyncio.ensure_future(self.loop.sock_recv(b, 100))
|
||||
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')
|
||||
|
||||
def _test_pipe(self):
|
||||
ADDRESS = r'\\.\pipe\_test_pipe-%s' % os.getpid()
|
||||
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
yield from self.loop.create_pipe_connection(
|
||||
asyncio.Protocol, ADDRESS)
|
||||
|
||||
[server] = yield from 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 = yield from 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 = yield from r.readline()
|
||||
self.assertEqual(response, 'LOWER-{}\n'.format(i).encode())
|
||||
w.close()
|
||||
|
||||
server.close()
|
||||
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
yield from 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()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
182
third_party/python/Lib/test/test_asyncio/test_windows_utils.py
vendored
Normal file
182
third_party/python/Lib/test/test_asyncio/test_windows_utils.py
vendored
Normal file
|
@ -0,0 +1,182 @@
|
|||
"""Tests for window_utils"""
|
||||
|
||||
import socket
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
from unittest import mock
|
||||
|
||||
if sys.platform != 'win32':
|
||||
raise unittest.SkipTest('Windows only')
|
||||
|
||||
import _winapi
|
||||
|
||||
from asyncio import _overlapped
|
||||
from asyncio import windows_utils
|
||||
try:
|
||||
from test import support
|
||||
except ImportError:
|
||||
from asyncio import test_support as support
|
||||
|
||||
|
||||
class WinsocketpairTests(unittest.TestCase):
|
||||
|
||||
def check_winsocketpair(self, ssock, csock):
|
||||
csock.send(b'xxx')
|
||||
self.assertEqual(b'xxx', ssock.recv(1024))
|
||||
csock.close()
|
||||
ssock.close()
|
||||
|
||||
def test_winsocketpair(self):
|
||||
ssock, csock = windows_utils.socketpair()
|
||||
self.check_winsocketpair(ssock, csock)
|
||||
|
||||
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 not supported or enabled')
|
||||
def test_winsocketpair_ipv6(self):
|
||||
ssock, csock = windows_utils.socketpair(family=socket.AF_INET6)
|
||||
self.check_winsocketpair(ssock, csock)
|
||||
|
||||
@unittest.skipIf(hasattr(socket, 'socketpair'),
|
||||
'socket.socketpair is available')
|
||||
@mock.patch('asyncio.windows_utils.socket')
|
||||
def test_winsocketpair_exc(self, m_socket):
|
||||
m_socket.AF_INET = socket.AF_INET
|
||||
m_socket.SOCK_STREAM = socket.SOCK_STREAM
|
||||
m_socket.socket.return_value.getsockname.return_value = ('', 12345)
|
||||
m_socket.socket.return_value.accept.return_value = object(), object()
|
||||
m_socket.socket.return_value.connect.side_effect = OSError()
|
||||
|
||||
self.assertRaises(OSError, windows_utils.socketpair)
|
||||
|
||||
def test_winsocketpair_invalid_args(self):
|
||||
self.assertRaises(ValueError,
|
||||
windows_utils.socketpair, family=socket.AF_UNSPEC)
|
||||
self.assertRaises(ValueError,
|
||||
windows_utils.socketpair, type=socket.SOCK_DGRAM)
|
||||
self.assertRaises(ValueError,
|
||||
windows_utils.socketpair, proto=1)
|
||||
|
||||
@unittest.skipIf(hasattr(socket, 'socketpair'),
|
||||
'socket.socketpair is available')
|
||||
@mock.patch('asyncio.windows_utils.socket')
|
||||
def test_winsocketpair_close(self, m_socket):
|
||||
m_socket.AF_INET = socket.AF_INET
|
||||
m_socket.SOCK_STREAM = socket.SOCK_STREAM
|
||||
sock = mock.Mock()
|
||||
m_socket.socket.return_value = sock
|
||||
sock.bind.side_effect = OSError
|
||||
self.assertRaises(OSError, windows_utils.socketpair)
|
||||
self.assertTrue(sock.close.called)
|
||||
|
||||
|
||||
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()
|
Loading…
Add table
Add a link
Reference in a new issue