2013-10-17 17:40:50 -03:00
|
|
|
import os
|
2018-12-18 17:56:17 -04:00
|
|
|
import signal
|
2017-11-28 06:15:26 -04:00
|
|
|
import socket
|
2013-10-17 17:40:50 -03:00
|
|
|
import sys
|
2018-12-18 17:56:17 -04:00
|
|
|
import time
|
2019-01-05 16:44:59 -04:00
|
|
|
import threading
|
2013-10-17 17:40:50 -03:00
|
|
|
import unittest
|
2015-01-26 10:04:03 -04:00
|
|
|
from unittest import mock
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
if sys.platform != 'win32':
|
|
|
|
raise unittest.SkipTest('Windows only')
|
|
|
|
|
2017-11-28 10:19:56 -04:00
|
|
|
import _overlapped
|
2013-10-30 18:44:05 -03:00
|
|
|
import _winapi
|
|
|
|
|
2013-10-17 17:40:50 -03:00
|
|
|
import asyncio
|
2014-01-25 10:32:06 -04:00
|
|
|
from asyncio import windows_events
|
2019-05-27 16:56:22 -03:00
|
|
|
from asyncio.streams import _StreamProtocol
|
2017-12-11 11:04:40 -04:00
|
|
|
from test.test_asyncio import utils as test_utils
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
|
2018-06-02 00:34:09 -03:00
|
|
|
def tearDownModule():
|
|
|
|
asyncio.set_event_loop_policy(None)
|
|
|
|
|
|
|
|
|
2014-01-25 10:32:06 -04:00
|
|
|
class UpperProto(asyncio.Protocol):
|
2013-10-17 17:40:50 -03:00
|
|
|
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()
|
|
|
|
|
|
|
|
|
2018-12-18 17:56:17 -04:00
|
|
|
class ProactorLoopCtrlC(test_utils.TestCase):
|
2019-01-05 16:44:59 -04:00
|
|
|
|
2018-12-18 17:56:17 -04:00
|
|
|
def test_ctrl_c(self):
|
2019-01-05 16:44:59 -04:00
|
|
|
|
|
|
|
def SIGINT_after_delay():
|
2019-06-14 08:02:51 -03:00
|
|
|
time.sleep(0.1)
|
2019-01-08 05:58:25 -04:00
|
|
|
signal.raise_signal(signal.SIGINT)
|
2019-01-05 16:44:59 -04:00
|
|
|
|
2019-06-14 08:02:51 -03:00
|
|
|
thread = threading.Thread(target=SIGINT_after_delay)
|
|
|
|
loop = asyncio.get_event_loop()
|
2019-01-05 16:44:59 -04:00
|
|
|
try:
|
2019-06-14 08:02:51 -03:00
|
|
|
# only start the loop once the event loop is running
|
|
|
|
loop.call_soon(thread.start)
|
|
|
|
loop.run_forever()
|
2019-01-05 16:44:59 -04:00
|
|
|
self.fail("should not fall through 'run_forever'")
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
pass
|
|
|
|
finally:
|
2019-06-14 08:02:51 -03:00
|
|
|
self.close_loop(loop)
|
|
|
|
thread.join()
|
2018-12-18 17:56:17 -04:00
|
|
|
|
|
|
|
|
2014-06-17 20:36:32 -03:00
|
|
|
class ProactorTests(test_utils.TestCase):
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
def setUp(self):
|
2016-11-04 15:29:28 -03:00
|
|
|
super().setUp()
|
2014-01-25 10:32:06 -04:00
|
|
|
self.loop = asyncio.ProactorEventLoop()
|
2014-06-17 20:36:32 -03:00
|
|
|
self.set_event_loop(self.loop)
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
def test_close(self):
|
2017-11-28 06:15:26 -04:00
|
|
|
a, b = socket.socketpair()
|
2014-01-25 10:32:06 -04:00
|
|
|
trans = self.loop._make_socket_transport(a, asyncio.Protocol())
|
2017-12-14 21:53:26 -04:00
|
|
|
f = asyncio.ensure_future(self.loop.sock_recv(b, 100), loop=self.loop)
|
2013-10-17 17:40:50 -03:00
|
|
|
trans.close()
|
|
|
|
self.loop.run_until_complete(f)
|
|
|
|
self.assertEqual(f.result(), b'')
|
2014-01-10 19:16:50 -04:00
|
|
|
b.close()
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
def test_double_bind(self):
|
|
|
|
ADDRESS = r'\\.\pipe\test_double_bind-%s' % os.getpid()
|
|
|
|
server1 = windows_events.PipeServer(ADDRESS)
|
|
|
|
with self.assertRaises(PermissionError):
|
2014-02-26 06:07:42 -04:00
|
|
|
windows_events.PipeServer(ADDRESS)
|
2013-10-17 17:40:50 -03:00
|
|
|
server1.close()
|
|
|
|
|
|
|
|
def test_pipe(self):
|
|
|
|
res = self.loop.run_until_complete(self._test_pipe())
|
|
|
|
self.assertEqual(res, 'done')
|
|
|
|
|
2017-12-08 18:23:48 -04:00
|
|
|
async def _test_pipe(self):
|
2013-10-17 17:40:50 -03:00
|
|
|
ADDRESS = r'\\.\pipe\_test_pipe-%s' % os.getpid()
|
|
|
|
|
|
|
|
with self.assertRaises(FileNotFoundError):
|
2017-12-08 18:23:48 -04:00
|
|
|
await self.loop.create_pipe_connection(
|
2014-01-25 10:32:06 -04:00
|
|
|
asyncio.Protocol, ADDRESS)
|
2013-10-17 17:40:50 -03:00
|
|
|
|
2017-12-08 18:23:48 -04:00
|
|
|
[server] = await self.loop.start_serving_pipe(
|
2013-10-17 17:40:50 -03:00
|
|
|
UpperProto, ADDRESS)
|
|
|
|
self.assertIsInstance(server, windows_events.PipeServer)
|
|
|
|
|
|
|
|
clients = []
|
|
|
|
for i in range(5):
|
2019-05-27 16:56:22 -03:00
|
|
|
stream = asyncio.Stream(mode=asyncio.StreamMode.READ,
|
|
|
|
loop=self.loop, _asyncio_internal=True)
|
|
|
|
protocol = _StreamProtocol(stream,
|
|
|
|
loop=self.loop,
|
|
|
|
_asyncio_internal=True)
|
2017-12-08 18:23:48 -04:00
|
|
|
trans, proto = await self.loop.create_pipe_connection(
|
2013-11-01 18:20:55 -03:00
|
|
|
lambda: protocol, ADDRESS)
|
2014-01-25 10:32:06 -04:00
|
|
|
self.assertIsInstance(trans, asyncio.Transport)
|
2013-10-17 17:40:50 -03:00
|
|
|
self.assertEqual(protocol, proto)
|
2019-05-27 16:56:22 -03:00
|
|
|
clients.append((stream, trans))
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
for i, (r, w) in enumerate(clients):
|
|
|
|
w.write('lower-{}\n'.format(i).encode())
|
|
|
|
|
|
|
|
for i, (r, w) in enumerate(clients):
|
2017-12-08 18:23:48 -04:00
|
|
|
response = await r.readline()
|
2013-10-17 17:40:50 -03:00
|
|
|
self.assertEqual(response, 'LOWER-{}\n'.format(i).encode())
|
|
|
|
w.close()
|
2019-05-27 16:56:22 -03:00
|
|
|
await r.close()
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
server.close()
|
|
|
|
|
|
|
|
with self.assertRaises(FileNotFoundError):
|
2017-12-08 18:23:48 -04:00
|
|
|
await self.loop.create_pipe_connection(
|
2014-01-25 10:32:06 -04:00
|
|
|
asyncio.Protocol, ADDRESS)
|
2013-10-17 17:40:50 -03:00
|
|
|
|
|
|
|
return 'done'
|
2013-10-20 16:02:53 -03:00
|
|
|
|
2015-01-26 10:04:03 -04:00
|
|
|
def test_connect_pipe_cancel(self):
|
|
|
|
exc = OSError()
|
|
|
|
exc.winerror = _overlapped.ERROR_PIPE_BUSY
|
2017-12-08 18:23:48 -04:00
|
|
|
with mock.patch.object(_overlapped, 'ConnectPipe',
|
|
|
|
side_effect=exc) as connect:
|
2015-01-26 10:04:03 -04:00
|
|
|
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)
|
|
|
|
|
2013-10-30 18:44:05 -03:00
|
|
|
def test_wait_for_handle(self):
|
|
|
|
event = _overlapped.CreateEvent(None, True, False, None)
|
|
|
|
self.addCleanup(_winapi.CloseHandle, event)
|
|
|
|
|
2014-07-24 07:04:22 -03:00
|
|
|
# Wait for unset event with 0.5s timeout;
|
2013-10-30 18:44:05 -03:00
|
|
|
# result should be False at timeout
|
2014-07-24 19:54:53 -03:00
|
|
|
fut = self.loop._proactor.wait_for_handle(event, 0.5)
|
2013-10-30 18:44:05 -03:00
|
|
|
start = self.loop.time()
|
2014-12-19 12:10:44 -04:00
|
|
|
done = self.loop.run_until_complete(fut)
|
2013-10-30 18:44:05 -03:00
|
|
|
elapsed = self.loop.time() - start
|
2014-12-19 12:10:44 -04:00
|
|
|
|
|
|
|
self.assertEqual(done, False)
|
2014-07-24 19:54:53 -03:00
|
|
|
self.assertFalse(fut.result())
|
2017-08-10 20:23:22 -03:00
|
|
|
# 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)
|
2013-10-30 18:44:05 -03:00
|
|
|
|
|
|
|
_overlapped.SetEvent(event)
|
|
|
|
|
2014-12-01 12:28:43 -04:00
|
|
|
# Wait for set event;
|
2013-10-30 18:44:05 -03:00
|
|
|
# result should be True immediately
|
2014-07-24 19:54:53 -03:00
|
|
|
fut = self.loop._proactor.wait_for_handle(event, 10)
|
2013-10-30 18:44:05 -03:00
|
|
|
start = self.loop.time()
|
2014-12-19 12:10:44 -04:00
|
|
|
done = self.loop.run_until_complete(fut)
|
2013-10-30 18:44:05 -03:00
|
|
|
elapsed = self.loop.time() - start
|
2014-12-19 12:10:44 -04:00
|
|
|
|
|
|
|
self.assertEqual(done, True)
|
2014-07-24 19:54:53 -03:00
|
|
|
self.assertTrue(fut.result())
|
2014-07-24 07:04:22 -03:00
|
|
|
self.assertTrue(0 <= elapsed < 0.3, elapsed)
|
2013-10-30 18:44:05 -03:00
|
|
|
|
2015-07-09 18:13:50 -03:00
|
|
|
# asyncio issue #195: cancelling a done _WaitHandleFuture
|
|
|
|
# must not crash
|
2014-07-24 19:54:53 -03:00
|
|
|
fut.cancel()
|
|
|
|
|
|
|
|
def test_wait_for_handle_cancel(self):
|
|
|
|
event = _overlapped.CreateEvent(None, True, False, None)
|
|
|
|
self.addCleanup(_winapi.CloseHandle, event)
|
2013-10-30 18:44:05 -03:00
|
|
|
|
|
|
|
# Wait for unset event with a cancelled future;
|
|
|
|
# CancelledError should be raised immediately
|
2014-07-24 19:54:53 -03:00
|
|
|
fut = self.loop._proactor.wait_for_handle(event, 10)
|
|
|
|
fut.cancel()
|
2013-10-30 18:44:05 -03:00
|
|
|
start = self.loop.time()
|
2014-01-25 10:32:06 -04:00
|
|
|
with self.assertRaises(asyncio.CancelledError):
|
2014-07-24 19:54:53 -03:00
|
|
|
self.loop.run_until_complete(fut)
|
2013-10-30 18:44:05 -03:00
|
|
|
elapsed = self.loop.time() - start
|
2013-12-12 21:45:18 -04:00
|
|
|
self.assertTrue(0 <= elapsed < 0.1, elapsed)
|
2013-10-30 18:44:05 -03:00
|
|
|
|
2015-07-09 18:13:50 -03:00
|
|
|
# asyncio issue #195: cancelling a _WaitHandleFuture twice
|
|
|
|
# must not crash
|
2014-07-24 19:54:53 -03:00
|
|
|
fut = self.loop._proactor.wait_for_handle(event)
|
|
|
|
fut.cancel()
|
|
|
|
fut.cancel()
|
|
|
|
|
2013-10-20 16:02:53 -03:00
|
|
|
|
2018-06-07 21:44:57 -03:00
|
|
|
class WinPolicyTests(test_utils.TestCase):
|
|
|
|
|
|
|
|
def test_selector_win_policy(self):
|
|
|
|
async def main():
|
|
|
|
self.assertIsInstance(
|
|
|
|
asyncio.get_running_loop(),
|
|
|
|
asyncio.SelectorEventLoop)
|
|
|
|
|
|
|
|
old_policy = asyncio.get_event_loop_policy()
|
|
|
|
try:
|
|
|
|
asyncio.set_event_loop_policy(
|
|
|
|
asyncio.WindowsSelectorEventLoopPolicy())
|
|
|
|
asyncio.run(main())
|
|
|
|
finally:
|
|
|
|
asyncio.set_event_loop_policy(old_policy)
|
|
|
|
|
|
|
|
def test_proactor_win_policy(self):
|
|
|
|
async def main():
|
|
|
|
self.assertIsInstance(
|
|
|
|
asyncio.get_running_loop(),
|
|
|
|
asyncio.ProactorEventLoop)
|
|
|
|
|
|
|
|
old_policy = asyncio.get_event_loop_policy()
|
|
|
|
try:
|
|
|
|
asyncio.set_event_loop_policy(
|
|
|
|
asyncio.WindowsProactorEventLoopPolicy())
|
|
|
|
asyncio.run(main())
|
|
|
|
finally:
|
|
|
|
asyncio.set_event_loop_policy(old_policy)
|
|
|
|
|
|
|
|
|
2013-10-20 16:02:53 -03:00
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|