diff options
author | Damien George <damien@micropython.org> | 2022-03-29 12:57:04 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2022-03-30 16:07:44 +1100 |
commit | 90aaf2dbef657e5afb8855a42d26093c3ef2a38d (patch) | |
tree | af6b356d6590a5d1f88d3cca3e670366be9598d3 /tests/extmod/uasyncio_gather.py | |
parent | 335002a4c020850591122d763324599e5edbe045 (diff) | |
download | micropython-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.py | 63 |
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()) |