blob: c24fbea5b0945725ffce3e521d181c02fc1e475c [file] [log] [blame]
Yury Selivanoveb636452016-09-08 22:01:51 -07001import inspect
2import sys
3import types
4import unittest
5
6from unittest import mock
7
Martin Panter94332cb2016-10-20 05:10:44 +00008from test.support import import_module
9asyncio = import_module("asyncio")
10
Yury Selivanoveb636452016-09-08 22:01:51 -070011
12class AwaitException(Exception):
13 pass
14
15
16@types.coroutine
17def awaitable(*, throw=False):
18 if throw:
19 yield ('throw',)
20 else:
21 yield ('result',)
22
23
24def run_until_complete(coro):
25 exc = False
26 while True:
27 try:
28 if exc:
29 exc = False
30 fut = coro.throw(AwaitException)
31 else:
32 fut = coro.send(None)
33 except StopIteration as ex:
34 return ex.args[0]
35
36 if fut == ('throw',):
37 exc = True
38
39
40def to_list(gen):
41 async def iterate():
42 res = []
43 async for i in gen:
44 res.append(i)
45 return res
46
47 return run_until_complete(iterate())
48
49
50class AsyncGenSyntaxTest(unittest.TestCase):
51
52 def test_async_gen_syntax_01(self):
53 code = '''async def foo():
54 await abc
55 yield from 123
56 '''
57
58 with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
59 exec(code, {}, {})
60
61 def test_async_gen_syntax_02(self):
62 code = '''async def foo():
63 yield from 123
64 '''
65
66 with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
67 exec(code, {}, {})
68
69 def test_async_gen_syntax_03(self):
70 code = '''async def foo():
71 await abc
72 yield
73 return 123
74 '''
75
76 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
77 exec(code, {}, {})
78
79 def test_async_gen_syntax_04(self):
80 code = '''async def foo():
81 yield
82 return 123
83 '''
84
85 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
86 exec(code, {}, {})
87
88 def test_async_gen_syntax_05(self):
89 code = '''async def foo():
90 if 0:
91 yield
92 return 12
93 '''
94
95 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
96 exec(code, {}, {})
97
98
99class AsyncGenTest(unittest.TestCase):
100
101 def compare_generators(self, sync_gen, async_gen):
102 def sync_iterate(g):
103 res = []
104 while True:
105 try:
106 res.append(g.__next__())
107 except StopIteration:
108 res.append('STOP')
109 break
110 except Exception as ex:
111 res.append(str(type(ex)))
112 return res
113
114 def async_iterate(g):
115 res = []
116 while True:
117 try:
118 g.__anext__().__next__()
119 except StopAsyncIteration:
120 res.append('STOP')
121 break
122 except StopIteration as ex:
123 if ex.args:
124 res.append(ex.args[0])
125 else:
126 res.append('EMPTY StopIteration')
127 break
128 except Exception as ex:
129 res.append(str(type(ex)))
130 return res
131
132 sync_gen_result = sync_iterate(sync_gen)
133 async_gen_result = async_iterate(async_gen)
134 self.assertEqual(sync_gen_result, async_gen_result)
135 return async_gen_result
136
137 def test_async_gen_iteration_01(self):
138 async def gen():
139 await awaitable()
140 a = yield 123
141 self.assertIs(a, None)
142 await awaitable()
143 yield 456
144 await awaitable()
145 yield 789
146
147 self.assertEqual(to_list(gen()), [123, 456, 789])
148
149 def test_async_gen_iteration_02(self):
150 async def gen():
151 await awaitable()
152 yield 123
153 await awaitable()
154
155 g = gen()
156 ai = g.__aiter__()
157 self.assertEqual(ai.__anext__().__next__(), ('result',))
158
159 try:
160 ai.__anext__().__next__()
161 except StopIteration as ex:
162 self.assertEqual(ex.args[0], 123)
163 else:
164 self.fail('StopIteration was not raised')
165
166 self.assertEqual(ai.__anext__().__next__(), ('result',))
167
168 try:
169 ai.__anext__().__next__()
170 except StopAsyncIteration as ex:
171 self.assertFalse(ex.args)
172 else:
173 self.fail('StopAsyncIteration was not raised')
174
175 def test_async_gen_exception_03(self):
176 async def gen():
177 await awaitable()
178 yield 123
179 await awaitable(throw=True)
180 yield 456
181
182 with self.assertRaises(AwaitException):
183 to_list(gen())
184
185 def test_async_gen_exception_04(self):
186 async def gen():
187 await awaitable()
188 yield 123
189 1 / 0
190
191 g = gen()
192 ai = g.__aiter__()
193 self.assertEqual(ai.__anext__().__next__(), ('result',))
194
195 try:
196 ai.__anext__().__next__()
197 except StopIteration as ex:
198 self.assertEqual(ex.args[0], 123)
199 else:
200 self.fail('StopIteration was not raised')
201
202 with self.assertRaises(ZeroDivisionError):
203 ai.__anext__().__next__()
204
205 def test_async_gen_exception_05(self):
206 async def gen():
207 yield 123
208 raise StopAsyncIteration
209
210 with self.assertRaisesRegex(RuntimeError,
211 'async generator.*StopAsyncIteration'):
212 to_list(gen())
213
214 def test_async_gen_exception_06(self):
215 async def gen():
216 yield 123
217 raise StopIteration
218
219 with self.assertRaisesRegex(RuntimeError,
220 'async generator.*StopIteration'):
221 to_list(gen())
222
223 def test_async_gen_exception_07(self):
224 def sync_gen():
225 try:
226 yield 1
227 1 / 0
228 finally:
229 yield 2
230 yield 3
231
232 yield 100
233
234 async def async_gen():
235 try:
236 yield 1
237 1 / 0
238 finally:
239 yield 2
240 yield 3
241
242 yield 100
243
244 self.compare_generators(sync_gen(), async_gen())
245
246 def test_async_gen_exception_08(self):
247 def sync_gen():
248 try:
249 yield 1
250 finally:
251 yield 2
252 1 / 0
253 yield 3
254
255 yield 100
256
257 async def async_gen():
258 try:
259 yield 1
260 await awaitable()
261 finally:
262 await awaitable()
263 yield 2
264 1 / 0
265 yield 3
266
267 yield 100
268
269 self.compare_generators(sync_gen(), async_gen())
270
271 def test_async_gen_exception_09(self):
272 def sync_gen():
273 try:
274 yield 1
275 1 / 0
276 finally:
277 yield 2
278 yield 3
279
280 yield 100
281
282 async def async_gen():
283 try:
284 await awaitable()
285 yield 1
286 1 / 0
287 finally:
288 yield 2
289 await awaitable()
290 yield 3
291
292 yield 100
293
294 self.compare_generators(sync_gen(), async_gen())
295
296 def test_async_gen_exception_10(self):
297 async def gen():
298 yield 123
299 with self.assertRaisesRegex(TypeError,
300 "non-None value .* async generator"):
301 gen().__anext__().send(100)
302
303 def test_async_gen_api_01(self):
304 async def gen():
305 yield 123
306
307 g = gen()
308
309 self.assertEqual(g.__name__, 'gen')
310 g.__name__ = '123'
311 self.assertEqual(g.__name__, '123')
312
313 self.assertIn('.gen', g.__qualname__)
314 g.__qualname__ = '123'
315 self.assertEqual(g.__qualname__, '123')
316
317 self.assertIsNone(g.ag_await)
318 self.assertIsInstance(g.ag_frame, types.FrameType)
319 self.assertFalse(g.ag_running)
320 self.assertIsInstance(g.ag_code, types.CodeType)
321
322 self.assertTrue(inspect.isawaitable(g.aclose()))
323
324
325class AsyncGenAsyncioTest(unittest.TestCase):
326
327 def setUp(self):
328 self.loop = asyncio.new_event_loop()
329 asyncio.set_event_loop(None)
330
331 def tearDown(self):
332 self.loop.close()
333 self.loop = None
334
335 async def to_list(self, gen):
336 res = []
337 async for i in gen:
338 res.append(i)
339 return res
340
341 def test_async_gen_asyncio_01(self):
342 async def gen():
343 yield 1
344 await asyncio.sleep(0.01, loop=self.loop)
345 yield 2
346 await asyncio.sleep(0.01, loop=self.loop)
347 return
348 yield 3
349
350 res = self.loop.run_until_complete(self.to_list(gen()))
351 self.assertEqual(res, [1, 2])
352
353 def test_async_gen_asyncio_02(self):
354 async def gen():
355 yield 1
356 await asyncio.sleep(0.01, loop=self.loop)
357 yield 2
358 1 / 0
359 yield 3
360
361 with self.assertRaises(ZeroDivisionError):
362 self.loop.run_until_complete(self.to_list(gen()))
363
364 def test_async_gen_asyncio_03(self):
365 loop = self.loop
366
367 class Gen:
368 async def __aiter__(self):
369 yield 1
370 await asyncio.sleep(0.01, loop=loop)
371 yield 2
372
373 res = loop.run_until_complete(self.to_list(Gen()))
374 self.assertEqual(res, [1, 2])
375
376 def test_async_gen_asyncio_anext_04(self):
377 async def foo():
378 yield 1
379 await asyncio.sleep(0.01, loop=self.loop)
380 try:
381 yield 2
382 yield 3
383 except ZeroDivisionError:
384 yield 1000
385 await asyncio.sleep(0.01, loop=self.loop)
386 yield 4
387
388 async def run1():
389 it = foo().__aiter__()
390
391 self.assertEqual(await it.__anext__(), 1)
392 self.assertEqual(await it.__anext__(), 2)
393 self.assertEqual(await it.__anext__(), 3)
394 self.assertEqual(await it.__anext__(), 4)
395 with self.assertRaises(StopAsyncIteration):
396 await it.__anext__()
397 with self.assertRaises(StopAsyncIteration):
398 await it.__anext__()
399
400 async def run2():
401 it = foo().__aiter__()
402
403 self.assertEqual(await it.__anext__(), 1)
404 self.assertEqual(await it.__anext__(), 2)
405 try:
406 it.__anext__().throw(ZeroDivisionError)
407 except StopIteration as ex:
408 self.assertEqual(ex.args[0], 1000)
409 else:
410 self.fail('StopIteration was not raised')
411 self.assertEqual(await it.__anext__(), 4)
412 with self.assertRaises(StopAsyncIteration):
413 await it.__anext__()
414
415 self.loop.run_until_complete(run1())
416 self.loop.run_until_complete(run2())
417
418 def test_async_gen_asyncio_anext_05(self):
419 async def foo():
420 v = yield 1
421 v = yield v
422 yield v * 100
423
424 async def run():
425 it = foo().__aiter__()
426
427 try:
428 it.__anext__().send(None)
429 except StopIteration as ex:
430 self.assertEqual(ex.args[0], 1)
431 else:
432 self.fail('StopIteration was not raised')
433
434 try:
435 it.__anext__().send(10)
436 except StopIteration as ex:
437 self.assertEqual(ex.args[0], 10)
438 else:
439 self.fail('StopIteration was not raised')
440
441 try:
442 it.__anext__().send(12)
443 except StopIteration as ex:
444 self.assertEqual(ex.args[0], 1200)
445 else:
446 self.fail('StopIteration was not raised')
447
448 with self.assertRaises(StopAsyncIteration):
449 await it.__anext__()
450
451 self.loop.run_until_complete(run())
452
453 def test_async_gen_asyncio_aclose_06(self):
454 async def foo():
455 try:
456 yield 1
457 1 / 0
458 finally:
459 await asyncio.sleep(0.01, loop=self.loop)
460 yield 12
461
462 async def run():
463 gen = foo()
464 it = gen.__aiter__()
465 await it.__anext__()
466 await gen.aclose()
467
468 with self.assertRaisesRegex(
469 RuntimeError,
470 "async generator ignored GeneratorExit"):
471 self.loop.run_until_complete(run())
472
473 def test_async_gen_asyncio_aclose_07(self):
474 DONE = 0
475
476 async def foo():
477 nonlocal DONE
478 try:
479 yield 1
480 1 / 0
481 finally:
482 await asyncio.sleep(0.01, loop=self.loop)
483 await asyncio.sleep(0.01, loop=self.loop)
484 DONE += 1
485 DONE += 1000
486
487 async def run():
488 gen = foo()
489 it = gen.__aiter__()
490 await it.__anext__()
491 await gen.aclose()
492
493 self.loop.run_until_complete(run())
494 self.assertEqual(DONE, 1)
495
496 def test_async_gen_asyncio_aclose_08(self):
497 DONE = 0
498
499 fut = asyncio.Future(loop=self.loop)
500
501 async def foo():
502 nonlocal DONE
503 try:
504 yield 1
505 await fut
506 DONE += 1000
507 yield 2
508 finally:
509 await asyncio.sleep(0.01, loop=self.loop)
510 await asyncio.sleep(0.01, loop=self.loop)
511 DONE += 1
512 DONE += 1000
513
514 async def run():
515 gen = foo()
516 it = gen.__aiter__()
517 self.assertEqual(await it.__anext__(), 1)
518 t = self.loop.create_task(it.__anext__())
519 await asyncio.sleep(0.01, loop=self.loop)
520 await gen.aclose()
521 return t
522
523 t = self.loop.run_until_complete(run())
524 self.assertEqual(DONE, 1)
525
526 # Silence ResourceWarnings
527 fut.cancel()
528 t.cancel()
529 self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop))
530
531 def test_async_gen_asyncio_gc_aclose_09(self):
532 DONE = 0
533
534 async def gen():
535 nonlocal DONE
536 try:
537 while True:
538 yield 1
539 finally:
540 await asyncio.sleep(0.01, loop=self.loop)
541 await asyncio.sleep(0.01, loop=self.loop)
542 DONE = 1
543
544 async def run():
545 g = gen()
546 await g.__anext__()
547 await g.__anext__()
548 del g
549
550 await asyncio.sleep(0.1, loop=self.loop)
551
552 self.loop.run_until_complete(run())
553 self.assertEqual(DONE, 1)
554
555 def test_async_gen_asyncio_asend_01(self):
556 DONE = 0
557
558 # Sanity check:
559 def sgen():
560 v = yield 1
561 yield v * 2
562 sg = sgen()
563 v = sg.send(None)
564 self.assertEqual(v, 1)
565 v = sg.send(100)
566 self.assertEqual(v, 200)
567
568 async def gen():
569 nonlocal DONE
570 try:
571 await asyncio.sleep(0.01, loop=self.loop)
572 v = yield 1
573 await asyncio.sleep(0.01, loop=self.loop)
574 yield v * 2
575 await asyncio.sleep(0.01, loop=self.loop)
576 return
577 finally:
578 await asyncio.sleep(0.01, loop=self.loop)
579 await asyncio.sleep(0.01, loop=self.loop)
580 DONE = 1
581
582 async def run():
583 g = gen()
584
585 v = await g.asend(None)
586 self.assertEqual(v, 1)
587
588 v = await g.asend(100)
589 self.assertEqual(v, 200)
590
591 with self.assertRaises(StopAsyncIteration):
592 await g.asend(None)
593
594 self.loop.run_until_complete(run())
595 self.assertEqual(DONE, 1)
596
597 def test_async_gen_asyncio_asend_02(self):
598 DONE = 0
599
600 async def sleep_n_crash(delay):
601 await asyncio.sleep(delay, loop=self.loop)
602 1 / 0
603
604 async def gen():
605 nonlocal DONE
606 try:
607 await asyncio.sleep(0.01, loop=self.loop)
608 v = yield 1
609 await sleep_n_crash(0.01)
610 DONE += 1000
611 yield v * 2
612 finally:
613 await asyncio.sleep(0.01, loop=self.loop)
614 await asyncio.sleep(0.01, loop=self.loop)
615 DONE = 1
616
617 async def run():
618 g = gen()
619
620 v = await g.asend(None)
621 self.assertEqual(v, 1)
622
623 await g.asend(100)
624
625 with self.assertRaises(ZeroDivisionError):
626 self.loop.run_until_complete(run())
627 self.assertEqual(DONE, 1)
628
629 def test_async_gen_asyncio_asend_03(self):
630 DONE = 0
631
632 async def sleep_n_crash(delay):
633 fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
634 loop=self.loop)
635 self.loop.call_later(delay / 2, lambda: fut.cancel())
636 return await fut
637
638 async def gen():
639 nonlocal DONE
640 try:
641 await asyncio.sleep(0.01, loop=self.loop)
642 v = yield 1
643 await sleep_n_crash(0.01)
644 DONE += 1000
645 yield v * 2
646 finally:
647 await asyncio.sleep(0.01, loop=self.loop)
648 await asyncio.sleep(0.01, loop=self.loop)
649 DONE = 1
650
651 async def run():
652 g = gen()
653
654 v = await g.asend(None)
655 self.assertEqual(v, 1)
656
657 await g.asend(100)
658
659 with self.assertRaises(asyncio.CancelledError):
660 self.loop.run_until_complete(run())
661 self.assertEqual(DONE, 1)
662
663 def test_async_gen_asyncio_athrow_01(self):
664 DONE = 0
665
666 class FooEr(Exception):
667 pass
668
669 # Sanity check:
670 def sgen():
671 try:
672 v = yield 1
673 except FooEr:
674 v = 1000
675 yield v * 2
676 sg = sgen()
677 v = sg.send(None)
678 self.assertEqual(v, 1)
679 v = sg.throw(FooEr)
680 self.assertEqual(v, 2000)
681 with self.assertRaises(StopIteration):
682 sg.send(None)
683
684 async def gen():
685 nonlocal DONE
686 try:
687 await asyncio.sleep(0.01, loop=self.loop)
688 try:
689 v = yield 1
690 except FooEr:
691 v = 1000
692 await asyncio.sleep(0.01, loop=self.loop)
693 yield v * 2
694 await asyncio.sleep(0.01, loop=self.loop)
695 # return
696 finally:
697 await asyncio.sleep(0.01, loop=self.loop)
698 await asyncio.sleep(0.01, loop=self.loop)
699 DONE = 1
700
701 async def run():
702 g = gen()
703
704 v = await g.asend(None)
705 self.assertEqual(v, 1)
706
707 v = await g.athrow(FooEr)
708 self.assertEqual(v, 2000)
709
710 with self.assertRaises(StopAsyncIteration):
711 await g.asend(None)
712
713 self.loop.run_until_complete(run())
714 self.assertEqual(DONE, 1)
715
716 def test_async_gen_asyncio_athrow_02(self):
717 DONE = 0
718
719 class FooEr(Exception):
720 pass
721
722 async def sleep_n_crash(delay):
723 fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
724 loop=self.loop)
725 self.loop.call_later(delay / 2, lambda: fut.cancel())
726 return await fut
727
728 async def gen():
729 nonlocal DONE
730 try:
731 await asyncio.sleep(0.01, loop=self.loop)
732 try:
733 v = yield 1
734 except FooEr:
735 await sleep_n_crash(0.01)
736 yield v * 2
737 await asyncio.sleep(0.01, loop=self.loop)
738 # return
739 finally:
740 await asyncio.sleep(0.01, loop=self.loop)
741 await asyncio.sleep(0.01, loop=self.loop)
742 DONE = 1
743
744 async def run():
745 g = gen()
746
747 v = await g.asend(None)
748 self.assertEqual(v, 1)
749
750 try:
751 await g.athrow(FooEr)
752 except asyncio.CancelledError:
753 self.assertEqual(DONE, 1)
754 raise
755 else:
756 self.fail('CancelledError was not raised')
757
758 with self.assertRaises(asyncio.CancelledError):
759 self.loop.run_until_complete(run())
760 self.assertEqual(DONE, 1)
761
762 def test_async_gen_asyncio_shutdown_01(self):
763 finalized = 0
764
765 async def waiter(timeout):
766 nonlocal finalized
767 try:
768 await asyncio.sleep(timeout, loop=self.loop)
769 yield 1
770 finally:
771 await asyncio.sleep(0, loop=self.loop)
772 finalized += 1
773
774 async def wait():
775 async for _ in waiter(1):
776 pass
777
778 t1 = self.loop.create_task(wait())
779 t2 = self.loop.create_task(wait())
780
781 self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
782
783 self.loop.run_until_complete(self.loop.shutdown_asyncgens())
784 self.assertEqual(finalized, 2)
785
786 # Silence warnings
787 t1.cancel()
788 t2.cancel()
789 self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
790
791 def test_async_gen_asyncio_shutdown_02(self):
792 logged = 0
793
794 def logger(loop, context):
795 nonlocal logged
796 self.assertIn('asyncgen', context)
797 expected = 'an error occurred during closing of asynchronous'
798 if expected in context['message']:
799 logged += 1
800
801 async def waiter(timeout):
802 try:
803 await asyncio.sleep(timeout, loop=self.loop)
804 yield 1
805 finally:
806 1 / 0
807
808 async def wait():
809 async for _ in waiter(1):
810 pass
811
812 t = self.loop.create_task(wait())
813 self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
814
815 self.loop.set_exception_handler(logger)
816 self.loop.run_until_complete(self.loop.shutdown_asyncgens())
817
818 self.assertEqual(logged, 1)
819
820 # Silence warnings
821 t.cancel()
822 self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
823
824if __name__ == "__main__":
825 unittest.main()