diff options
author | Damien George <damien@micropython.org> | 2024-06-19 15:04:12 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2024-06-20 00:11:54 +1000 |
commit | 13195a678d0155a52818beaa5ffc4f4678a4226d (patch) | |
tree | f06a9984f39d7701ff621cdc6c32516ca07c6a2a /tests/ports | |
parent | 8ac9c8f392000febb6ca58c470b653589dd7c710 (diff) | |
download | micropython-13195a678d0155a52818beaa5ffc4f4678a4226d.tar.gz micropython-13195a678d0155a52818beaa5ffc4f4678a4226d.zip |
webassembly/asyncio: Schedule run loop when tasks are pushed to queue.
In the webassembly port there is no asyncio run loop running at the top
level. Instead the Python asyncio run loop is scheduled through setTimeout
and run by the outer JavaScript event loop. Because tasks can become
runable from an external (to Python) event (eg a JavaScript callback), the
run loop must be scheduled whenever a task is pushed to the asyncio task
queue, otherwise tasks may be waiting forever on the queue.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'tests/ports')
-rw-r--r-- | tests/ports/webassembly/asyncio_top_level_await.mjs | 65 | ||||
-rw-r--r-- | tests/ports/webassembly/asyncio_top_level_await.mjs.exp | 12 |
2 files changed, 77 insertions, 0 deletions
diff --git a/tests/ports/webassembly/asyncio_top_level_await.mjs b/tests/ports/webassembly/asyncio_top_level_await.mjs index d8a9cad422..234b7a6ce6 100644 --- a/tests/ports/webassembly/asyncio_top_level_await.mjs +++ b/tests/ports/webassembly/asyncio_top_level_await.mjs @@ -2,6 +2,71 @@ const mp = await (await import(process.argv[2])).loadMicroPython(); +/**********************************************************/ +// Top-level await for an Event which is set by a JavaScript +// callback. + +console.log("= TEST 1 =========="); + +await mp.runPythonAsync(` +import asyncio +import js + +event = asyncio.Event() + +def callback(): + print("callback set event") + event.set() + +js.setTimeout(callback, 100) + +print("top-level wait event") +await event.wait() +print("top-level end") +`); + +console.log("finished"); + +/**********************************************************/ +// Top-level await for a Task which is cancelled by a +// JavaScript callback. + +console.log("= TEST 2 =========="); + +await mp.runPythonAsync(` +import asyncio +import js +import time + +async def task(): + print("task start") + await asyncio.sleep(5) + print("task end") + +def callback(): + print("callback cancel task") + t.cancel() + +t = asyncio.create_task(task()) +js.setTimeout(callback, 100) + +print("top-level wait task") +try: + t0 = time.time() + await t +except asyncio.CancelledError: + dt = time.time() - t0 + print("top-level task CancelledError", dt < 1) +`); + +console.log("finished"); + +/**********************************************************/ +// Top-level await for an Event and a Task, with the task +// setting the event. + +console.log("= TEST 3 =========="); + await mp.runPythonAsync(` import asyncio diff --git a/tests/ports/webassembly/asyncio_top_level_await.mjs.exp b/tests/ports/webassembly/asyncio_top_level_await.mjs.exp index 7232c5d4f0..66fefd2dce 100644 --- a/tests/ports/webassembly/asyncio_top_level_await.mjs.exp +++ b/tests/ports/webassembly/asyncio_top_level_await.mjs.exp @@ -1,3 +1,15 @@ += TEST 1 ========== +top-level wait event +callback set event +top-level end +finished += TEST 2 ========== +top-level wait task +task start +callback cancel task +top-level task CancelledError True +finished += TEST 3 ========== top-level wait event task set event task sleep |