Skip to content

Commit 94fb0e3

Browse files
committed
Make simultaneous task test clearer
1 parent 32c5595 commit 94fb0e3

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

Lib/test/test_asyncgen.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,32 +1771,54 @@ 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

1777-
async def run():
1780+
1781+
async def run_collision(op, *args):
1782+
# Two tasks are created and scheduled. The first will sleep inside the
1783+
# `asend()` and the other will then attempt a second operation and fail.
1784+
17781785
async def consumer():
17791786
while True:
1787+
# task fa will sleep here, and another task will try to iterate
1788+
# the generator
17801789
await asyncio.sleep(0)
17811790
if (yield) is None:
17821791
break
17831792

1793+
# create and start the generator
1794+
agenerator = consumer()
1795+
await agenerator.asend(None)
1796+
1797+
# start the first asend() task
1798+
fa = asyncio.create_task(agenerator.asend("A"))
1799+
1800+
# start the second task, which should fail (asend, athrow, aclose)
1801+
method = getattr(agenerator, op)
1802+
fb = asyncio.create_task(method(*args))
1803+
1804+
# first asend should succeed
1805+
await fa
1806+
1807+
# second operation should fail
1808+
with self.assertRaises(RuntimeError) as err:
1809+
await fb
1810+
assert "already running" in str(err.exception)
1811+
1812+
# cleanup partially run generator
1813+
with self.assertRaises(StopAsyncIteration):
1814+
await agenerator.asend(None) # close it
1815+
1816+
async def run():
17841817
# try different combinations of asend, athrow, aclose
17851818
# which are clashing with an asend which is already running
17861819
# (and awaiting sleep(0))
17871820
for op, args in [("asend", ["A"]), ("athrow", [EOFError]), ("aclose", [])]:
1788-
agenerator = consumer()
1789-
await agenerator.asend(None) # start it
1790-
# fa will hit sleep and then fb will run
1791-
fa = asyncio.create_task(agenerator.asend("A"))
1792-
coro = getattr(agenerator, op)(*args)
1793-
fb = asyncio.create_task(coro)
1794-
await fa
1795-
with self.assertRaises(RuntimeError) as err:
1796-
await fb
1797-
assert "already running" in str(err.exception)
1798-
with self.assertRaises(StopAsyncIteration):
1799-
await agenerator.asend(None) # close it
1821+
await run_collision(op, *args)
18001822

18011823
self.loop.run_until_complete(run())
18021824

0 commit comments

Comments
 (0)