summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorThomas Grainger <tagrain@gmail.com>2024-10-11 23:31:06 (GMT)
committerGitHub <noreply@github.com>2024-10-11 23:31:06 (GMT)
commit979c0df7c0adfb744159a5fc184043dc733d8534 (patch)
tree875a18ebd7943a572fa076bdf2794d17b3e0dfc0 /Lib/test
parent21ac0a7f4cf6d11da728b33ed5e8cfa65a5a8ae7 (diff)
downloadcpython-979c0df7c0adfb744159a5fc184043dc733d8534.zip
cpython-979c0df7c0adfb744159a5fc184043dc733d8534.tar.gz
cpython-979c0df7c0adfb744159a5fc184043dc733d8534.tar.bz2
gh-124309: fix staggered race on eager tasks (#124847)
This patch is entirely by Thomas and Peter Co-authored-by: Thomas Grainger <tagrain@gmail.com> Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_asyncio/test_eager_task_factory.py46
-rw-r--r--Lib/test/test_asyncio/test_staggered.py27
2 files changed, 73 insertions, 0 deletions
diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py
index 0777f39..31d2a00 100644
--- a/Lib/test/test_asyncio/test_eager_task_factory.py
+++ b/Lib/test/test_asyncio/test_eager_task_factory.py
@@ -213,6 +213,52 @@ class EagerTaskFactoryLoopTests:
self.run_coro(run())
+ def test_staggered_race_with_eager_tasks(self):
+ # See https://github.com/python/cpython/issues/124309
+
+ async def fail():
+ await asyncio.sleep(0)
+ raise ValueError("no good")
+
+ async def run():
+ winner, index, excs = await asyncio.staggered.staggered_race(
+ [
+ lambda: asyncio.sleep(2, result="sleep2"),
+ lambda: asyncio.sleep(1, result="sleep1"),
+ lambda: fail()
+ ],
+ delay=0.25
+ )
+ self.assertEqual(winner, 'sleep1')
+ self.assertEqual(index, 1)
+ self.assertIsNone(excs[index])
+ self.assertIsInstance(excs[0], asyncio.CancelledError)
+ self.assertIsInstance(excs[2], ValueError)
+
+ self.run_coro(run())
+
+ def test_staggered_race_with_eager_tasks_no_delay(self):
+ # See https://github.com/python/cpython/issues/124309
+ async def fail():
+ raise ValueError("no good")
+
+ async def run():
+ winner, index, excs = await asyncio.staggered.staggered_race(
+ [
+ lambda: fail(),
+ lambda: asyncio.sleep(1, result="sleep1"),
+ lambda: asyncio.sleep(0, result="sleep0"),
+ ],
+ delay=None
+ )
+ self.assertEqual(winner, 'sleep1')
+ self.assertEqual(index, 1)
+ self.assertIsNone(excs[index])
+ self.assertIsInstance(excs[0], ValueError)
+ self.assertEqual(len(excs), 2)
+
+ self.run_coro(run())
+
class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase):
Task = tasks._PyTask
diff --git a/Lib/test/test_asyncio/test_staggered.py b/Lib/test/test_asyncio/test_staggered.py
index e6e32f7..74941f7 100644
--- a/Lib/test/test_asyncio/test_staggered.py
+++ b/Lib/test/test_asyncio/test_staggered.py
@@ -95,3 +95,30 @@ class StaggeredTests(unittest.IsolatedAsyncioTestCase):
self.assertEqual(len(excs), 2)
self.assertIsInstance(excs[0], ValueError)
self.assertIsInstance(excs[1], ValueError)
+
+
+ async def test_multiple_winners(self):
+ event = asyncio.Event()
+
+ async def coro(index):
+ await event.wait()
+ return index
+
+ async def do_set():
+ event.set()
+ await asyncio.Event().wait()
+
+ winner, index, excs = await staggered_race(
+ [
+ lambda: coro(0),
+ lambda: coro(1),
+ do_set,
+ ],
+ delay=0.1,
+ )
+ self.assertIs(winner, 0)
+ self.assertIs(index, 0)
+ self.assertEqual(len(excs), 3)
+ self.assertIsNone(excs[0], None)
+ self.assertIsInstance(excs[1], asyncio.CancelledError)
+ self.assertIsInstance(excs[2], asyncio.CancelledError)