1import inspect
2import sys
3import types
4import unittest
5
6from unittest import mock
7
8from test.support import import_module
9asyncio = import_module("asyncio")
10
11
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_anext_06(self):
454        DONE = 0
455
456        # test synchronous generators
457        def foo():
458            try:
459                yield
460            except:
461                pass
462        g = foo()
463        g.send(None)
464        with self.assertRaises(StopIteration):
465            g.send(None)
466
467        # now with asynchronous generators
468
469        async def gen():
470            nonlocal DONE
471            try:
472                yield
473            except:
474                pass
475            DONE = 1
476
477        async def run():
478            nonlocal DONE
479            g = gen()
480            await g.asend(None)
481            with self.assertRaises(StopAsyncIteration):
482                await g.asend(None)
483            DONE += 10
484
485        self.loop.run_until_complete(run())
486        self.assertEqual(DONE, 11)
487
488    def test_async_gen_asyncio_anext_tuple(self):
489        async def foo():
490            try:
491                yield (1,)
492            except ZeroDivisionError:
493                yield (2,)
494
495        async def run():
496            it = foo().__aiter__()
497
498            self.assertEqual(await it.__anext__(), (1,))
499            with self.assertRaises(StopIteration) as cm:
500                it.__anext__().throw(ZeroDivisionError)
501            self.assertEqual(cm.exception.args[0], (2,))
502            with self.assertRaises(StopAsyncIteration):
503                await it.__anext__()
504
505        self.loop.run_until_complete(run())
506
507    def test_async_gen_asyncio_anext_stopiteration(self):
508        async def foo():
509            try:
510                yield StopIteration(1)
511            except ZeroDivisionError:
512                yield StopIteration(3)
513
514        async def run():
515            it = foo().__aiter__()
516
517            v = await it.__anext__()
518            self.assertIsInstance(v, StopIteration)
519            self.assertEqual(v.value, 1)
520            with self.assertRaises(StopIteration) as cm:
521                it.__anext__().throw(ZeroDivisionError)
522            v = cm.exception.args[0]
523            self.assertIsInstance(v, StopIteration)
524            self.assertEqual(v.value, 3)
525            with self.assertRaises(StopAsyncIteration):
526                await it.__anext__()
527
528        self.loop.run_until_complete(run())
529
530    def test_async_gen_asyncio_aclose_06(self):
531        async def foo():
532            try:
533                yield 1
534                1 / 0
535            finally:
536                await asyncio.sleep(0.01, loop=self.loop)
537                yield 12
538
539        async def run():
540            gen = foo()
541            it = gen.__aiter__()
542            await it.__anext__()
543            await gen.aclose()
544
545        with self.assertRaisesRegex(
546                RuntimeError,
547                "async generator ignored GeneratorExit"):
548            self.loop.run_until_complete(run())
549
550    def test_async_gen_asyncio_aclose_07(self):
551        DONE = 0
552
553        async def foo():
554            nonlocal DONE
555            try:
556                yield 1
557                1 / 0
558            finally:
559                await asyncio.sleep(0.01, loop=self.loop)
560                await asyncio.sleep(0.01, loop=self.loop)
561                DONE += 1
562            DONE += 1000
563
564        async def run():
565            gen = foo()
566            it = gen.__aiter__()
567            await it.__anext__()
568            await gen.aclose()
569
570        self.loop.run_until_complete(run())
571        self.assertEqual(DONE, 1)
572
573    def test_async_gen_asyncio_aclose_08(self):
574        DONE = 0
575
576        fut = asyncio.Future(loop=self.loop)
577
578        async def foo():
579            nonlocal DONE
580            try:
581                yield 1
582                await fut
583                DONE += 1000
584                yield 2
585            finally:
586                await asyncio.sleep(0.01, loop=self.loop)
587                await asyncio.sleep(0.01, loop=self.loop)
588                DONE += 1
589            DONE += 1000
590
591        async def run():
592            gen = foo()
593            it = gen.__aiter__()
594            self.assertEqual(await it.__anext__(), 1)
595            t = self.loop.create_task(it.__anext__())
596            await asyncio.sleep(0.01, loop=self.loop)
597            await gen.aclose()
598            return t
599
600        t = self.loop.run_until_complete(run())
601        self.assertEqual(DONE, 1)
602
603        # Silence ResourceWarnings
604        fut.cancel()
605        t.cancel()
606        self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop))
607
608    def test_async_gen_asyncio_gc_aclose_09(self):
609        DONE = 0
610
611        async def gen():
612            nonlocal DONE
613            try:
614                while True:
615                    yield 1
616            finally:
617                await asyncio.sleep(0.01, loop=self.loop)
618                await asyncio.sleep(0.01, loop=self.loop)
619                DONE = 1
620
621        async def run():
622            g = gen()
623            await g.__anext__()
624            await g.__anext__()
625            del g
626
627            await asyncio.sleep(0.1, loop=self.loop)
628
629        self.loop.run_until_complete(run())
630        self.assertEqual(DONE, 1)
631
632    def test_async_gen_asyncio_aclose_10(self):
633        DONE = 0
634
635        # test synchronous generators
636        def foo():
637            try:
638                yield
639            except:
640                pass
641        g = foo()
642        g.send(None)
643        g.close()
644
645        # now with asynchronous generators
646
647        async def gen():
648            nonlocal DONE
649            try:
650                yield
651            except:
652                pass
653            DONE = 1
654
655        async def run():
656            nonlocal DONE
657            g = gen()
658            await g.asend(None)
659            await g.aclose()
660            DONE += 10
661
662        self.loop.run_until_complete(run())
663        self.assertEqual(DONE, 11)
664
665    def test_async_gen_asyncio_aclose_11(self):
666        DONE = 0
667
668        # test synchronous generators
669        def foo():
670            try:
671                yield
672            except:
673                pass
674            yield
675        g = foo()
676        g.send(None)
677        with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
678            g.close()
679
680        # now with asynchronous generators
681
682        async def gen():
683            nonlocal DONE
684            try:
685                yield
686            except:
687                pass
688            yield
689            DONE += 1
690
691        async def run():
692            nonlocal DONE
693            g = gen()
694            await g.asend(None)
695            with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
696                await g.aclose()
697            DONE += 10
698
699        self.loop.run_until_complete(run())
700        self.assertEqual(DONE, 10)
701
702    def test_async_gen_asyncio_asend_01(self):
703        DONE = 0
704
705        # Sanity check:
706        def sgen():
707            v = yield 1
708            yield v * 2
709        sg = sgen()
710        v = sg.send(None)
711        self.assertEqual(v, 1)
712        v = sg.send(100)
713        self.assertEqual(v, 200)
714
715        async def gen():
716            nonlocal DONE
717            try:
718                await asyncio.sleep(0.01, loop=self.loop)
719                v = yield 1
720                await asyncio.sleep(0.01, loop=self.loop)
721                yield v * 2
722                await asyncio.sleep(0.01, loop=self.loop)
723                return
724            finally:
725                await asyncio.sleep(0.01, loop=self.loop)
726                await asyncio.sleep(0.01, loop=self.loop)
727                DONE = 1
728
729        async def run():
730            g = gen()
731
732            v = await g.asend(None)
733            self.assertEqual(v, 1)
734
735            v = await g.asend(100)
736            self.assertEqual(v, 200)
737
738            with self.assertRaises(StopAsyncIteration):
739                await g.asend(None)
740
741        self.loop.run_until_complete(run())
742        self.assertEqual(DONE, 1)
743
744    def test_async_gen_asyncio_asend_02(self):
745        DONE = 0
746
747        async def sleep_n_crash(delay):
748            await asyncio.sleep(delay, loop=self.loop)
749            1 / 0
750
751        async def gen():
752            nonlocal DONE
753            try:
754                await asyncio.sleep(0.01, loop=self.loop)
755                v = yield 1
756                await sleep_n_crash(0.01)
757                DONE += 1000
758                yield v * 2
759            finally:
760                await asyncio.sleep(0.01, loop=self.loop)
761                await asyncio.sleep(0.01, loop=self.loop)
762                DONE = 1
763
764        async def run():
765            g = gen()
766
767            v = await g.asend(None)
768            self.assertEqual(v, 1)
769
770            await g.asend(100)
771
772        with self.assertRaises(ZeroDivisionError):
773            self.loop.run_until_complete(run())
774        self.assertEqual(DONE, 1)
775
776    def test_async_gen_asyncio_asend_03(self):
777        DONE = 0
778
779        async def sleep_n_crash(delay):
780            fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
781                                        loop=self.loop)
782            self.loop.call_later(delay / 2, lambda: fut.cancel())
783            return await fut
784
785        async def gen():
786            nonlocal DONE
787            try:
788                await asyncio.sleep(0.01, loop=self.loop)
789                v = yield 1
790                await sleep_n_crash(0.01)
791                DONE += 1000
792                yield v * 2
793            finally:
794                await asyncio.sleep(0.01, loop=self.loop)
795                await asyncio.sleep(0.01, loop=self.loop)
796                DONE = 1
797
798        async def run():
799            g = gen()
800
801            v = await g.asend(None)
802            self.assertEqual(v, 1)
803
804            await g.asend(100)
805
806        with self.assertRaises(asyncio.CancelledError):
807            self.loop.run_until_complete(run())
808        self.assertEqual(DONE, 1)
809
810    def test_async_gen_asyncio_athrow_01(self):
811        DONE = 0
812
813        class FooEr(Exception):
814            pass
815
816        # Sanity check:
817        def sgen():
818            try:
819                v = yield 1
820            except FooEr:
821                v = 1000
822            yield v * 2
823        sg = sgen()
824        v = sg.send(None)
825        self.assertEqual(v, 1)
826        v = sg.throw(FooEr)
827        self.assertEqual(v, 2000)
828        with self.assertRaises(StopIteration):
829            sg.send(None)
830
831        async def gen():
832            nonlocal DONE
833            try:
834                await asyncio.sleep(0.01, loop=self.loop)
835                try:
836                    v = yield 1
837                except FooEr:
838                    v = 1000
839                    await asyncio.sleep(0.01, loop=self.loop)
840                yield v * 2
841                await asyncio.sleep(0.01, loop=self.loop)
842                # return
843            finally:
844                await asyncio.sleep(0.01, loop=self.loop)
845                await asyncio.sleep(0.01, loop=self.loop)
846                DONE = 1
847
848        async def run():
849            g = gen()
850
851            v = await g.asend(None)
852            self.assertEqual(v, 1)
853
854            v = await g.athrow(FooEr)
855            self.assertEqual(v, 2000)
856
857            with self.assertRaises(StopAsyncIteration):
858                await g.asend(None)
859
860        self.loop.run_until_complete(run())
861        self.assertEqual(DONE, 1)
862
863    def test_async_gen_asyncio_athrow_02(self):
864        DONE = 0
865
866        class FooEr(Exception):
867            pass
868
869        async def sleep_n_crash(delay):
870            fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
871                                        loop=self.loop)
872            self.loop.call_later(delay / 2, lambda: fut.cancel())
873            return await fut
874
875        async def gen():
876            nonlocal DONE
877            try:
878                await asyncio.sleep(0.01, loop=self.loop)
879                try:
880                    v = yield 1
881                except FooEr:
882                    await sleep_n_crash(0.01)
883                yield v * 2
884                await asyncio.sleep(0.01, loop=self.loop)
885                # return
886            finally:
887                await asyncio.sleep(0.01, loop=self.loop)
888                await asyncio.sleep(0.01, loop=self.loop)
889                DONE = 1
890
891        async def run():
892            g = gen()
893
894            v = await g.asend(None)
895            self.assertEqual(v, 1)
896
897            try:
898                await g.athrow(FooEr)
899            except asyncio.CancelledError:
900                self.assertEqual(DONE, 1)
901                raise
902            else:
903                self.fail('CancelledError was not raised')
904
905        with self.assertRaises(asyncio.CancelledError):
906            self.loop.run_until_complete(run())
907        self.assertEqual(DONE, 1)
908
909    def test_async_gen_asyncio_athrow_03(self):
910        DONE = 0
911
912        # test synchronous generators
913        def foo():
914            try:
915                yield
916            except:
917                pass
918        g = foo()
919        g.send(None)
920        with self.assertRaises(StopIteration):
921            g.throw(ValueError)
922
923        # now with asynchronous generators
924
925        async def gen():
926            nonlocal DONE
927            try:
928                yield
929            except:
930                pass
931            DONE = 1
932
933        async def run():
934            nonlocal DONE
935            g = gen()
936            await g.asend(None)
937            with self.assertRaises(StopAsyncIteration):
938                await g.athrow(ValueError)
939            DONE += 10
940
941        self.loop.run_until_complete(run())
942        self.assertEqual(DONE, 11)
943
944    def test_async_gen_asyncio_athrow_tuple(self):
945        async def gen():
946            try:
947                yield 1
948            except ZeroDivisionError:
949                yield (2,)
950
951        async def run():
952            g = gen()
953            v = await g.asend(None)
954            self.assertEqual(v, 1)
955            v = await g.athrow(ZeroDivisionError)
956            self.assertEqual(v, (2,))
957            with self.assertRaises(StopAsyncIteration):
958                await g.asend(None)
959
960        self.loop.run_until_complete(run())
961
962    def test_async_gen_asyncio_athrow_stopiteration(self):
963        async def gen():
964            try:
965                yield 1
966            except ZeroDivisionError:
967                yield StopIteration(2)
968
969        async def run():
970            g = gen()
971            v = await g.asend(None)
972            self.assertEqual(v, 1)
973            v = await g.athrow(ZeroDivisionError)
974            self.assertIsInstance(v, StopIteration)
975            self.assertEqual(v.value, 2)
976            with self.assertRaises(StopAsyncIteration):
977                await g.asend(None)
978
979        self.loop.run_until_complete(run())
980
981    def test_async_gen_asyncio_shutdown_01(self):
982        finalized = 0
983
984        async def waiter(timeout):
985            nonlocal finalized
986            try:
987                await asyncio.sleep(timeout, loop=self.loop)
988                yield 1
989            finally:
990                await asyncio.sleep(0, loop=self.loop)
991                finalized += 1
992
993        async def wait():
994            async for _ in waiter(1):
995                pass
996
997        t1 = self.loop.create_task(wait())
998        t2 = self.loop.create_task(wait())
999
1000        self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
1001
1002        self.loop.run_until_complete(self.loop.shutdown_asyncgens())
1003        self.assertEqual(finalized, 2)
1004
1005        # Silence warnings
1006        t1.cancel()
1007        t2.cancel()
1008        self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
1009
1010    def test_async_gen_asyncio_shutdown_02(self):
1011        logged = 0
1012
1013        def logger(loop, context):
1014            nonlocal logged
1015            self.assertIn('asyncgen', context)
1016            expected = 'an error occurred during closing of asynchronous'
1017            if expected in context['message']:
1018                logged += 1
1019
1020        async def waiter(timeout):
1021            try:
1022                await asyncio.sleep(timeout, loop=self.loop)
1023                yield 1
1024            finally:
1025                1 / 0
1026
1027        async def wait():
1028            async for _ in waiter(1):
1029                pass
1030
1031        t = self.loop.create_task(wait())
1032        self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
1033
1034        self.loop.set_exception_handler(logger)
1035        self.loop.run_until_complete(self.loop.shutdown_asyncgens())
1036
1037        self.assertEqual(logged, 1)
1038
1039        # Silence warnings
1040        t.cancel()
1041        self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
1042
1043if __name__ == "__main__":
1044    unittest.main()
1045