@@ -1771,33 +1771,55 @@ def tearDown(self):
17711771 def test_simultaneous_asend (self ):
17721772 """
17731773 Verify that simultaneous use of generator by different coroutines is not
1774- permitted
1774+ permitted. We use Tasks to achieve this, where one task is suspended
1775+ in a `asyncio.sleep()` call inside the generator (during an `asend()` call),
1776+ and the other task attempts
1777+ to do an `asend()`, (or `athrow()`, or `aclose()`) on the generator.
17751778 """
17761779
17771780 async def run ():
1778- async def consumer ():
1779- while True :
1780- await asyncio .sleep (0 )
1781- if (yield ) is None :
1782- break
17831781
1784- # try different combinations of asend, athrow, aclose
1785- # which are clashing with an asend which is already running
1786- # (and awaiting sleep(0))
1787- for op , args in [("asend" , ["A" ]), ("athrow" , [EOFError ]), ("aclose" , [])]:
1782+ async def run_collision (op , * args ):
1783+ # Two tasks are created and scheduled. The first will sleep inside the
1784+ # `asend()` and the other will then attempt a second operation and fail.
1785+
1786+ async def consumer ():
1787+ while True :
1788+ # task fa will sleep here, and another task will try to iterate
1789+ # the generator
1790+ await asyncio .sleep (0 )
1791+ if (yield ) is None :
1792+ break
1793+
1794+ # create and start the generator
17881795 agenerator = consumer ()
1789- await agenerator .asend (None ) # start it
1790- # fa will hit sleep and then fb will run
1796+ await agenerator .asend (None )
1797+
1798+ # start the first asend() task
17911799 fa = asyncio .create_task (agenerator .asend ("A" ))
1792- coro = getattr (agenerator , op )(* args )
1793- fb = asyncio .create_task (coro )
1800+
1801+ # start the second task, which should fail (asend, athrow, aclose)
1802+ method = getattr (agenerator , op )
1803+ fb = asyncio .create_task (method (* args ))
1804+
1805+ # first asend should succeed
17941806 await fa
1807+
1808+ # second operation should fail
17951809 with self .assertRaises (RuntimeError ) as err :
17961810 await fb
17971811 assert "already running" in str (err .exception )
1812+
1813+ # cleanup partially run generator
17981814 with self .assertRaises (StopAsyncIteration ):
17991815 await agenerator .asend (None ) # close it
18001816
1817+ # try different combinations of asend, athrow, aclose
1818+ # which are clashing with an asend which is already running
1819+ # (and awaiting sleep(0))
1820+ for op , args in [("asend" , ["A" ]), ("athrow" , [EOFError ]), ("aclose" , [])]:
1821+ await run_collision (op , * args )
1822+
18011823 self .loop .run_until_complete (run ())
18021824
18031825 def test_ag_running (self ):
0 commit comments