summaryrefslogtreecommitdiffstatshomepage
path: root/tests/extmod/uasyncio_gather.py
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-03-29 12:57:04 +1100
committerDamien George <damien@micropython.org>2022-03-30 16:07:44 +1100
commit90aaf2dbef657e5afb8855a42d26093c3ef2a38d (patch)
treeaf6b356d6590a5d1f88d3cca3e670366be9598d3 /tests/extmod/uasyncio_gather.py
parent335002a4c020850591122d763324599e5edbe045 (diff)
downloadmicropython-90aaf2dbef657e5afb8855a42d26093c3ef2a38d.tar.gz
micropython-90aaf2dbef657e5afb8855a42d26093c3ef2a38d.zip
extmod/uasyncio: Fix gather cancelling and handling of exceptions.
The following fixes are made: - cancelling a gather now cancels all sub-tasks of the gather (previously it would only cancel the first) - if any sub-task of a gather raises an exception then the gather finishes (previously it would only finish if the first sub-task raised) Fixes issues #5798, #7807, #7901. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'tests/extmod/uasyncio_gather.py')
-rw-r--r--tests/extmod/uasyncio_gather.py63
1 files changed, 53 insertions, 10 deletions
diff --git a/tests/extmod/uasyncio_gather.py b/tests/extmod/uasyncio_gather.py
index 6053873dbc..718e702be6 100644
--- a/tests/extmod/uasyncio_gather.py
+++ b/tests/extmod/uasyncio_gather.py
@@ -27,9 +27,22 @@ async def task(id):
return id
-async def gather_task():
+async def task_loop(id):
+ print("task_loop start", id)
+ while True:
+ await asyncio.sleep(0.02)
+ print("task_loop loop", id)
+
+
+async def task_raise(id):
+ print("task_raise start", id)
+ await asyncio.sleep(0.02)
+ raise ValueError(id)
+
+
+async def gather_task(t0, t1):
print("gather_task")
- await asyncio.gather(task(1), task(2))
+ await asyncio.gather(t0, t1)
print("gather_task2")
@@ -37,19 +50,49 @@ async def main():
# Simple gather with return values
print(await asyncio.gather(factorial("A", 2), factorial("B", 3), factorial("C", 4)))
+ print("====")
+
# Test return_exceptions, where one task is cancelled and the other finishes normally
tasks = [asyncio.create_task(task(1)), asyncio.create_task(task(2))]
tasks[0].cancel()
print(await asyncio.gather(*tasks, return_exceptions=True))
- # Cancel a multi gather
- # TODO doesn't work, Task should not forward cancellation from gather to sub-task
- # but rather CancelledError should cancel the gather directly, which will then cancel
- # all sub-tasks explicitly
- # t = asyncio.create_task(gather_task())
- # await asyncio.sleep(0.01)
- # t.cancel()
- # await asyncio.sleep(0.01)
+ print("====")
+
+ # Test return_exceptions, where one task raises an exception and the other finishes normally.
+ tasks = [asyncio.create_task(task(1)), asyncio.create_task(task_raise(2))]
+ print(await asyncio.gather(*tasks, return_exceptions=True))
+
+ print("====")
+
+ # Test case where one task raises an exception and other task keeps running.
+ tasks = [asyncio.create_task(task_loop(1)), asyncio.create_task(task_raise(2))]
+ try:
+ await asyncio.gather(*tasks)
+ except ValueError as er:
+ print(repr(er))
+ print(tasks[0].done(), tasks[1].done())
+ for t in tasks:
+ t.cancel()
+ await asyncio.sleep(0.04)
+
+ print("====")
+
+ # Test case where both tasks raise an exception.
+ tasks = [asyncio.create_task(task_raise(1)), asyncio.create_task(task_raise(2))]
+ try:
+ await asyncio.gather(*tasks)
+ except ValueError as er:
+ print(repr(er))
+ print(tasks[0].done(), tasks[1].done())
+
+ print("====")
+
+ # Cancel a multi gather.
+ t = asyncio.create_task(gather_task(task(1), task(2)))
+ await asyncio.sleep(0.01)
+ t.cancel()
+ await asyncio.sleep(0.04)
asyncio.run(main())