ยปCore Development>Code coverage>Lib/test/test_asyncio/test_tasks.py

Python code coverage for Lib/test/test_asyncio/test_tasks.py

#countcontent
1n/a"""Tests for tasks.py."""
2n/a
3n/aimport collections
4n/aimport contextlib
5n/aimport functools
6n/aimport io
7n/aimport os
8n/aimport re
9n/aimport sys
10n/aimport types
11n/aimport unittest
12n/aimport weakref
13n/afrom unittest import mock
14n/a
15n/aimport asyncio
16n/afrom asyncio import coroutines
17n/afrom asyncio import futures
18n/afrom asyncio import tasks
19n/afrom asyncio import test_utils
20n/atry:
21n/a from test import support
22n/aexcept ImportError:
23n/a from asyncio import test_support as support
24n/atry:
25n/a from test.support.script_helper import assert_python_ok
26n/aexcept ImportError:
27n/a try:
28n/a from test.script_helper import assert_python_ok
29n/a except ImportError:
30n/a from asyncio.test_support import assert_python_ok
31n/a
32n/a
33n/aPY34 = (sys.version_info >= (3, 4))
34n/aPY35 = (sys.version_info >= (3, 5))
35n/a
36n/a
37n/a@asyncio.coroutine
38n/adef coroutine_function():
39n/a pass
40n/a
41n/a
42n/a@contextlib.contextmanager
43n/adef set_coroutine_debug(enabled):
44n/a coroutines = asyncio.coroutines
45n/a
46n/a old_debug = coroutines._DEBUG
47n/a try:
48n/a coroutines._DEBUG = enabled
49n/a yield
50n/a finally:
51n/a coroutines._DEBUG = old_debug
52n/a
53n/a
54n/a
55n/adef format_coroutine(qualname, state, src, source_traceback, generator=False):
56n/a if generator:
57n/a state = '%s' % state
58n/a else:
59n/a state = '%s, defined' % state
60n/a if source_traceback is not None:
61n/a frame = source_traceback[-1]
62n/a return ('coro=<%s() %s at %s> created at %s:%s'
63n/a % (qualname, state, src, frame[0], frame[1]))
64n/a else:
65n/a return 'coro=<%s() %s at %s>' % (qualname, state, src)
66n/a
67n/a
68n/aclass Dummy:
69n/a
70n/a def __repr__(self):
71n/a return '<Dummy>'
72n/a
73n/a def __call__(self, *args):
74n/a pass
75n/a
76n/a
77n/aclass BaseTaskTests:
78n/a
79n/a Task = None
80n/a Future = None
81n/a
82n/a def new_task(self, loop, coro):
83n/a return self.__class__.Task(coro, loop=loop)
84n/a
85n/a def new_future(self, loop):
86n/a return self.__class__.Future(loop=loop)
87n/a
88n/a def setUp(self):
89n/a super().setUp()
90n/a self.loop = self.new_test_loop()
91n/a self.loop.set_task_factory(self.new_task)
92n/a self.loop.create_future = lambda: self.new_future(self.loop)
93n/a
94n/a def test_other_loop_future(self):
95n/a other_loop = asyncio.new_event_loop()
96n/a fut = self.new_future(other_loop)
97n/a
98n/a @asyncio.coroutine
99n/a def run(fut):
100n/a yield from fut
101n/a
102n/a try:
103n/a with self.assertRaisesRegex(RuntimeError,
104n/a r'Task .* got Future .* attached'):
105n/a self.loop.run_until_complete(run(fut))
106n/a finally:
107n/a other_loop.close()
108n/a
109n/a def test_task_awaits_on_itself(self):
110n/a @asyncio.coroutine
111n/a def test():
112n/a yield from task
113n/a
114n/a task = asyncio.ensure_future(test(), loop=self.loop)
115n/a
116n/a with self.assertRaisesRegex(RuntimeError,
117n/a 'Task cannot await on itself'):
118n/a self.loop.run_until_complete(task)
119n/a
120n/a def test_task_class(self):
121n/a @asyncio.coroutine
122n/a def notmuch():
123n/a return 'ok'
124n/a t = self.new_task(self.loop, notmuch())
125n/a self.loop.run_until_complete(t)
126n/a self.assertTrue(t.done())
127n/a self.assertEqual(t.result(), 'ok')
128n/a self.assertIs(t._loop, self.loop)
129n/a
130n/a loop = asyncio.new_event_loop()
131n/a self.set_event_loop(loop)
132n/a t = self.new_task(loop, notmuch())
133n/a self.assertIs(t._loop, loop)
134n/a loop.run_until_complete(t)
135n/a loop.close()
136n/a
137n/a def test_ensure_future_coroutine(self):
138n/a @asyncio.coroutine
139n/a def notmuch():
140n/a return 'ok'
141n/a t = asyncio.ensure_future(notmuch(), loop=self.loop)
142n/a self.loop.run_until_complete(t)
143n/a self.assertTrue(t.done())
144n/a self.assertEqual(t.result(), 'ok')
145n/a self.assertIs(t._loop, self.loop)
146n/a
147n/a loop = asyncio.new_event_loop()
148n/a self.set_event_loop(loop)
149n/a t = asyncio.ensure_future(notmuch(), loop=loop)
150n/a self.assertIs(t._loop, loop)
151n/a loop.run_until_complete(t)
152n/a loop.close()
153n/a
154n/a def test_ensure_future_future(self):
155n/a f_orig = self.new_future(self.loop)
156n/a f_orig.set_result('ko')
157n/a
158n/a f = asyncio.ensure_future(f_orig)
159n/a self.loop.run_until_complete(f)
160n/a self.assertTrue(f.done())
161n/a self.assertEqual(f.result(), 'ko')
162n/a self.assertIs(f, f_orig)
163n/a
164n/a loop = asyncio.new_event_loop()
165n/a self.set_event_loop(loop)
166n/a
167n/a with self.assertRaises(ValueError):
168n/a f = asyncio.ensure_future(f_orig, loop=loop)
169n/a
170n/a loop.close()
171n/a
172n/a f = asyncio.ensure_future(f_orig, loop=self.loop)
173n/a self.assertIs(f, f_orig)
174n/a
175n/a def test_ensure_future_task(self):
176n/a @asyncio.coroutine
177n/a def notmuch():
178n/a return 'ok'
179n/a t_orig = self.new_task(self.loop, notmuch())
180n/a t = asyncio.ensure_future(t_orig)
181n/a self.loop.run_until_complete(t)
182n/a self.assertTrue(t.done())
183n/a self.assertEqual(t.result(), 'ok')
184n/a self.assertIs(t, t_orig)
185n/a
186n/a loop = asyncio.new_event_loop()
187n/a self.set_event_loop(loop)
188n/a
189n/a with self.assertRaises(ValueError):
190n/a t = asyncio.ensure_future(t_orig, loop=loop)
191n/a
192n/a loop.close()
193n/a
194n/a t = asyncio.ensure_future(t_orig, loop=self.loop)
195n/a self.assertIs(t, t_orig)
196n/a
197n/a @unittest.skipUnless(PY35, 'need python 3.5 or later')
198n/a def test_ensure_future_awaitable(self):
199n/a class Aw:
200n/a def __init__(self, coro):
201n/a self.coro = coro
202n/a def __await__(self):
203n/a return (yield from self.coro)
204n/a
205n/a @asyncio.coroutine
206n/a def coro():
207n/a return 'ok'
208n/a
209n/a loop = asyncio.new_event_loop()
210n/a self.set_event_loop(loop)
211n/a fut = asyncio.ensure_future(Aw(coro()), loop=loop)
212n/a loop.run_until_complete(fut)
213n/a assert fut.result() == 'ok'
214n/a
215n/a def test_ensure_future_neither(self):
216n/a with self.assertRaises(TypeError):
217n/a asyncio.ensure_future('ok')
218n/a
219n/a def test_async_warning(self):
220n/a f = self.new_future(self.loop)
221n/a with self.assertWarnsRegex(DeprecationWarning,
222n/a 'function is deprecated, use ensure_'):
223n/a self.assertIs(f, asyncio.async(f))
224n/a
225n/a def test_get_stack(self):
226n/a T = None
227n/a
228n/a @asyncio.coroutine
229n/a def foo():
230n/a yield from bar()
231n/a
232n/a @asyncio.coroutine
233n/a def bar():
234n/a # test get_stack()
235n/a f = T.get_stack(limit=1)
236n/a try:
237n/a self.assertEqual(f[0].f_code.co_name, 'foo')
238n/a finally:
239n/a f = None
240n/a
241n/a # test print_stack()
242n/a file = io.StringIO()
243n/a T.print_stack(limit=1, file=file)
244n/a file.seek(0)
245n/a tb = file.read()
246n/a self.assertRegex(tb, r'foo\(\) running')
247n/a
248n/a @asyncio.coroutine
249n/a def runner():
250n/a nonlocal T
251n/a T = asyncio.ensure_future(foo(), loop=self.loop)
252n/a yield from T
253n/a
254n/a self.loop.run_until_complete(runner())
255n/a
256n/a def test_task_repr(self):
257n/a self.loop.set_debug(False)
258n/a
259n/a @asyncio.coroutine
260n/a def notmuch():
261n/a yield from []
262n/a return 'abc'
263n/a
264n/a # test coroutine function
265n/a self.assertEqual(notmuch.__name__, 'notmuch')
266n/a if PY35:
267n/a self.assertRegex(notmuch.__qualname__,
268n/a r'\w+.test_task_repr.<locals>.notmuch')
269n/a self.assertEqual(notmuch.__module__, __name__)
270n/a
271n/a filename, lineno = test_utils.get_function_source(notmuch)
272n/a src = "%s:%s" % (filename, lineno)
273n/a
274n/a # test coroutine object
275n/a gen = notmuch()
276n/a if coroutines._DEBUG or PY35:
277n/a coro_qualname = 'BaseTaskTests.test_task_repr.<locals>.notmuch'
278n/a else:
279n/a coro_qualname = 'notmuch'
280n/a self.assertEqual(gen.__name__, 'notmuch')
281n/a if PY35:
282n/a self.assertEqual(gen.__qualname__,
283n/a coro_qualname)
284n/a
285n/a # test pending Task
286n/a t = self.new_task(self.loop, gen)
287n/a t.add_done_callback(Dummy())
288n/a
289n/a coro = format_coroutine(coro_qualname, 'running', src,
290n/a t._source_traceback, generator=True)
291n/a self.assertEqual(repr(t),
292n/a '<Task pending %s cb=[<Dummy>()]>' % coro)
293n/a
294n/a # test cancelling Task
295n/a t.cancel() # Does not take immediate effect!
296n/a self.assertEqual(repr(t),
297n/a '<Task cancelling %s cb=[<Dummy>()]>' % coro)
298n/a
299n/a # test cancelled Task
300n/a self.assertRaises(asyncio.CancelledError,
301n/a self.loop.run_until_complete, t)
302n/a coro = format_coroutine(coro_qualname, 'done', src,
303n/a t._source_traceback)
304n/a self.assertEqual(repr(t),
305n/a '<Task cancelled %s>' % coro)
306n/a
307n/a # test finished Task
308n/a t = self.new_task(self.loop, notmuch())
309n/a self.loop.run_until_complete(t)
310n/a coro = format_coroutine(coro_qualname, 'done', src,
311n/a t._source_traceback)
312n/a self.assertEqual(repr(t),
313n/a "<Task finished %s result='abc'>" % coro)
314n/a
315n/a def test_task_repr_coro_decorator(self):
316n/a self.loop.set_debug(False)
317n/a
318n/a @asyncio.coroutine
319n/a def notmuch():
320n/a # notmuch() function doesn't use yield from: it will be wrapped by
321n/a # @coroutine decorator
322n/a return 123
323n/a
324n/a # test coroutine function
325n/a self.assertEqual(notmuch.__name__, 'notmuch')
326n/a if PY35:
327n/a self.assertRegex(notmuch.__qualname__,
328n/a r'\w+.test_task_repr_coro_decorator'
329n/a r'\.<locals>\.notmuch')
330n/a self.assertEqual(notmuch.__module__, __name__)
331n/a
332n/a # test coroutine object
333n/a gen = notmuch()
334n/a if coroutines._DEBUG or PY35:
335n/a # On Python >= 3.5, generators now inherit the name of the
336n/a # function, as expected, and have a qualified name (__qualname__
337n/a # attribute).
338n/a coro_name = 'notmuch'
339n/a coro_qualname = ('BaseTaskTests.test_task_repr_coro_decorator'
340n/a '.<locals>.notmuch')
341n/a else:
342n/a # On Python < 3.5, generators inherit the name of the code, not of
343n/a # the function. See: http://bugs.python.org/issue21205
344n/a coro_name = coro_qualname = 'coro'
345n/a self.assertEqual(gen.__name__, coro_name)
346n/a if PY35:
347n/a self.assertEqual(gen.__qualname__, coro_qualname)
348n/a
349n/a # test repr(CoroWrapper)
350n/a if coroutines._DEBUG:
351n/a # format the coroutine object
352n/a if coroutines._DEBUG:
353n/a filename, lineno = test_utils.get_function_source(notmuch)
354n/a frame = gen._source_traceback[-1]
355n/a coro = ('%s() running, defined at %s:%s, created at %s:%s'
356n/a % (coro_qualname, filename, lineno,
357n/a frame[0], frame[1]))
358n/a else:
359n/a code = gen.gi_code
360n/a coro = ('%s() running at %s:%s'
361n/a % (coro_qualname, code.co_filename,
362n/a code.co_firstlineno))
363n/a
364n/a self.assertEqual(repr(gen), '<CoroWrapper %s>' % coro)
365n/a
366n/a # test pending Task
367n/a t = self.new_task(self.loop, gen)
368n/a t.add_done_callback(Dummy())
369n/a
370n/a # format the coroutine object
371n/a if coroutines._DEBUG:
372n/a src = '%s:%s' % test_utils.get_function_source(notmuch)
373n/a else:
374n/a code = gen.gi_code
375n/a src = '%s:%s' % (code.co_filename, code.co_firstlineno)
376n/a coro = format_coroutine(coro_qualname, 'running', src,
377n/a t._source_traceback,
378n/a generator=not coroutines._DEBUG)
379n/a self.assertEqual(repr(t),
380n/a '<Task pending %s cb=[<Dummy>()]>' % coro)
381n/a self.loop.run_until_complete(t)
382n/a
383n/a def test_task_repr_wait_for(self):
384n/a self.loop.set_debug(False)
385n/a
386n/a @asyncio.coroutine
387n/a def wait_for(fut):
388n/a return (yield from fut)
389n/a
390n/a fut = self.new_future(self.loop)
391n/a task = self.new_task(self.loop, wait_for(fut))
392n/a test_utils.run_briefly(self.loop)
393n/a self.assertRegex(repr(task),
394n/a '<Task .* wait_for=%s>' % re.escape(repr(fut)))
395n/a
396n/a fut.set_result(None)
397n/a self.loop.run_until_complete(task)
398n/a
399n/a def test_task_repr_partial_corowrapper(self):
400n/a # Issue #222: repr(CoroWrapper) must not fail in debug mode if the
401n/a # coroutine is a partial function
402n/a with set_coroutine_debug(True):
403n/a self.loop.set_debug(True)
404n/a
405n/a @asyncio.coroutine
406n/a def func(x, y):
407n/a yield from asyncio.sleep(0)
408n/a
409n/a partial_func = asyncio.coroutine(functools.partial(func, 1))
410n/a task = self.loop.create_task(partial_func(2))
411n/a
412n/a # make warnings quiet
413n/a task._log_destroy_pending = False
414n/a self.addCleanup(task._coro.close)
415n/a
416n/a coro_repr = repr(task._coro)
417n/a expected = (
418n/a r'<CoroWrapper \w+.test_task_repr_partial_corowrapper'
419n/a r'\.<locals>\.func\(1\)\(\) running, '
420n/a )
421n/a self.assertRegex(coro_repr, expected)
422n/a
423n/a def test_task_basics(self):
424n/a @asyncio.coroutine
425n/a def outer():
426n/a a = yield from inner1()
427n/a b = yield from inner2()
428n/a return a+b
429n/a
430n/a @asyncio.coroutine
431n/a def inner1():
432n/a return 42
433n/a
434n/a @asyncio.coroutine
435n/a def inner2():
436n/a return 1000
437n/a
438n/a t = outer()
439n/a self.assertEqual(self.loop.run_until_complete(t), 1042)
440n/a
441n/a def test_cancel(self):
442n/a
443n/a def gen():
444n/a when = yield
445n/a self.assertAlmostEqual(10.0, when)
446n/a yield 0
447n/a
448n/a loop = self.new_test_loop(gen)
449n/a
450n/a @asyncio.coroutine
451n/a def task():
452n/a yield from asyncio.sleep(10.0, loop=loop)
453n/a return 12
454n/a
455n/a t = self.new_task(loop, task())
456n/a loop.call_soon(t.cancel)
457n/a with self.assertRaises(asyncio.CancelledError):
458n/a loop.run_until_complete(t)
459n/a self.assertTrue(t.done())
460n/a self.assertTrue(t.cancelled())
461n/a self.assertFalse(t.cancel())
462n/a
463n/a def test_cancel_yield(self):
464n/a @asyncio.coroutine
465n/a def task():
466n/a yield
467n/a yield
468n/a return 12
469n/a
470n/a t = self.new_task(self.loop, task())
471n/a test_utils.run_briefly(self.loop) # start coro
472n/a t.cancel()
473n/a self.assertRaises(
474n/a asyncio.CancelledError, self.loop.run_until_complete, t)
475n/a self.assertTrue(t.done())
476n/a self.assertTrue(t.cancelled())
477n/a self.assertFalse(t.cancel())
478n/a
479n/a def test_cancel_inner_future(self):
480n/a f = self.new_future(self.loop)
481n/a
482n/a @asyncio.coroutine
483n/a def task():
484n/a yield from f
485n/a return 12
486n/a
487n/a t = self.new_task(self.loop, task())
488n/a test_utils.run_briefly(self.loop) # start task
489n/a f.cancel()
490n/a with self.assertRaises(asyncio.CancelledError):
491n/a self.loop.run_until_complete(t)
492n/a self.assertTrue(f.cancelled())
493n/a self.assertTrue(t.cancelled())
494n/a
495n/a def test_cancel_both_task_and_inner_future(self):
496n/a f = self.new_future(self.loop)
497n/a
498n/a @asyncio.coroutine
499n/a def task():
500n/a yield from f
501n/a return 12
502n/a
503n/a t = self.new_task(self.loop, task())
504n/a test_utils.run_briefly(self.loop)
505n/a
506n/a f.cancel()
507n/a t.cancel()
508n/a
509n/a with self.assertRaises(asyncio.CancelledError):
510n/a self.loop.run_until_complete(t)
511n/a
512n/a self.assertTrue(t.done())
513n/a self.assertTrue(f.cancelled())
514n/a self.assertTrue(t.cancelled())
515n/a
516n/a def test_cancel_task_catching(self):
517n/a fut1 = self.new_future(self.loop)
518n/a fut2 = self.new_future(self.loop)
519n/a
520n/a @asyncio.coroutine
521n/a def task():
522n/a yield from fut1
523n/a try:
524n/a yield from fut2
525n/a except asyncio.CancelledError:
526n/a return 42
527n/a
528n/a t = self.new_task(self.loop, task())
529n/a test_utils.run_briefly(self.loop)
530n/a self.assertIs(t._fut_waiter, fut1) # White-box test.
531n/a fut1.set_result(None)
532n/a test_utils.run_briefly(self.loop)
533n/a self.assertIs(t._fut_waiter, fut2) # White-box test.
534n/a t.cancel()
535n/a self.assertTrue(fut2.cancelled())
536n/a res = self.loop.run_until_complete(t)
537n/a self.assertEqual(res, 42)
538n/a self.assertFalse(t.cancelled())
539n/a
540n/a def test_cancel_task_ignoring(self):
541n/a fut1 = self.new_future(self.loop)
542n/a fut2 = self.new_future(self.loop)
543n/a fut3 = self.new_future(self.loop)
544n/a
545n/a @asyncio.coroutine
546n/a def task():
547n/a yield from fut1
548n/a try:
549n/a yield from fut2
550n/a except asyncio.CancelledError:
551n/a pass
552n/a res = yield from fut3
553n/a return res
554n/a
555n/a t = self.new_task(self.loop, task())
556n/a test_utils.run_briefly(self.loop)
557n/a self.assertIs(t._fut_waiter, fut1) # White-box test.
558n/a fut1.set_result(None)
559n/a test_utils.run_briefly(self.loop)
560n/a self.assertIs(t._fut_waiter, fut2) # White-box test.
561n/a t.cancel()
562n/a self.assertTrue(fut2.cancelled())
563n/a test_utils.run_briefly(self.loop)
564n/a self.assertIs(t._fut_waiter, fut3) # White-box test.
565n/a fut3.set_result(42)
566n/a res = self.loop.run_until_complete(t)
567n/a self.assertEqual(res, 42)
568n/a self.assertFalse(fut3.cancelled())
569n/a self.assertFalse(t.cancelled())
570n/a
571n/a def test_cancel_current_task(self):
572n/a loop = asyncio.new_event_loop()
573n/a self.set_event_loop(loop)
574n/a
575n/a @asyncio.coroutine
576n/a def task():
577n/a t.cancel()
578n/a self.assertTrue(t._must_cancel) # White-box test.
579n/a # The sleep should be cancelled immediately.
580n/a yield from asyncio.sleep(100, loop=loop)
581n/a return 12
582n/a
583n/a t = self.new_task(loop, task())
584n/a self.assertRaises(
585n/a asyncio.CancelledError, loop.run_until_complete, t)
586n/a self.assertTrue(t.done())
587n/a self.assertFalse(t._must_cancel) # White-box test.
588n/a self.assertFalse(t.cancel())
589n/a
590n/a def test_stop_while_run_in_complete(self):
591n/a
592n/a def gen():
593n/a when = yield
594n/a self.assertAlmostEqual(0.1, when)
595n/a when = yield 0.1
596n/a self.assertAlmostEqual(0.2, when)
597n/a when = yield 0.1
598n/a self.assertAlmostEqual(0.3, when)
599n/a yield 0.1
600n/a
601n/a loop = self.new_test_loop(gen)
602n/a
603n/a x = 0
604n/a waiters = []
605n/a
606n/a @asyncio.coroutine
607n/a def task():
608n/a nonlocal x
609n/a while x < 10:
610n/a waiters.append(asyncio.sleep(0.1, loop=loop))
611n/a yield from waiters[-1]
612n/a x += 1
613n/a if x == 2:
614n/a loop.stop()
615n/a
616n/a t = self.new_task(loop, task())
617n/a with self.assertRaises(RuntimeError) as cm:
618n/a loop.run_until_complete(t)
619n/a self.assertEqual(str(cm.exception),
620n/a 'Event loop stopped before Future completed.')
621n/a self.assertFalse(t.done())
622n/a self.assertEqual(x, 2)
623n/a self.assertAlmostEqual(0.3, loop.time())
624n/a
625n/a # close generators
626n/a for w in waiters:
627n/a w.close()
628n/a t.cancel()
629n/a self.assertRaises(asyncio.CancelledError, loop.run_until_complete, t)
630n/a
631n/a def test_wait_for(self):
632n/a
633n/a def gen():
634n/a when = yield
635n/a self.assertAlmostEqual(0.2, when)
636n/a when = yield 0
637n/a self.assertAlmostEqual(0.1, when)
638n/a when = yield 0.1
639n/a
640n/a loop = self.new_test_loop(gen)
641n/a
642n/a foo_running = None
643n/a
644n/a @asyncio.coroutine
645n/a def foo():
646n/a nonlocal foo_running
647n/a foo_running = True
648n/a try:
649n/a yield from asyncio.sleep(0.2, loop=loop)
650n/a finally:
651n/a foo_running = False
652n/a return 'done'
653n/a
654n/a fut = self.new_task(loop, foo())
655n/a
656n/a with self.assertRaises(asyncio.TimeoutError):
657n/a loop.run_until_complete(asyncio.wait_for(fut, 0.1, loop=loop))
658n/a self.assertTrue(fut.done())
659n/a # it should have been cancelled due to the timeout
660n/a self.assertTrue(fut.cancelled())
661n/a self.assertAlmostEqual(0.1, loop.time())
662n/a self.assertEqual(foo_running, False)
663n/a
664n/a def test_wait_for_blocking(self):
665n/a loop = self.new_test_loop()
666n/a
667n/a @asyncio.coroutine
668n/a def coro():
669n/a return 'done'
670n/a
671n/a res = loop.run_until_complete(asyncio.wait_for(coro(),
672n/a timeout=None,
673n/a loop=loop))
674n/a self.assertEqual(res, 'done')
675n/a
676n/a def test_wait_for_with_global_loop(self):
677n/a
678n/a def gen():
679n/a when = yield
680n/a self.assertAlmostEqual(0.2, when)
681n/a when = yield 0
682n/a self.assertAlmostEqual(0.01, when)
683n/a yield 0.01
684n/a
685n/a loop = self.new_test_loop(gen)
686n/a
687n/a @asyncio.coroutine
688n/a def foo():
689n/a yield from asyncio.sleep(0.2, loop=loop)
690n/a return 'done'
691n/a
692n/a asyncio.set_event_loop(loop)
693n/a try:
694n/a fut = self.new_task(loop, foo())
695n/a with self.assertRaises(asyncio.TimeoutError):
696n/a loop.run_until_complete(asyncio.wait_for(fut, 0.01))
697n/a finally:
698n/a asyncio.set_event_loop(None)
699n/a
700n/a self.assertAlmostEqual(0.01, loop.time())
701n/a self.assertTrue(fut.done())
702n/a self.assertTrue(fut.cancelled())
703n/a
704n/a def test_wait_for_race_condition(self):
705n/a
706n/a def gen():
707n/a yield 0.1
708n/a yield 0.1
709n/a yield 0.1
710n/a
711n/a loop = self.new_test_loop(gen)
712n/a
713n/a fut = self.new_future(loop)
714n/a task = asyncio.wait_for(fut, timeout=0.2, loop=loop)
715n/a loop.call_later(0.1, fut.set_result, "ok")
716n/a res = loop.run_until_complete(task)
717n/a self.assertEqual(res, "ok")
718n/a
719n/a def test_wait(self):
720n/a
721n/a def gen():
722n/a when = yield
723n/a self.assertAlmostEqual(0.1, when)
724n/a when = yield 0
725n/a self.assertAlmostEqual(0.15, when)
726n/a yield 0.15
727n/a
728n/a loop = self.new_test_loop(gen)
729n/a
730n/a a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
731n/a b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
732n/a
733n/a @asyncio.coroutine
734n/a def foo():
735n/a done, pending = yield from asyncio.wait([b, a], loop=loop)
736n/a self.assertEqual(done, set([a, b]))
737n/a self.assertEqual(pending, set())
738n/a return 42
739n/a
740n/a res = loop.run_until_complete(self.new_task(loop, foo()))
741n/a self.assertEqual(res, 42)
742n/a self.assertAlmostEqual(0.15, loop.time())
743n/a
744n/a # Doing it again should take no time and exercise a different path.
745n/a res = loop.run_until_complete(self.new_task(loop, foo()))
746n/a self.assertAlmostEqual(0.15, loop.time())
747n/a self.assertEqual(res, 42)
748n/a
749n/a def test_wait_with_global_loop(self):
750n/a
751n/a def gen():
752n/a when = yield
753n/a self.assertAlmostEqual(0.01, when)
754n/a when = yield 0
755n/a self.assertAlmostEqual(0.015, when)
756n/a yield 0.015
757n/a
758n/a loop = self.new_test_loop(gen)
759n/a
760n/a a = self.new_task(loop, asyncio.sleep(0.01, loop=loop))
761n/a b = self.new_task(loop, asyncio.sleep(0.015, loop=loop))
762n/a
763n/a @asyncio.coroutine
764n/a def foo():
765n/a done, pending = yield from asyncio.wait([b, a])
766n/a self.assertEqual(done, set([a, b]))
767n/a self.assertEqual(pending, set())
768n/a return 42
769n/a
770n/a asyncio.set_event_loop(loop)
771n/a res = loop.run_until_complete(
772n/a self.new_task(loop, foo()))
773n/a
774n/a self.assertEqual(res, 42)
775n/a
776n/a def test_wait_duplicate_coroutines(self):
777n/a @asyncio.coroutine
778n/a def coro(s):
779n/a return s
780n/a c = coro('test')
781n/a
782n/a task =self.new_task(
783n/a self.loop,
784n/a asyncio.wait([c, c, coro('spam')], loop=self.loop))
785n/a
786n/a done, pending = self.loop.run_until_complete(task)
787n/a
788n/a self.assertFalse(pending)
789n/a self.assertEqual(set(f.result() for f in done), {'test', 'spam'})
790n/a
791n/a def test_wait_errors(self):
792n/a self.assertRaises(
793n/a ValueError, self.loop.run_until_complete,
794n/a asyncio.wait(set(), loop=self.loop))
795n/a
796n/a # -1 is an invalid return_when value
797n/a sleep_coro = asyncio.sleep(10.0, loop=self.loop)
798n/a wait_coro = asyncio.wait([sleep_coro], return_when=-1, loop=self.loop)
799n/a self.assertRaises(ValueError,
800n/a self.loop.run_until_complete, wait_coro)
801n/a
802n/a sleep_coro.close()
803n/a
804n/a def test_wait_first_completed(self):
805n/a
806n/a def gen():
807n/a when = yield
808n/a self.assertAlmostEqual(10.0, when)
809n/a when = yield 0
810n/a self.assertAlmostEqual(0.1, when)
811n/a yield 0.1
812n/a
813n/a loop = self.new_test_loop(gen)
814n/a
815n/a a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
816n/a b = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
817n/a task = self.new_task(
818n/a loop,
819n/a asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED,
820n/a loop=loop))
821n/a
822n/a done, pending = loop.run_until_complete(task)
823n/a self.assertEqual({b}, done)
824n/a self.assertEqual({a}, pending)
825n/a self.assertFalse(a.done())
826n/a self.assertTrue(b.done())
827n/a self.assertIsNone(b.result())
828n/a self.assertAlmostEqual(0.1, loop.time())
829n/a
830n/a # move forward to close generator
831n/a loop.advance_time(10)
832n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
833n/a
834n/a def test_wait_really_done(self):
835n/a # there is possibility that some tasks in the pending list
836n/a # became done but their callbacks haven't all been called yet
837n/a
838n/a @asyncio.coroutine
839n/a def coro1():
840n/a yield
841n/a
842n/a @asyncio.coroutine
843n/a def coro2():
844n/a yield
845n/a yield
846n/a
847n/a a = self.new_task(self.loop, coro1())
848n/a b = self.new_task(self.loop, coro2())
849n/a task = self.new_task(
850n/a self.loop,
851n/a asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED,
852n/a loop=self.loop))
853n/a
854n/a done, pending = self.loop.run_until_complete(task)
855n/a self.assertEqual({a, b}, done)
856n/a self.assertTrue(a.done())
857n/a self.assertIsNone(a.result())
858n/a self.assertTrue(b.done())
859n/a self.assertIsNone(b.result())
860n/a
861n/a def test_wait_first_exception(self):
862n/a
863n/a def gen():
864n/a when = yield
865n/a self.assertAlmostEqual(10.0, when)
866n/a yield 0
867n/a
868n/a loop = self.new_test_loop(gen)
869n/a
870n/a # first_exception, task already has exception
871n/a a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
872n/a
873n/a @asyncio.coroutine
874n/a def exc():
875n/a raise ZeroDivisionError('err')
876n/a
877n/a b = self.new_task(loop, exc())
878n/a task = self.new_task(
879n/a loop,
880n/a asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION,
881n/a loop=loop))
882n/a
883n/a done, pending = loop.run_until_complete(task)
884n/a self.assertEqual({b}, done)
885n/a self.assertEqual({a}, pending)
886n/a self.assertAlmostEqual(0, loop.time())
887n/a
888n/a # move forward to close generator
889n/a loop.advance_time(10)
890n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
891n/a
892n/a def test_wait_first_exception_in_wait(self):
893n/a
894n/a def gen():
895n/a when = yield
896n/a self.assertAlmostEqual(10.0, when)
897n/a when = yield 0
898n/a self.assertAlmostEqual(0.01, when)
899n/a yield 0.01
900n/a
901n/a loop = self.new_test_loop(gen)
902n/a
903n/a # first_exception, exception during waiting
904n/a a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
905n/a
906n/a @asyncio.coroutine
907n/a def exc():
908n/a yield from asyncio.sleep(0.01, loop=loop)
909n/a raise ZeroDivisionError('err')
910n/a
911n/a b = self.new_task(loop, exc())
912n/a task = asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION,
913n/a loop=loop)
914n/a
915n/a done, pending = loop.run_until_complete(task)
916n/a self.assertEqual({b}, done)
917n/a self.assertEqual({a}, pending)
918n/a self.assertAlmostEqual(0.01, loop.time())
919n/a
920n/a # move forward to close generator
921n/a loop.advance_time(10)
922n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
923n/a
924n/a def test_wait_with_exception(self):
925n/a
926n/a def gen():
927n/a when = yield
928n/a self.assertAlmostEqual(0.1, when)
929n/a when = yield 0
930n/a self.assertAlmostEqual(0.15, when)
931n/a yield 0.15
932n/a
933n/a loop = self.new_test_loop(gen)
934n/a
935n/a a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
936n/a
937n/a @asyncio.coroutine
938n/a def sleeper():
939n/a yield from asyncio.sleep(0.15, loop=loop)
940n/a raise ZeroDivisionError('really')
941n/a
942n/a b = self.new_task(loop, sleeper())
943n/a
944n/a @asyncio.coroutine
945n/a def foo():
946n/a done, pending = yield from asyncio.wait([b, a], loop=loop)
947n/a self.assertEqual(len(done), 2)
948n/a self.assertEqual(pending, set())
949n/a errors = set(f for f in done if f.exception() is not None)
950n/a self.assertEqual(len(errors), 1)
951n/a
952n/a loop.run_until_complete(self.new_task(loop, foo()))
953n/a self.assertAlmostEqual(0.15, loop.time())
954n/a
955n/a loop.run_until_complete(self.new_task(loop, foo()))
956n/a self.assertAlmostEqual(0.15, loop.time())
957n/a
958n/a def test_wait_with_timeout(self):
959n/a
960n/a def gen():
961n/a when = yield
962n/a self.assertAlmostEqual(0.1, when)
963n/a when = yield 0
964n/a self.assertAlmostEqual(0.15, when)
965n/a when = yield 0
966n/a self.assertAlmostEqual(0.11, when)
967n/a yield 0.11
968n/a
969n/a loop = self.new_test_loop(gen)
970n/a
971n/a a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
972n/a b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
973n/a
974n/a @asyncio.coroutine
975n/a def foo():
976n/a done, pending = yield from asyncio.wait([b, a], timeout=0.11,
977n/a loop=loop)
978n/a self.assertEqual(done, set([a]))
979n/a self.assertEqual(pending, set([b]))
980n/a
981n/a loop.run_until_complete(self.new_task(loop, foo()))
982n/a self.assertAlmostEqual(0.11, loop.time())
983n/a
984n/a # move forward to close generator
985n/a loop.advance_time(10)
986n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
987n/a
988n/a def test_wait_concurrent_complete(self):
989n/a
990n/a def gen():
991n/a when = yield
992n/a self.assertAlmostEqual(0.1, when)
993n/a when = yield 0
994n/a self.assertAlmostEqual(0.15, when)
995n/a when = yield 0
996n/a self.assertAlmostEqual(0.1, when)
997n/a yield 0.1
998n/a
999n/a loop = self.new_test_loop(gen)
1000n/a
1001n/a a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
1002n/a b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
1003n/a
1004n/a done, pending = loop.run_until_complete(
1005n/a asyncio.wait([b, a], timeout=0.1, loop=loop))
1006n/a
1007n/a self.assertEqual(done, set([a]))
1008n/a self.assertEqual(pending, set([b]))
1009n/a self.assertAlmostEqual(0.1, loop.time())
1010n/a
1011n/a # move forward to close generator
1012n/a loop.advance_time(10)
1013n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
1014n/a
1015n/a def test_as_completed(self):
1016n/a
1017n/a def gen():
1018n/a yield 0
1019n/a yield 0
1020n/a yield 0.01
1021n/a yield 0
1022n/a
1023n/a loop = self.new_test_loop(gen)
1024n/a # disable "slow callback" warning
1025n/a loop.slow_callback_duration = 1.0
1026n/a completed = set()
1027n/a time_shifted = False
1028n/a
1029n/a @asyncio.coroutine
1030n/a def sleeper(dt, x):
1031n/a nonlocal time_shifted
1032n/a yield from asyncio.sleep(dt, loop=loop)
1033n/a completed.add(x)
1034n/a if not time_shifted and 'a' in completed and 'b' in completed:
1035n/a time_shifted = True
1036n/a loop.advance_time(0.14)
1037n/a return x
1038n/a
1039n/a a = sleeper(0.01, 'a')
1040n/a b = sleeper(0.01, 'b')
1041n/a c = sleeper(0.15, 'c')
1042n/a
1043n/a @asyncio.coroutine
1044n/a def foo():
1045n/a values = []
1046n/a for f in asyncio.as_completed([b, c, a], loop=loop):
1047n/a values.append((yield from f))
1048n/a return values
1049n/a
1050n/a res = loop.run_until_complete(self.new_task(loop, foo()))
1051n/a self.assertAlmostEqual(0.15, loop.time())
1052n/a self.assertTrue('a' in res[:2])
1053n/a self.assertTrue('b' in res[:2])
1054n/a self.assertEqual(res[2], 'c')
1055n/a
1056n/a # Doing it again should take no time and exercise a different path.
1057n/a res = loop.run_until_complete(self.new_task(loop, foo()))
1058n/a self.assertAlmostEqual(0.15, loop.time())
1059n/a
1060n/a def test_as_completed_with_timeout(self):
1061n/a
1062n/a def gen():
1063n/a yield
1064n/a yield 0
1065n/a yield 0
1066n/a yield 0.1
1067n/a
1068n/a loop = self.new_test_loop(gen)
1069n/a
1070n/a a = asyncio.sleep(0.1, 'a', loop=loop)
1071n/a b = asyncio.sleep(0.15, 'b', loop=loop)
1072n/a
1073n/a @asyncio.coroutine
1074n/a def foo():
1075n/a values = []
1076n/a for f in asyncio.as_completed([a, b], timeout=0.12, loop=loop):
1077n/a if values:
1078n/a loop.advance_time(0.02)
1079n/a try:
1080n/a v = yield from f
1081n/a values.append((1, v))
1082n/a except asyncio.TimeoutError as exc:
1083n/a values.append((2, exc))
1084n/a return values
1085n/a
1086n/a res = loop.run_until_complete(self.new_task(loop, foo()))
1087n/a self.assertEqual(len(res), 2, res)
1088n/a self.assertEqual(res[0], (1, 'a'))
1089n/a self.assertEqual(res[1][0], 2)
1090n/a self.assertIsInstance(res[1][1], asyncio.TimeoutError)
1091n/a self.assertAlmostEqual(0.12, loop.time())
1092n/a
1093n/a # move forward to close generator
1094n/a loop.advance_time(10)
1095n/a loop.run_until_complete(asyncio.wait([a, b], loop=loop))
1096n/a
1097n/a def test_as_completed_with_unused_timeout(self):
1098n/a
1099n/a def gen():
1100n/a yield
1101n/a yield 0
1102n/a yield 0.01
1103n/a
1104n/a loop = self.new_test_loop(gen)
1105n/a
1106n/a a = asyncio.sleep(0.01, 'a', loop=loop)
1107n/a
1108n/a @asyncio.coroutine
1109n/a def foo():
1110n/a for f in asyncio.as_completed([a], timeout=1, loop=loop):
1111n/a v = yield from f
1112n/a self.assertEqual(v, 'a')
1113n/a
1114n/a loop.run_until_complete(self.new_task(loop, foo()))
1115n/a
1116n/a def test_as_completed_reverse_wait(self):
1117n/a
1118n/a def gen():
1119n/a yield 0
1120n/a yield 0.05
1121n/a yield 0
1122n/a
1123n/a loop = self.new_test_loop(gen)
1124n/a
1125n/a a = asyncio.sleep(0.05, 'a', loop=loop)
1126n/a b = asyncio.sleep(0.10, 'b', loop=loop)
1127n/a fs = {a, b}
1128n/a futs = list(asyncio.as_completed(fs, loop=loop))
1129n/a self.assertEqual(len(futs), 2)
1130n/a
1131n/a x = loop.run_until_complete(futs[1])
1132n/a self.assertEqual(x, 'a')
1133n/a self.assertAlmostEqual(0.05, loop.time())
1134n/a loop.advance_time(0.05)
1135n/a y = loop.run_until_complete(futs[0])
1136n/a self.assertEqual(y, 'b')
1137n/a self.assertAlmostEqual(0.10, loop.time())
1138n/a
1139n/a def test_as_completed_concurrent(self):
1140n/a
1141n/a def gen():
1142n/a when = yield
1143n/a self.assertAlmostEqual(0.05, when)
1144n/a when = yield 0
1145n/a self.assertAlmostEqual(0.05, when)
1146n/a yield 0.05
1147n/a
1148n/a loop = self.new_test_loop(gen)
1149n/a
1150n/a a = asyncio.sleep(0.05, 'a', loop=loop)
1151n/a b = asyncio.sleep(0.05, 'b', loop=loop)
1152n/a fs = {a, b}
1153n/a futs = list(asyncio.as_completed(fs, loop=loop))
1154n/a self.assertEqual(len(futs), 2)
1155n/a waiter = asyncio.wait(futs, loop=loop)
1156n/a done, pending = loop.run_until_complete(waiter)
1157n/a self.assertEqual(set(f.result() for f in done), {'a', 'b'})
1158n/a
1159n/a def test_as_completed_duplicate_coroutines(self):
1160n/a
1161n/a @asyncio.coroutine
1162n/a def coro(s):
1163n/a return s
1164n/a
1165n/a @asyncio.coroutine
1166n/a def runner():
1167n/a result = []
1168n/a c = coro('ham')
1169n/a for f in asyncio.as_completed([c, c, coro('spam')],
1170n/a loop=self.loop):
1171n/a result.append((yield from f))
1172n/a return result
1173n/a
1174n/a fut = self.new_task(self.loop, runner())
1175n/a self.loop.run_until_complete(fut)
1176n/a result = fut.result()
1177n/a self.assertEqual(set(result), {'ham', 'spam'})
1178n/a self.assertEqual(len(result), 2)
1179n/a
1180n/a def test_sleep(self):
1181n/a
1182n/a def gen():
1183n/a when = yield
1184n/a self.assertAlmostEqual(0.05, when)
1185n/a when = yield 0.05
1186n/a self.assertAlmostEqual(0.1, when)
1187n/a yield 0.05
1188n/a
1189n/a loop = self.new_test_loop(gen)
1190n/a
1191n/a @asyncio.coroutine
1192n/a def sleeper(dt, arg):
1193n/a yield from asyncio.sleep(dt/2, loop=loop)
1194n/a res = yield from asyncio.sleep(dt/2, arg, loop=loop)
1195n/a return res
1196n/a
1197n/a t = self.new_task(loop, sleeper(0.1, 'yeah'))
1198n/a loop.run_until_complete(t)
1199n/a self.assertTrue(t.done())
1200n/a self.assertEqual(t.result(), 'yeah')
1201n/a self.assertAlmostEqual(0.1, loop.time())
1202n/a
1203n/a def test_sleep_cancel(self):
1204n/a
1205n/a def gen():
1206n/a when = yield
1207n/a self.assertAlmostEqual(10.0, when)
1208n/a yield 0
1209n/a
1210n/a loop = self.new_test_loop(gen)
1211n/a
1212n/a t = self.new_task(loop, asyncio.sleep(10.0, 'yeah', loop=loop))
1213n/a
1214n/a handle = None
1215n/a orig_call_later = loop.call_later
1216n/a
1217n/a def call_later(delay, callback, *args):
1218n/a nonlocal handle
1219n/a handle = orig_call_later(delay, callback, *args)
1220n/a return handle
1221n/a
1222n/a loop.call_later = call_later
1223n/a test_utils.run_briefly(loop)
1224n/a
1225n/a self.assertFalse(handle._cancelled)
1226n/a
1227n/a t.cancel()
1228n/a test_utils.run_briefly(loop)
1229n/a self.assertTrue(handle._cancelled)
1230n/a
1231n/a def test_task_cancel_sleeping_task(self):
1232n/a
1233n/a def gen():
1234n/a when = yield
1235n/a self.assertAlmostEqual(0.1, when)
1236n/a when = yield 0
1237n/a self.assertAlmostEqual(5000, when)
1238n/a yield 0.1
1239n/a
1240n/a loop = self.new_test_loop(gen)
1241n/a
1242n/a @asyncio.coroutine
1243n/a def sleep(dt):
1244n/a yield from asyncio.sleep(dt, loop=loop)
1245n/a
1246n/a @asyncio.coroutine
1247n/a def doit():
1248n/a sleeper = self.new_task(loop, sleep(5000))
1249n/a loop.call_later(0.1, sleeper.cancel)
1250n/a try:
1251n/a yield from sleeper
1252n/a except asyncio.CancelledError:
1253n/a return 'cancelled'
1254n/a else:
1255n/a return 'slept in'
1256n/a
1257n/a doer = doit()
1258n/a self.assertEqual(loop.run_until_complete(doer), 'cancelled')
1259n/a self.assertAlmostEqual(0.1, loop.time())
1260n/a
1261n/a def test_task_cancel_waiter_future(self):
1262n/a fut = self.new_future(self.loop)
1263n/a
1264n/a @asyncio.coroutine
1265n/a def coro():
1266n/a yield from fut
1267n/a
1268n/a task = self.new_task(self.loop, coro())
1269n/a test_utils.run_briefly(self.loop)
1270n/a self.assertIs(task._fut_waiter, fut)
1271n/a
1272n/a task.cancel()
1273n/a test_utils.run_briefly(self.loop)
1274n/a self.assertRaises(
1275n/a asyncio.CancelledError, self.loop.run_until_complete, task)
1276n/a self.assertIsNone(task._fut_waiter)
1277n/a self.assertTrue(fut.cancelled())
1278n/a
1279n/a def test_step_in_completed_task(self):
1280n/a @asyncio.coroutine
1281n/a def notmuch():
1282n/a return 'ko'
1283n/a
1284n/a gen = notmuch()
1285n/a task = self.new_task(self.loop, gen)
1286n/a task.set_result('ok')
1287n/a
1288n/a self.assertRaises(AssertionError, task._step)
1289n/a gen.close()
1290n/a
1291n/a def test_step_result(self):
1292n/a @asyncio.coroutine
1293n/a def notmuch():
1294n/a yield None
1295n/a yield 1
1296n/a return 'ko'
1297n/a
1298n/a self.assertRaises(
1299n/a RuntimeError, self.loop.run_until_complete, notmuch())
1300n/a
1301n/a def test_step_result_future(self):
1302n/a # If coroutine returns future, task waits on this future.
1303n/a
1304n/a class Fut(asyncio.Future):
1305n/a def __init__(self, *args, **kwds):
1306n/a self.cb_added = False
1307n/a super().__init__(*args, **kwds)
1308n/a
1309n/a def add_done_callback(self, fn):
1310n/a self.cb_added = True
1311n/a super().add_done_callback(fn)
1312n/a
1313n/a fut = Fut(loop=self.loop)
1314n/a result = None
1315n/a
1316n/a @asyncio.coroutine
1317n/a def wait_for_future():
1318n/a nonlocal result
1319n/a result = yield from fut
1320n/a
1321n/a t = self.new_task(self.loop, wait_for_future())
1322n/a test_utils.run_briefly(self.loop)
1323n/a self.assertTrue(fut.cb_added)
1324n/a
1325n/a res = object()
1326n/a fut.set_result(res)
1327n/a test_utils.run_briefly(self.loop)
1328n/a self.assertIs(res, result)
1329n/a self.assertTrue(t.done())
1330n/a self.assertIsNone(t.result())
1331n/a
1332n/a def test_step_with_baseexception(self):
1333n/a @asyncio.coroutine
1334n/a def notmutch():
1335n/a raise BaseException()
1336n/a
1337n/a task = self.new_task(self.loop, notmutch())
1338n/a self.assertRaises(BaseException, task._step)
1339n/a
1340n/a self.assertTrue(task.done())
1341n/a self.assertIsInstance(task.exception(), BaseException)
1342n/a
1343n/a def test_baseexception_during_cancel(self):
1344n/a
1345n/a def gen():
1346n/a when = yield
1347n/a self.assertAlmostEqual(10.0, when)
1348n/a yield 0
1349n/a
1350n/a loop = self.new_test_loop(gen)
1351n/a
1352n/a @asyncio.coroutine
1353n/a def sleeper():
1354n/a yield from asyncio.sleep(10, loop=loop)
1355n/a
1356n/a base_exc = BaseException()
1357n/a
1358n/a @asyncio.coroutine
1359n/a def notmutch():
1360n/a try:
1361n/a yield from sleeper()
1362n/a except asyncio.CancelledError:
1363n/a raise base_exc
1364n/a
1365n/a task = self.new_task(loop, notmutch())
1366n/a test_utils.run_briefly(loop)
1367n/a
1368n/a task.cancel()
1369n/a self.assertFalse(task.done())
1370n/a
1371n/a self.assertRaises(BaseException, test_utils.run_briefly, loop)
1372n/a
1373n/a self.assertTrue(task.done())
1374n/a self.assertFalse(task.cancelled())
1375n/a self.assertIs(task.exception(), base_exc)
1376n/a
1377n/a def test_iscoroutinefunction(self):
1378n/a def fn():
1379n/a pass
1380n/a
1381n/a self.assertFalse(asyncio.iscoroutinefunction(fn))
1382n/a
1383n/a def fn1():
1384n/a yield
1385n/a self.assertFalse(asyncio.iscoroutinefunction(fn1))
1386n/a
1387n/a @asyncio.coroutine
1388n/a def fn2():
1389n/a yield
1390n/a self.assertTrue(asyncio.iscoroutinefunction(fn2))
1391n/a
1392n/a self.assertFalse(asyncio.iscoroutinefunction(mock.Mock()))
1393n/a
1394n/a def test_yield_vs_yield_from(self):
1395n/a fut = self.new_future(self.loop)
1396n/a
1397n/a @asyncio.coroutine
1398n/a def wait_for_future():
1399n/a yield fut
1400n/a
1401n/a task = wait_for_future()
1402n/a with self.assertRaises(RuntimeError):
1403n/a self.loop.run_until_complete(task)
1404n/a
1405n/a self.assertFalse(fut.done())
1406n/a
1407n/a def test_yield_vs_yield_from_generator(self):
1408n/a @asyncio.coroutine
1409n/a def coro():
1410n/a yield
1411n/a
1412n/a @asyncio.coroutine
1413n/a def wait_for_future():
1414n/a gen = coro()
1415n/a try:
1416n/a yield gen
1417n/a finally:
1418n/a gen.close()
1419n/a
1420n/a task = wait_for_future()
1421n/a self.assertRaises(
1422n/a RuntimeError,
1423n/a self.loop.run_until_complete, task)
1424n/a
1425n/a def test_coroutine_non_gen_function(self):
1426n/a @asyncio.coroutine
1427n/a def func():
1428n/a return 'test'
1429n/a
1430n/a self.assertTrue(asyncio.iscoroutinefunction(func))
1431n/a
1432n/a coro = func()
1433n/a self.assertTrue(asyncio.iscoroutine(coro))
1434n/a
1435n/a res = self.loop.run_until_complete(coro)
1436n/a self.assertEqual(res, 'test')
1437n/a
1438n/a def test_coroutine_non_gen_function_return_future(self):
1439n/a fut = self.new_future(self.loop)
1440n/a
1441n/a @asyncio.coroutine
1442n/a def func():
1443n/a return fut
1444n/a
1445n/a @asyncio.coroutine
1446n/a def coro():
1447n/a fut.set_result('test')
1448n/a
1449n/a t1 = self.new_task(self.loop, func())
1450n/a t2 = self.new_task(self.loop, coro())
1451n/a res = self.loop.run_until_complete(t1)
1452n/a self.assertEqual(res, 'test')
1453n/a self.assertIsNone(t2.result())
1454n/a
1455n/a def test_current_task(self):
1456n/a Task = self.__class__.Task
1457n/a
1458n/a self.assertIsNone(Task.current_task(loop=self.loop))
1459n/a
1460n/a @asyncio.coroutine
1461n/a def coro(loop):
1462n/a self.assertTrue(Task.current_task(loop=loop) is task)
1463n/a
1464n/a task = self.new_task(self.loop, coro(self.loop))
1465n/a self.loop.run_until_complete(task)
1466n/a self.assertIsNone(Task.current_task(loop=self.loop))
1467n/a
1468n/a def test_current_task_with_interleaving_tasks(self):
1469n/a Task = self.__class__.Task
1470n/a
1471n/a self.assertIsNone(Task.current_task(loop=self.loop))
1472n/a
1473n/a fut1 = self.new_future(self.loop)
1474n/a fut2 = self.new_future(self.loop)
1475n/a
1476n/a @asyncio.coroutine
1477n/a def coro1(loop):
1478n/a self.assertTrue(Task.current_task(loop=loop) is task1)
1479n/a yield from fut1
1480n/a self.assertTrue(Task.current_task(loop=loop) is task1)
1481n/a fut2.set_result(True)
1482n/a
1483n/a @asyncio.coroutine
1484n/a def coro2(loop):
1485n/a self.assertTrue(Task.current_task(loop=loop) is task2)
1486n/a fut1.set_result(True)
1487n/a yield from fut2
1488n/a self.assertTrue(Task.current_task(loop=loop) is task2)
1489n/a
1490n/a task1 = self.new_task(self.loop, coro1(self.loop))
1491n/a task2 = self.new_task(self.loop, coro2(self.loop))
1492n/a
1493n/a self.loop.run_until_complete(asyncio.wait((task1, task2),
1494n/a loop=self.loop))
1495n/a self.assertIsNone(Task.current_task(loop=self.loop))
1496n/a
1497n/a # Some thorough tests for cancellation propagation through
1498n/a # coroutines, tasks and wait().
1499n/a
1500n/a def test_yield_future_passes_cancel(self):
1501n/a # Cancelling outer() cancels inner() cancels waiter.
1502n/a proof = 0
1503n/a waiter = self.new_future(self.loop)
1504n/a
1505n/a @asyncio.coroutine
1506n/a def inner():
1507n/a nonlocal proof
1508n/a try:
1509n/a yield from waiter
1510n/a except asyncio.CancelledError:
1511n/a proof += 1
1512n/a raise
1513n/a else:
1514n/a self.fail('got past sleep() in inner()')
1515n/a
1516n/a @asyncio.coroutine
1517n/a def outer():
1518n/a nonlocal proof
1519n/a try:
1520n/a yield from inner()
1521n/a except asyncio.CancelledError:
1522n/a proof += 100 # Expect this path.
1523n/a else:
1524n/a proof += 10
1525n/a
1526n/a f = asyncio.ensure_future(outer(), loop=self.loop)
1527n/a test_utils.run_briefly(self.loop)
1528n/a f.cancel()
1529n/a self.loop.run_until_complete(f)
1530n/a self.assertEqual(proof, 101)
1531n/a self.assertTrue(waiter.cancelled())
1532n/a
1533n/a def test_yield_wait_does_not_shield_cancel(self):
1534n/a # Cancelling outer() makes wait() return early, leaves inner()
1535n/a # running.
1536n/a proof = 0
1537n/a waiter = self.new_future(self.loop)
1538n/a
1539n/a @asyncio.coroutine
1540n/a def inner():
1541n/a nonlocal proof
1542n/a yield from waiter
1543n/a proof += 1
1544n/a
1545n/a @asyncio.coroutine
1546n/a def outer():
1547n/a nonlocal proof
1548n/a d, p = yield from asyncio.wait([inner()], loop=self.loop)
1549n/a proof += 100
1550n/a
1551n/a f = asyncio.ensure_future(outer(), loop=self.loop)
1552n/a test_utils.run_briefly(self.loop)
1553n/a f.cancel()
1554n/a self.assertRaises(
1555n/a asyncio.CancelledError, self.loop.run_until_complete, f)
1556n/a waiter.set_result(None)
1557n/a test_utils.run_briefly(self.loop)
1558n/a self.assertEqual(proof, 1)
1559n/a
1560n/a def test_shield_result(self):
1561n/a inner = self.new_future(self.loop)
1562n/a outer = asyncio.shield(inner)
1563n/a inner.set_result(42)
1564n/a res = self.loop.run_until_complete(outer)
1565n/a self.assertEqual(res, 42)
1566n/a
1567n/a def test_shield_exception(self):
1568n/a inner = self.new_future(self.loop)
1569n/a outer = asyncio.shield(inner)
1570n/a test_utils.run_briefly(self.loop)
1571n/a exc = RuntimeError('expected')
1572n/a inner.set_exception(exc)
1573n/a test_utils.run_briefly(self.loop)
1574n/a self.assertIs(outer.exception(), exc)
1575n/a
1576n/a def test_shield_cancel(self):
1577n/a inner = self.new_future(self.loop)
1578n/a outer = asyncio.shield(inner)
1579n/a test_utils.run_briefly(self.loop)
1580n/a inner.cancel()
1581n/a test_utils.run_briefly(self.loop)
1582n/a self.assertTrue(outer.cancelled())
1583n/a
1584n/a def test_shield_shortcut(self):
1585n/a fut = self.new_future(self.loop)
1586n/a fut.set_result(42)
1587n/a res = self.loop.run_until_complete(asyncio.shield(fut))
1588n/a self.assertEqual(res, 42)
1589n/a
1590n/a def test_shield_effect(self):
1591n/a # Cancelling outer() does not affect inner().
1592n/a proof = 0
1593n/a waiter = self.new_future(self.loop)
1594n/a
1595n/a @asyncio.coroutine
1596n/a def inner():
1597n/a nonlocal proof
1598n/a yield from waiter
1599n/a proof += 1
1600n/a
1601n/a @asyncio.coroutine
1602n/a def outer():
1603n/a nonlocal proof
1604n/a yield from asyncio.shield(inner(), loop=self.loop)
1605n/a proof += 100
1606n/a
1607n/a f = asyncio.ensure_future(outer(), loop=self.loop)
1608n/a test_utils.run_briefly(self.loop)
1609n/a f.cancel()
1610n/a with self.assertRaises(asyncio.CancelledError):
1611n/a self.loop.run_until_complete(f)
1612n/a waiter.set_result(None)
1613n/a test_utils.run_briefly(self.loop)
1614n/a self.assertEqual(proof, 1)
1615n/a
1616n/a def test_shield_gather(self):
1617n/a child1 = self.new_future(self.loop)
1618n/a child2 = self.new_future(self.loop)
1619n/a parent = asyncio.gather(child1, child2, loop=self.loop)
1620n/a outer = asyncio.shield(parent, loop=self.loop)
1621n/a test_utils.run_briefly(self.loop)
1622n/a outer.cancel()
1623n/a test_utils.run_briefly(self.loop)
1624n/a self.assertTrue(outer.cancelled())
1625n/a child1.set_result(1)
1626n/a child2.set_result(2)
1627n/a test_utils.run_briefly(self.loop)
1628n/a self.assertEqual(parent.result(), [1, 2])
1629n/a
1630n/a def test_gather_shield(self):
1631n/a child1 = self.new_future(self.loop)
1632n/a child2 = self.new_future(self.loop)
1633n/a inner1 = asyncio.shield(child1, loop=self.loop)
1634n/a inner2 = asyncio.shield(child2, loop=self.loop)
1635n/a parent = asyncio.gather(inner1, inner2, loop=self.loop)
1636n/a test_utils.run_briefly(self.loop)
1637n/a parent.cancel()
1638n/a # This should cancel inner1 and inner2 but bot child1 and child2.
1639n/a test_utils.run_briefly(self.loop)
1640n/a self.assertIsInstance(parent.exception(), asyncio.CancelledError)
1641n/a self.assertTrue(inner1.cancelled())
1642n/a self.assertTrue(inner2.cancelled())
1643n/a child1.set_result(1)
1644n/a child2.set_result(2)
1645n/a test_utils.run_briefly(self.loop)
1646n/a
1647n/a def test_as_completed_invalid_args(self):
1648n/a fut = self.new_future(self.loop)
1649n/a
1650n/a # as_completed() expects a list of futures, not a future instance
1651n/a self.assertRaises(TypeError, self.loop.run_until_complete,
1652n/a asyncio.as_completed(fut, loop=self.loop))
1653n/a coro = coroutine_function()
1654n/a self.assertRaises(TypeError, self.loop.run_until_complete,
1655n/a asyncio.as_completed(coro, loop=self.loop))
1656n/a coro.close()
1657n/a
1658n/a def test_wait_invalid_args(self):
1659n/a fut = self.new_future(self.loop)
1660n/a
1661n/a # wait() expects a list of futures, not a future instance
1662n/a self.assertRaises(TypeError, self.loop.run_until_complete,
1663n/a asyncio.wait(fut, loop=self.loop))
1664n/a coro = coroutine_function()
1665n/a self.assertRaises(TypeError, self.loop.run_until_complete,
1666n/a asyncio.wait(coro, loop=self.loop))
1667n/a coro.close()
1668n/a
1669n/a # wait() expects at least a future
1670n/a self.assertRaises(ValueError, self.loop.run_until_complete,
1671n/a asyncio.wait([], loop=self.loop))
1672n/a
1673n/a def test_corowrapper_mocks_generator(self):
1674n/a
1675n/a def check():
1676n/a # A function that asserts various things.
1677n/a # Called twice, with different debug flag values.
1678n/a
1679n/a @asyncio.coroutine
1680n/a def coro():
1681n/a # The actual coroutine.
1682n/a self.assertTrue(gen.gi_running)
1683n/a yield from fut
1684n/a
1685n/a # A completed Future used to run the coroutine.
1686n/a fut = self.new_future(self.loop)
1687n/a fut.set_result(None)
1688n/a
1689n/a # Call the coroutine.
1690n/a gen = coro()
1691n/a
1692n/a # Check some properties.
1693n/a self.assertTrue(asyncio.iscoroutine(gen))
1694n/a self.assertIsInstance(gen.gi_frame, types.FrameType)
1695n/a self.assertFalse(gen.gi_running)
1696n/a self.assertIsInstance(gen.gi_code, types.CodeType)
1697n/a
1698n/a # Run it.
1699n/a self.loop.run_until_complete(gen)
1700n/a
1701n/a # The frame should have changed.
1702n/a self.assertIsNone(gen.gi_frame)
1703n/a
1704n/a # Test with debug flag cleared.
1705n/a with set_coroutine_debug(False):
1706n/a check()
1707n/a
1708n/a # Test with debug flag set.
1709n/a with set_coroutine_debug(True):
1710n/a check()
1711n/a
1712n/a def test_yield_from_corowrapper(self):
1713n/a with set_coroutine_debug(True):
1714n/a @asyncio.coroutine
1715n/a def t1():
1716n/a return (yield from t2())
1717n/a
1718n/a @asyncio.coroutine
1719n/a def t2():
1720n/a f = self.new_future(self.loop)
1721n/a self.new_task(self.loop, t3(f))
1722n/a return (yield from f)
1723n/a
1724n/a @asyncio.coroutine
1725n/a def t3(f):
1726n/a f.set_result((1, 2, 3))
1727n/a
1728n/a task = self.new_task(self.loop, t1())
1729n/a val = self.loop.run_until_complete(task)
1730n/a self.assertEqual(val, (1, 2, 3))
1731n/a
1732n/a def test_yield_from_corowrapper_send(self):
1733n/a def foo():
1734n/a a = yield
1735n/a return a
1736n/a
1737n/a def call(arg):
1738n/a cw = asyncio.coroutines.CoroWrapper(foo())
1739n/a cw.send(None)
1740n/a try:
1741n/a cw.send(arg)
1742n/a except StopIteration as ex:
1743n/a return ex.args[0]
1744n/a else:
1745n/a raise AssertionError('StopIteration was expected')
1746n/a
1747n/a self.assertEqual(call((1, 2)), (1, 2))
1748n/a self.assertEqual(call('spam'), 'spam')
1749n/a
1750n/a def test_corowrapper_weakref(self):
1751n/a wd = weakref.WeakValueDictionary()
1752n/a def foo(): yield from []
1753n/a cw = asyncio.coroutines.CoroWrapper(foo())
1754n/a wd['cw'] = cw # Would fail without __weakref__ slot.
1755n/a cw.gen = None # Suppress warning from __del__.
1756n/a
1757n/a def test_corowrapper_throw(self):
1758n/a # Issue 429: CoroWrapper.throw must be compatible with gen.throw
1759n/a def foo():
1760n/a value = None
1761n/a while True:
1762n/a try:
1763n/a value = yield value
1764n/a except Exception as e:
1765n/a value = e
1766n/a
1767n/a exception = Exception("foo")
1768n/a cw = asyncio.coroutines.CoroWrapper(foo())
1769n/a cw.send(None)
1770n/a self.assertIs(exception, cw.throw(exception))
1771n/a
1772n/a cw = asyncio.coroutines.CoroWrapper(foo())
1773n/a cw.send(None)
1774n/a self.assertIs(exception, cw.throw(Exception, exception))
1775n/a
1776n/a cw = asyncio.coroutines.CoroWrapper(foo())
1777n/a cw.send(None)
1778n/a exception = cw.throw(Exception, "foo")
1779n/a self.assertIsInstance(exception, Exception)
1780n/a self.assertEqual(exception.args, ("foo", ))
1781n/a
1782n/a cw = asyncio.coroutines.CoroWrapper(foo())
1783n/a cw.send(None)
1784n/a exception = cw.throw(Exception, "foo", None)
1785n/a self.assertIsInstance(exception, Exception)
1786n/a self.assertEqual(exception.args, ("foo", ))
1787n/a
1788n/a @unittest.skipUnless(PY34,
1789n/a 'need python 3.4 or later')
1790n/a def test_log_destroyed_pending_task(self):
1791n/a Task = self.__class__.Task
1792n/a
1793n/a @asyncio.coroutine
1794n/a def kill_me(loop):
1795n/a future = self.new_future(loop)
1796n/a yield from future
1797n/a # at this point, the only reference to kill_me() task is
1798n/a # the Task._wakeup() method in future._callbacks
1799n/a raise Exception("code never reached")
1800n/a
1801n/a mock_handler = mock.Mock()
1802n/a self.loop.set_debug(True)
1803n/a self.loop.set_exception_handler(mock_handler)
1804n/a
1805n/a # schedule the task
1806n/a coro = kill_me(self.loop)
1807n/a task = asyncio.ensure_future(coro, loop=self.loop)
1808n/a self.assertEqual(Task.all_tasks(loop=self.loop), {task})
1809n/a
1810n/a # execute the task so it waits for future
1811n/a self.loop._run_once()
1812n/a self.assertEqual(len(self.loop._ready), 0)
1813n/a
1814n/a # remove the future used in kill_me(), and references to the task
1815n/a del coro.gi_frame.f_locals['future']
1816n/a coro = None
1817n/a source_traceback = task._source_traceback
1818n/a task = None
1819n/a
1820n/a # no more reference to kill_me() task: the task is destroyed by the GC
1821n/a support.gc_collect()
1822n/a
1823n/a self.assertEqual(Task.all_tasks(loop=self.loop), set())
1824n/a
1825n/a mock_handler.assert_called_with(self.loop, {
1826n/a 'message': 'Task was destroyed but it is pending!',
1827n/a 'task': mock.ANY,
1828n/a 'source_traceback': source_traceback,
1829n/a })
1830n/a mock_handler.reset_mock()
1831n/a
1832n/a @mock.patch('asyncio.coroutines.logger')
1833n/a def test_coroutine_never_yielded(self, m_log):
1834n/a with set_coroutine_debug(True):
1835n/a @asyncio.coroutine
1836n/a def coro_noop():
1837n/a pass
1838n/a
1839n/a tb_filename = __file__
1840n/a tb_lineno = sys._getframe().f_lineno + 2
1841n/a # create a coroutine object but don't use it
1842n/a coro_noop()
1843n/a support.gc_collect()
1844n/a
1845n/a self.assertTrue(m_log.error.called)
1846n/a message = m_log.error.call_args[0][0]
1847n/a func_filename, func_lineno = test_utils.get_function_source(coro_noop)
1848n/a
1849n/a regex = (r'^<CoroWrapper %s\(?\)? .* at %s:%s, .*> '
1850n/a r'was never yielded from\n'
1851n/a r'Coroutine object created at \(most recent call last\):\n'
1852n/a r'.*\n'
1853n/a r' File "%s", line %s, in test_coroutine_never_yielded\n'
1854n/a r' coro_noop\(\)$'
1855n/a % (re.escape(coro_noop.__qualname__),
1856n/a re.escape(func_filename), func_lineno,
1857n/a re.escape(tb_filename), tb_lineno))
1858n/a
1859n/a self.assertRegex(message, re.compile(regex, re.DOTALL))
1860n/a
1861n/a def test_return_coroutine_from_coroutine(self):
1862n/a """Return of @asyncio.coroutine()-wrapped function generator object
1863n/a from @asyncio.coroutine()-wrapped function should have same effect as
1864n/a returning generator object or Future."""
1865n/a def check():
1866n/a @asyncio.coroutine
1867n/a def outer_coro():
1868n/a @asyncio.coroutine
1869n/a def inner_coro():
1870n/a return 1
1871n/a
1872n/a return inner_coro()
1873n/a
1874n/a result = self.loop.run_until_complete(outer_coro())
1875n/a self.assertEqual(result, 1)
1876n/a
1877n/a # Test with debug flag cleared.
1878n/a with set_coroutine_debug(False):
1879n/a check()
1880n/a
1881n/a # Test with debug flag set.
1882n/a with set_coroutine_debug(True):
1883n/a check()
1884n/a
1885n/a def test_task_source_traceback(self):
1886n/a self.loop.set_debug(True)
1887n/a
1888n/a task = self.new_task(self.loop, coroutine_function())
1889n/a lineno = sys._getframe().f_lineno - 1
1890n/a self.assertIsInstance(task._source_traceback, list)
1891n/a self.assertEqual(task._source_traceback[-2][:3],
1892n/a (__file__,
1893n/a lineno,
1894n/a 'test_task_source_traceback'))
1895n/a self.loop.run_until_complete(task)
1896n/a
1897n/a def _test_cancel_wait_for(self, timeout):
1898n/a loop = asyncio.new_event_loop()
1899n/a self.addCleanup(loop.close)
1900n/a
1901n/a @asyncio.coroutine
1902n/a def blocking_coroutine():
1903n/a fut = self.new_future(loop)
1904n/a # Block: fut result is never set
1905n/a yield from fut
1906n/a
1907n/a task = loop.create_task(blocking_coroutine())
1908n/a
1909n/a wait = loop.create_task(asyncio.wait_for(task, timeout, loop=loop))
1910n/a loop.call_soon(wait.cancel)
1911n/a
1912n/a self.assertRaises(asyncio.CancelledError,
1913n/a loop.run_until_complete, wait)
1914n/a
1915n/a # Python issue #23219: cancelling the wait must also cancel the task
1916n/a self.assertTrue(task.cancelled())
1917n/a
1918n/a def test_cancel_blocking_wait_for(self):
1919n/a self._test_cancel_wait_for(None)
1920n/a
1921n/a def test_cancel_wait_for(self):
1922n/a self._test_cancel_wait_for(60.0)
1923n/a
1924n/a def test_cancel_gather(self):
1925n/a """Ensure that a gathering future refuses to be cancelled once all
1926n/a children are done"""
1927n/a loop = asyncio.new_event_loop()
1928n/a self.addCleanup(loop.close)
1929n/a
1930n/a fut = self.new_future(loop)
1931n/a # The indirection fut->child_coro is needed since otherwise the
1932n/a # gathering task is done at the same time as the child future
1933n/a def child_coro():
1934n/a return (yield from fut)
1935n/a gather_future = asyncio.gather(child_coro(), loop=loop)
1936n/a gather_task = asyncio.ensure_future(gather_future, loop=loop)
1937n/a
1938n/a cancel_result = None
1939n/a def cancelling_callback(_):
1940n/a nonlocal cancel_result
1941n/a cancel_result = gather_task.cancel()
1942n/a fut.add_done_callback(cancelling_callback)
1943n/a
1944n/a fut.set_result(42) # calls the cancelling_callback after fut is done()
1945n/a
1946n/a # At this point the task should complete.
1947n/a loop.run_until_complete(gather_task)
1948n/a
1949n/a # Python issue #26923: asyncio.gather drops cancellation
1950n/a self.assertEqual(cancel_result, False)
1951n/a self.assertFalse(gather_task.cancelled())
1952n/a self.assertEqual(gather_task.result(), [42])
1953n/a
1954n/a def test_exception_traceback(self):
1955n/a # See http://bugs.python.org/issue28843
1956n/a
1957n/a @asyncio.coroutine
1958n/a def foo():
1959n/a 1 / 0
1960n/a
1961n/a @asyncio.coroutine
1962n/a def main():
1963n/a task = self.new_task(self.loop, foo())
1964n/a yield # skip one loop iteration
1965n/a self.assertIsNotNone(task.exception().__traceback__)
1966n/a
1967n/a self.loop.run_until_complete(main())
1968n/a
1969n/a @mock.patch('asyncio.base_events.logger')
1970n/a def test_error_in_call_soon(self, m_log):
1971n/a def call_soon(callback, *args):
1972n/a raise ValueError
1973n/a self.loop.call_soon = call_soon
1974n/a
1975n/a @asyncio.coroutine
1976n/a def coro():
1977n/a pass
1978n/a
1979n/a self.assertFalse(m_log.error.called)
1980n/a
1981n/a with self.assertRaises(ValueError):
1982n/a self.new_task(self.loop, coro())
1983n/a
1984n/a self.assertTrue(m_log.error.called)
1985n/a message = m_log.error.call_args[0][0]
1986n/a self.assertIn('Task was destroyed but it is pending', message)
1987n/a
1988n/a self.assertEqual(self.Task.all_tasks(self.loop), set())
1989n/a
1990n/a
1991n/adef add_subclass_tests(cls):
1992n/a BaseTask = cls.Task
1993n/a BaseFuture = cls.Future
1994n/a
1995n/a if BaseTask is None or BaseFuture is None:
1996n/a return cls
1997n/a
1998n/a class CommonFuture:
1999n/a def __init__(self, *args, **kwargs):
2000n/a self.calls = collections.defaultdict(lambda: 0)
2001n/a super().__init__(*args, **kwargs)
2002n/a
2003n/a def _schedule_callbacks(self):
2004n/a self.calls['_schedule_callbacks'] += 1
2005n/a return super()._schedule_callbacks()
2006n/a
2007n/a def add_done_callback(self, *args):
2008n/a self.calls['add_done_callback'] += 1
2009n/a return super().add_done_callback(*args)
2010n/a
2011n/a class Task(CommonFuture, BaseTask):
2012n/a def _step(self, *args):
2013n/a self.calls['_step'] += 1
2014n/a return super()._step(*args)
2015n/a
2016n/a def _wakeup(self, *args):
2017n/a self.calls['_wakeup'] += 1
2018n/a return super()._wakeup(*args)
2019n/a
2020n/a class Future(CommonFuture, BaseFuture):
2021n/a pass
2022n/a
2023n/a def test_subclasses_ctask_cfuture(self):
2024n/a fut = self.Future(loop=self.loop)
2025n/a
2026n/a async def func():
2027n/a self.loop.call_soon(lambda: fut.set_result('spam'))
2028n/a return await fut
2029n/a
2030n/a task = self.Task(func(), loop=self.loop)
2031n/a
2032n/a result = self.loop.run_until_complete(task)
2033n/a
2034n/a self.assertEqual(result, 'spam')
2035n/a
2036n/a self.assertEqual(
2037n/a dict(task.calls),
2038n/a {'_step': 2, '_wakeup': 1, 'add_done_callback': 1,
2039n/a '_schedule_callbacks': 1})
2040n/a
2041n/a self.assertEqual(
2042n/a dict(fut.calls),
2043n/a {'add_done_callback': 1, '_schedule_callbacks': 1})
2044n/a
2045n/a # Add patched Task & Future back to the test case
2046n/a cls.Task = Task
2047n/a cls.Future = Future
2048n/a
2049n/a # Add an extra unit-test
2050n/a cls.test_subclasses_ctask_cfuture = test_subclasses_ctask_cfuture
2051n/a
2052n/a # Disable the "test_task_source_traceback" test
2053n/a # (the test is hardcoded for a particular call stack, which
2054n/a # is slightly different for Task subclasses)
2055n/a cls.test_task_source_traceback = None
2056n/a
2057n/a return cls
2058n/a
2059n/a
2060n/a@unittest.skipUnless(hasattr(futures, '_CFuture'),
2061n/a 'requires the C _asyncio module')
2062n/aclass CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase):
2063n/a Task = getattr(tasks, '_CTask', None)
2064n/a Future = getattr(futures, '_CFuture', None)
2065n/a
2066n/a
2067n/a@unittest.skipUnless(hasattr(futures, '_CFuture'),
2068n/a 'requires the C _asyncio module')
2069n/a@add_subclass_tests
2070n/aclass CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase):
2071n/a Task = getattr(tasks, '_CTask', None)
2072n/a Future = getattr(futures, '_CFuture', None)
2073n/a
2074n/a
2075n/a@unittest.skipUnless(hasattr(futures, '_CFuture'),
2076n/a 'requires the C _asyncio module')
2077n/aclass CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):
2078n/a Task = getattr(tasks, '_CTask', None)
2079n/a Future = futures._PyFuture
2080n/a
2081n/a
2082n/a@unittest.skipUnless(hasattr(futures, '_CFuture'),
2083n/a 'requires the C _asyncio module')
2084n/aclass PyTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase):
2085n/a Task = tasks._PyTask
2086n/a Future = getattr(futures, '_CFuture', None)
2087n/a
2088n/a
2089n/aclass PyTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):
2090n/a Task = tasks._PyTask
2091n/a Future = futures._PyFuture
2092n/a
2093n/a
2094n/a@add_subclass_tests
2095n/aclass PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase):
2096n/a Task = tasks._PyTask
2097n/a Future = futures._PyFuture
2098n/a
2099n/a
2100n/aclass GenericTaskTests(test_utils.TestCase):
2101n/a
2102n/a def test_future_subclass(self):
2103n/a self.assertTrue(issubclass(asyncio.Task, asyncio.Future))
2104n/a
2105n/a def test_asyncio_module_compiled(self):
2106n/a # Because of circular imports it's easy to make _asyncio
2107n/a # module non-importable. This is a simple test that will
2108n/a # fail on systems where C modules were successfully compiled
2109n/a # (hence the test for _functools), but _asyncio somehow didn't.
2110n/a try:
2111n/a import _functools
2112n/a except ImportError:
2113n/a pass
2114n/a else:
2115n/a try:
2116n/a import _asyncio
2117n/a except ImportError:
2118n/a self.fail('_asyncio module is missing')
2119n/a
2120n/a
2121n/aclass GatherTestsBase:
2122n/a
2123n/a def setUp(self):
2124n/a super().setUp()
2125n/a self.one_loop = self.new_test_loop()
2126n/a self.other_loop = self.new_test_loop()
2127n/a self.set_event_loop(self.one_loop, cleanup=False)
2128n/a
2129n/a def _run_loop(self, loop):
2130n/a while loop._ready:
2131n/a test_utils.run_briefly(loop)
2132n/a
2133n/a def _check_success(self, **kwargs):
2134n/a a, b, c = [asyncio.Future(loop=self.one_loop) for i in range(3)]
2135n/a fut = asyncio.gather(*self.wrap_futures(a, b, c), **kwargs)
2136n/a cb = test_utils.MockCallback()
2137n/a fut.add_done_callback(cb)
2138n/a b.set_result(1)
2139n/a a.set_result(2)
2140n/a self._run_loop(self.one_loop)
2141n/a self.assertEqual(cb.called, False)
2142n/a self.assertFalse(fut.done())
2143n/a c.set_result(3)
2144n/a self._run_loop(self.one_loop)
2145n/a cb.assert_called_once_with(fut)
2146n/a self.assertEqual(fut.result(), [2, 1, 3])
2147n/a
2148n/a def test_success(self):
2149n/a self._check_success()
2150n/a self._check_success(return_exceptions=False)
2151n/a
2152n/a def test_result_exception_success(self):
2153n/a self._check_success(return_exceptions=True)
2154n/a
2155n/a def test_one_exception(self):
2156n/a a, b, c, d, e = [asyncio.Future(loop=self.one_loop) for i in range(5)]
2157n/a fut = asyncio.gather(*self.wrap_futures(a, b, c, d, e))
2158n/a cb = test_utils.MockCallback()
2159n/a fut.add_done_callback(cb)
2160n/a exc = ZeroDivisionError()
2161n/a a.set_result(1)
2162n/a b.set_exception(exc)
2163n/a self._run_loop(self.one_loop)
2164n/a self.assertTrue(fut.done())
2165n/a cb.assert_called_once_with(fut)
2166n/a self.assertIs(fut.exception(), exc)
2167n/a # Does nothing
2168n/a c.set_result(3)
2169n/a d.cancel()
2170n/a e.set_exception(RuntimeError())
2171n/a e.exception()
2172n/a
2173n/a def test_return_exceptions(self):
2174n/a a, b, c, d = [asyncio.Future(loop=self.one_loop) for i in range(4)]
2175n/a fut = asyncio.gather(*self.wrap_futures(a, b, c, d),
2176n/a return_exceptions=True)
2177n/a cb = test_utils.MockCallback()
2178n/a fut.add_done_callback(cb)
2179n/a exc = ZeroDivisionError()
2180n/a exc2 = RuntimeError()
2181n/a b.set_result(1)
2182n/a c.set_exception(exc)
2183n/a a.set_result(3)
2184n/a self._run_loop(self.one_loop)
2185n/a self.assertFalse(fut.done())
2186n/a d.set_exception(exc2)
2187n/a self._run_loop(self.one_loop)
2188n/a self.assertTrue(fut.done())
2189n/a cb.assert_called_once_with(fut)
2190n/a self.assertEqual(fut.result(), [3, 1, exc, exc2])
2191n/a
2192n/a def test_env_var_debug(self):
2193n/a aio_path = os.path.dirname(os.path.dirname(asyncio.__file__))
2194n/a
2195n/a code = '\n'.join((
2196n/a 'import asyncio.coroutines',
2197n/a 'print(asyncio.coroutines._DEBUG)'))
2198n/a
2199n/a # Test with -E to not fail if the unit test was run with
2200n/a # PYTHONASYNCIODEBUG set to a non-empty string
2201n/a sts, stdout, stderr = assert_python_ok('-E', '-c', code,
2202n/a PYTHONPATH=aio_path)
2203n/a self.assertEqual(stdout.rstrip(), b'False')
2204n/a
2205n/a sts, stdout, stderr = assert_python_ok('-c', code,
2206n/a PYTHONASYNCIODEBUG='',
2207n/a PYTHONPATH=aio_path)
2208n/a self.assertEqual(stdout.rstrip(), b'False')
2209n/a
2210n/a sts, stdout, stderr = assert_python_ok('-c', code,
2211n/a PYTHONASYNCIODEBUG='1',
2212n/a PYTHONPATH=aio_path)
2213n/a self.assertEqual(stdout.rstrip(), b'True')
2214n/a
2215n/a sts, stdout, stderr = assert_python_ok('-E', '-c', code,
2216n/a PYTHONASYNCIODEBUG='1',
2217n/a PYTHONPATH=aio_path)
2218n/a self.assertEqual(stdout.rstrip(), b'False')
2219n/a
2220n/a
2221n/aclass FutureGatherTests(GatherTestsBase, test_utils.TestCase):
2222n/a
2223n/a def wrap_futures(self, *futures):
2224n/a return futures
2225n/a
2226n/a def _check_empty_sequence(self, seq_or_iter):
2227n/a asyncio.set_event_loop(self.one_loop)
2228n/a self.addCleanup(asyncio.set_event_loop, None)
2229n/a fut = asyncio.gather(*seq_or_iter)
2230n/a self.assertIsInstance(fut, asyncio.Future)
2231n/a self.assertIs(fut._loop, self.one_loop)
2232n/a self._run_loop(self.one_loop)
2233n/a self.assertTrue(fut.done())
2234n/a self.assertEqual(fut.result(), [])
2235n/a fut = asyncio.gather(*seq_or_iter, loop=self.other_loop)
2236n/a self.assertIs(fut._loop, self.other_loop)
2237n/a
2238n/a def test_constructor_empty_sequence(self):
2239n/a self._check_empty_sequence([])
2240n/a self._check_empty_sequence(())
2241n/a self._check_empty_sequence(set())
2242n/a self._check_empty_sequence(iter(""))
2243n/a
2244n/a def test_constructor_heterogenous_futures(self):
2245n/a fut1 = asyncio.Future(loop=self.one_loop)
2246n/a fut2 = asyncio.Future(loop=self.other_loop)
2247n/a with self.assertRaises(ValueError):
2248n/a asyncio.gather(fut1, fut2)
2249n/a with self.assertRaises(ValueError):
2250n/a asyncio.gather(fut1, loop=self.other_loop)
2251n/a
2252n/a def test_constructor_homogenous_futures(self):
2253n/a children = [asyncio.Future(loop=self.other_loop) for i in range(3)]
2254n/a fut = asyncio.gather(*children)
2255n/a self.assertIs(fut._loop, self.other_loop)
2256n/a self._run_loop(self.other_loop)
2257n/a self.assertFalse(fut.done())
2258n/a fut = asyncio.gather(*children, loop=self.other_loop)
2259n/a self.assertIs(fut._loop, self.other_loop)
2260n/a self._run_loop(self.other_loop)
2261n/a self.assertFalse(fut.done())
2262n/a
2263n/a def test_one_cancellation(self):
2264n/a a, b, c, d, e = [asyncio.Future(loop=self.one_loop) for i in range(5)]
2265n/a fut = asyncio.gather(a, b, c, d, e)
2266n/a cb = test_utils.MockCallback()
2267n/a fut.add_done_callback(cb)
2268n/a a.set_result(1)
2269n/a b.cancel()
2270n/a self._run_loop(self.one_loop)
2271n/a self.assertTrue(fut.done())
2272n/a cb.assert_called_once_with(fut)
2273n/a self.assertFalse(fut.cancelled())
2274n/a self.assertIsInstance(fut.exception(), asyncio.CancelledError)
2275n/a # Does nothing
2276n/a c.set_result(3)
2277n/a d.cancel()
2278n/a e.set_exception(RuntimeError())
2279n/a e.exception()
2280n/a
2281n/a def test_result_exception_one_cancellation(self):
2282n/a a, b, c, d, e, f = [asyncio.Future(loop=self.one_loop)
2283n/a for i in range(6)]
2284n/a fut = asyncio.gather(a, b, c, d, e, f, return_exceptions=True)
2285n/a cb = test_utils.MockCallback()
2286n/a fut.add_done_callback(cb)
2287n/a a.set_result(1)
2288n/a zde = ZeroDivisionError()
2289n/a b.set_exception(zde)
2290n/a c.cancel()
2291n/a self._run_loop(self.one_loop)
2292n/a self.assertFalse(fut.done())
2293n/a d.set_result(3)
2294n/a e.cancel()
2295n/a rte = RuntimeError()
2296n/a f.set_exception(rte)
2297n/a res = self.one_loop.run_until_complete(fut)
2298n/a self.assertIsInstance(res[2], asyncio.CancelledError)
2299n/a self.assertIsInstance(res[4], asyncio.CancelledError)
2300n/a res[2] = res[4] = None
2301n/a self.assertEqual(res, [1, zde, None, 3, None, rte])
2302n/a cb.assert_called_once_with(fut)
2303n/a
2304n/a
2305n/aclass CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
2306n/a
2307n/a def setUp(self):
2308n/a super().setUp()
2309n/a asyncio.set_event_loop(self.one_loop)
2310n/a
2311n/a def wrap_futures(self, *futures):
2312n/a coros = []
2313n/a for fut in futures:
2314n/a @asyncio.coroutine
2315n/a def coro(fut=fut):
2316n/a return (yield from fut)
2317n/a coros.append(coro())
2318n/a return coros
2319n/a
2320n/a def test_constructor_loop_selection(self):
2321n/a @asyncio.coroutine
2322n/a def coro():
2323n/a return 'abc'
2324n/a gen1 = coro()
2325n/a gen2 = coro()
2326n/a fut = asyncio.gather(gen1, gen2)
2327n/a self.assertIs(fut._loop, self.one_loop)
2328n/a self.one_loop.run_until_complete(fut)
2329n/a
2330n/a self.set_event_loop(self.other_loop, cleanup=False)
2331n/a gen3 = coro()
2332n/a gen4 = coro()
2333n/a fut2 = asyncio.gather(gen3, gen4, loop=self.other_loop)
2334n/a self.assertIs(fut2._loop, self.other_loop)
2335n/a self.other_loop.run_until_complete(fut2)
2336n/a
2337n/a def test_duplicate_coroutines(self):
2338n/a @asyncio.coroutine
2339n/a def coro(s):
2340n/a return s
2341n/a c = coro('abc')
2342n/a fut = asyncio.gather(c, c, coro('def'), c, loop=self.one_loop)
2343n/a self._run_loop(self.one_loop)
2344n/a self.assertEqual(fut.result(), ['abc', 'abc', 'def', 'abc'])
2345n/a
2346n/a def test_cancellation_broadcast(self):
2347n/a # Cancelling outer() cancels all children.
2348n/a proof = 0
2349n/a waiter = asyncio.Future(loop=self.one_loop)
2350n/a
2351n/a @asyncio.coroutine
2352n/a def inner():
2353n/a nonlocal proof
2354n/a yield from waiter
2355n/a proof += 1
2356n/a
2357n/a child1 = asyncio.ensure_future(inner(), loop=self.one_loop)
2358n/a child2 = asyncio.ensure_future(inner(), loop=self.one_loop)
2359n/a gatherer = None
2360n/a
2361n/a @asyncio.coroutine
2362n/a def outer():
2363n/a nonlocal proof, gatherer
2364n/a gatherer = asyncio.gather(child1, child2, loop=self.one_loop)
2365n/a yield from gatherer
2366n/a proof += 100
2367n/a
2368n/a f = asyncio.ensure_future(outer(), loop=self.one_loop)
2369n/a test_utils.run_briefly(self.one_loop)
2370n/a self.assertTrue(f.cancel())
2371n/a with self.assertRaises(asyncio.CancelledError):
2372n/a self.one_loop.run_until_complete(f)
2373n/a self.assertFalse(gatherer.cancel())
2374n/a self.assertTrue(waiter.cancelled())
2375n/a self.assertTrue(child1.cancelled())
2376n/a self.assertTrue(child2.cancelled())
2377n/a test_utils.run_briefly(self.one_loop)
2378n/a self.assertEqual(proof, 0)
2379n/a
2380n/a def test_exception_marking(self):
2381n/a # Test for the first line marked "Mark exception retrieved."
2382n/a
2383n/a @asyncio.coroutine
2384n/a def inner(f):
2385n/a yield from f
2386n/a raise RuntimeError('should not be ignored')
2387n/a
2388n/a a = asyncio.Future(loop=self.one_loop)
2389n/a b = asyncio.Future(loop=self.one_loop)
2390n/a
2391n/a @asyncio.coroutine
2392n/a def outer():
2393n/a yield from asyncio.gather(inner(a), inner(b), loop=self.one_loop)
2394n/a
2395n/a f = asyncio.ensure_future(outer(), loop=self.one_loop)
2396n/a test_utils.run_briefly(self.one_loop)
2397n/a a.set_result(None)
2398n/a test_utils.run_briefly(self.one_loop)
2399n/a b.set_result(None)
2400n/a test_utils.run_briefly(self.one_loop)
2401n/a self.assertIsInstance(f.exception(), RuntimeError)
2402n/a
2403n/a
2404n/aclass RunCoroutineThreadsafeTests(test_utils.TestCase):
2405n/a """Test case for asyncio.run_coroutine_threadsafe."""
2406n/a
2407n/a def setUp(self):
2408n/a super().setUp()
2409n/a self.loop = asyncio.new_event_loop()
2410n/a self.set_event_loop(self.loop) # Will cleanup properly
2411n/a
2412n/a @asyncio.coroutine
2413n/a def add(self, a, b, fail=False, cancel=False):
2414n/a """Wait 0.05 second and return a + b."""
2415n/a yield from asyncio.sleep(0.05, loop=self.loop)
2416n/a if fail:
2417n/a raise RuntimeError("Fail!")
2418n/a if cancel:
2419n/a asyncio.tasks.Task.current_task(self.loop).cancel()
2420n/a yield
2421n/a return a + b
2422n/a
2423n/a def target(self, fail=False, cancel=False, timeout=None,
2424n/a advance_coro=False):
2425n/a """Run add coroutine in the event loop."""
2426n/a coro = self.add(1, 2, fail=fail, cancel=cancel)
2427n/a future = asyncio.run_coroutine_threadsafe(coro, self.loop)
2428n/a if advance_coro:
2429n/a # this is for test_run_coroutine_threadsafe_task_factory_exception;
2430n/a # otherwise it spills errors and breaks **other** unittests, since
2431n/a # 'target' is interacting with threads.
2432n/a
2433n/a # With this call, `coro` will be advanced, so that
2434n/a # CoroWrapper.__del__ won't do anything when asyncio tests run
2435n/a # in debug mode.
2436n/a self.loop.call_soon_threadsafe(coro.send, None)
2437n/a try:
2438n/a return future.result(timeout)
2439n/a finally:
2440n/a future.done() or future.cancel()
2441n/a
2442n/a def test_run_coroutine_threadsafe(self):
2443n/a """Test coroutine submission from a thread to an event loop."""
2444n/a future = self.loop.run_in_executor(None, self.target)
2445n/a result = self.loop.run_until_complete(future)
2446n/a self.assertEqual(result, 3)
2447n/a
2448n/a def test_run_coroutine_threadsafe_with_exception(self):
2449n/a """Test coroutine submission from a thread to an event loop
2450n/a when an exception is raised."""
2451n/a future = self.loop.run_in_executor(None, self.target, True)
2452n/a with self.assertRaises(RuntimeError) as exc_context:
2453n/a self.loop.run_until_complete(future)
2454n/a self.assertIn("Fail!", exc_context.exception.args)
2455n/a
2456n/a def test_run_coroutine_threadsafe_with_timeout(self):
2457n/a """Test coroutine submission from a thread to an event loop
2458n/a when a timeout is raised."""
2459n/a callback = lambda: self.target(timeout=0)
2460n/a future = self.loop.run_in_executor(None, callback)
2461n/a with self.assertRaises(asyncio.TimeoutError):
2462n/a self.loop.run_until_complete(future)
2463n/a test_utils.run_briefly(self.loop)
2464n/a # Check that there's no pending task (add has been cancelled)
2465n/a for task in asyncio.Task.all_tasks(self.loop):
2466n/a self.assertTrue(task.done())
2467n/a
2468n/a def test_run_coroutine_threadsafe_task_cancelled(self):
2469n/a """Test coroutine submission from a tread to an event loop
2470n/a when the task is cancelled."""
2471n/a callback = lambda: self.target(cancel=True)
2472n/a future = self.loop.run_in_executor(None, callback)
2473n/a with self.assertRaises(asyncio.CancelledError):
2474n/a self.loop.run_until_complete(future)
2475n/a
2476n/a def test_run_coroutine_threadsafe_task_factory_exception(self):
2477n/a """Test coroutine submission from a tread to an event loop
2478n/a when the task factory raise an exception."""
2479n/a # Schedule the target
2480n/a future = self.loop.run_in_executor(
2481n/a None, lambda: self.target(advance_coro=True))
2482n/a # Set corrupted task factory
2483n/a self.loop.set_task_factory(lambda loop, coro: wrong_name)
2484n/a # Set exception handler
2485n/a callback = test_utils.MockCallback()
2486n/a self.loop.set_exception_handler(callback)
2487n/a # Run event loop
2488n/a with self.assertRaises(NameError) as exc_context:
2489n/a self.loop.run_until_complete(future)
2490n/a # Check exceptions
2491n/a self.assertIn('wrong_name', exc_context.exception.args[0])
2492n/a self.assertEqual(len(callback.call_args_list), 1)
2493n/a (loop, context), kwargs = callback.call_args
2494n/a self.assertEqual(context['exception'], exc_context.exception)
2495n/a
2496n/a
2497n/aclass SleepTests(test_utils.TestCase):
2498n/a def setUp(self):
2499n/a super().setUp()
2500n/a self.loop = asyncio.new_event_loop()
2501n/a asyncio.set_event_loop(None)
2502n/a
2503n/a def tearDown(self):
2504n/a self.loop.close()
2505n/a self.loop = None
2506n/a super().tearDown()
2507n/a
2508n/a def test_sleep_zero(self):
2509n/a result = 0
2510n/a
2511n/a def inc_result(num):
2512n/a nonlocal result
2513n/a result += num
2514n/a
2515n/a @asyncio.coroutine
2516n/a def coro():
2517n/a self.loop.call_soon(inc_result, 1)
2518n/a self.assertEqual(result, 0)
2519n/a num = yield from asyncio.sleep(0, loop=self.loop, result=10)
2520n/a self.assertEqual(result, 1) # inc'ed by call_soon
2521n/a inc_result(num) # num should be 11
2522n/a
2523n/a self.loop.run_until_complete(coro())
2524n/a self.assertEqual(result, 11)
2525n/a
2526n/a
2527n/aif __name__ == '__main__':
2528n/a unittest.main()