def test_task_yield_future_passes_cancel(self): # Canceling outer() cancels inner() cancels waiter. proof = 0 waiter = self.create_future() @asyncio.coroutine def inner(): nonlocal proof try: yield from waiter except asyncio.CancelledError: proof += 1 raise else: self.fail('got past sleep() in inner()') @asyncio.coroutine def outer(): nonlocal proof try: yield from inner() except asyncio.CancelledError: proof += 100 # Expect this path. else: proof += 10 f = asyncio.ensure_future(outer(), loop=self.loop) tb.run_briefly(self.loop) f.cancel() self.loop.run_until_complete(f) self.assertEqual(proof, 101) self.assertTrue(waiter.cancelled())
def test_task_step_result_future(self): # If coroutine returns future, task waits on this future. class Fut(asyncio.Future): def __init__(self, *args, **kwds): self.cb_added = False super().__init__(*args, **kwds) def add_done_callback(self, fn, context=None): self.cb_added = True super().add_done_callback(fn) fut = Fut(loop=self.loop) result = None @asyncio.coroutine def wait_for_future(): nonlocal result result = yield from fut t = self.create_task(wait_for_future()) tb.run_briefly(self.loop) self.assertTrue(fut.cb_added) res = object() fut.set_result(res) tb.run_briefly(self.loop) self.assertIs(res, result) self.assertTrue(t.done()) self.assertIsNone(t.result())
def test_task_yield_wait_does_not_shield_cancel(self): # Canceling outer() makes wait() return early, leaves inner() # running. proof = 0 waiter = self.create_future() @asyncio.coroutine def inner(): nonlocal proof yield from waiter proof += 1 @asyncio.coroutine def outer(): nonlocal proof d, p = yield from asyncio.wait([inner()], loop=self.loop) proof += 100 f = asyncio.ensure_future(outer(), loop=self.loop) tb.run_briefly(self.loop) f.cancel() self.assertRaises(asyncio.CancelledError, self.loop.run_until_complete, f) waiter.set_result(None) tb.run_briefly(self.loop) self.assertEqual(proof, 1)
def test_task_yield_wait_does_not_shield_cancel(self): # Canceling outer() makes wait() return early, leaves inner() # running. proof = 0 waiter = self.create_future() @asyncio.coroutine def inner(): nonlocal proof yield from waiter proof += 1 @asyncio.coroutine def outer(): nonlocal proof d, p = yield from asyncio.wait([inner()], loop=self.loop) proof += 100 f = asyncio.ensure_future(outer(), loop=self.loop) tb.run_briefly(self.loop) f.cancel() self.assertRaises( asyncio.CancelledError, self.loop.run_until_complete, f) waiter.set_result(None) tb.run_briefly(self.loop) self.assertEqual(proof, 1)
def test_task_step_with_baseexception(self): @asyncio.coroutine def notmutch(): raise BaseException() task = self.create_task(notmutch()) with self.assertRaises(BaseException): tb.run_briefly(self.loop) self.assertTrue(task.done()) self.assertIsInstance(task.exception(), BaseException)
def test_task_cancel_yield(self): @asyncio.coroutine def task(): while True: yield return 12 t = self.create_task(task()) tb.run_briefly(self.loop) # start coro t.cancel() self.assertRaises( asyncio.CancelledError, self.loop.run_until_complete, t) self.assertTrue(t.done()) self.assertTrue(t.cancelled()) self.assertFalse(t.cancel())
def test_task_cancel_inner_future(self): f = self.create_future() @asyncio.coroutine def task(): yield from f return 12 t = self.create_task(task()) tb.run_briefly(self.loop) # start task f.cancel() with self.assertRaises(asyncio.CancelledError): self.loop.run_until_complete(t) self.assertTrue(f.cancelled()) self.assertTrue(t.cancelled())
def test_task_cancel_yield(self): @asyncio.coroutine def task(): while True: yield return 12 t = self.create_task(task()) tb.run_briefly(self.loop) # start coro t.cancel() self.assertRaises(asyncio.CancelledError, self.loop.run_until_complete, t) self.assertTrue(t.done()) self.assertTrue(t.cancelled()) self.assertFalse(t.cancel())
def test_cancel_post_init(self): async def cancel_make_transport(): coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *self.PROGRAM_BLOCKED) task = self.loop.create_task(coro) self.loop.call_soon(task.cancel) try: await task except asyncio.CancelledError: pass # Give the process handler some time to close itself await asyncio.sleep(0.3) gc.collect() # ignore the log: # "Exception during subprocess creation, kill the subprocess" with tb.disable_logger(): self.loop.run_until_complete(cancel_make_transport()) tb.run_briefly(self.loop)
def test_task_cancel_both_task_and_inner_future(self): f = self.create_future() @asyncio.coroutine def task(): yield from f return 12 t = self.create_task(task()) self.assertEqual(all_tasks(loop=self.loop), {t}) tb.run_briefly(self.loop) f.cancel() t.cancel() with self.assertRaises(asyncio.CancelledError): self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertTrue(f.cancelled()) self.assertTrue(t.cancelled())
def test_task_cancel_both_task_and_inner_future(self): f = self.create_future() @asyncio.coroutine def task(): yield from f return 12 t = self.create_task(task()) self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {t}) tb.run_briefly(self.loop) f.cancel() t.cancel() with self.assertRaises(asyncio.CancelledError): self.loop.run_until_complete(t) self.assertTrue(t.done()) self.assertTrue(f.cancelled()) self.assertTrue(t.cancelled())
def test_task_cancel_task_ignoring(self): fut1 = self.create_future() fut2 = self.create_future() fut3 = self.create_future() @asyncio.coroutine def task(): yield from fut1 try: yield from fut2 except asyncio.CancelledError: pass res = yield from fut3 return res t = self.create_task(task()) tb.run_briefly(self.loop) self.assertIs(t._fut_waiter, fut1) # White-box test. fut1.set_result(None) tb.run_briefly(self.loop) self.assertIs(t._fut_waiter, fut2) # White-box test. t.cancel() self.assertTrue(fut2.cancelled()) tb.run_briefly(self.loop) self.assertIs(t._fut_waiter, fut3) # White-box test. fut3.set_result(42) res = self.loop.run_until_complete(t) self.assertEqual(res, 42) self.assertFalse(fut3.cancelled()) self.assertFalse(t.cancelled())
def test_cancel_post_init(self): @asyncio.coroutine def cancel_make_transport(): coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *self.PROGRAM_BLOCKED) task = self.loop.create_task(coro) self.loop.call_soon(task.cancel) try: yield from task except asyncio.CancelledError: pass # Give the process handler some time to close itself yield from asyncio.sleep(0.3, loop=self.loop) gc.collect() # ignore the log: # "Exception during subprocess creation, kill the subprocess" with tb.disable_logger(): self.loop.run_until_complete(cancel_make_transport()) tb.run_briefly(self.loop)