Files
Artemis-Eapil/tests/unit/drivers/test_native_cancellation.py

71 lines
2.5 KiB
Python

"""Cancellation drains input threads, while read-only work cannot hold the deadline."""
import asyncio
from threading import Event
from types import SimpleNamespace
import pytest
from artemis.drivers.android.adb_driver import AndroidAdbDriver
@pytest.mark.asyncio
@pytest.mark.parametrize("command", ["control_action", "touch_gesture", "inspect_control"])
async def test_cancel_keeps_input_owned_until_transport_finishes(command):
started, release, finished, cancel_seen = Event(), Event(), Event(), Event()
def request(name, args, *, timeout):
if name == "cancel_gesture":
cancel_seen.set()
return {"success": True, "execution": "observed", "code": "CANCEL_RECORDED"}
started.set()
try:
if not release.wait(2):
raise RuntimeError("test transport was not released")
return {"success": True, "execution": "completed", "code": "OK"}
finally:
finished.set()
driver = object.__new__(AndroidAdbDriver)
driver._ui_adb_client = SimpleNamespace(native_request=request)
operation = asyncio.create_task(driver.native_request(command, {"operation_id": "test-cancel"}))
try:
assert await asyncio.to_thread(started.wait, 1)
operation.cancel()
done, _ = await asyncio.wait({operation}, timeout=0.05)
if command == "inspect_control":
assert operation in done and not finished.is_set()
else:
assert operation not in done and not finished.is_set()
operation.cancel()
done, _ = await asyncio.wait({operation}, timeout=0.02)
assert not done
assert cancel_seen.is_set() == (command == "touch_gesture")
finally:
release.set()
with pytest.raises(asyncio.CancelledError):
await operation
assert await asyncio.to_thread(finished.wait, 1)
@pytest.mark.asyncio
async def test_cancelled_input_transport_failure_does_not_replace_cancellation():
started, release = Event(), Event()
def request(*args, **kwargs):
started.set()
release.wait(2)
raise OSError("response lost")
driver = object.__new__(AndroidAdbDriver)
driver._ui_adb_client = SimpleNamespace(native_request=request)
operation = asyncio.create_task(driver.native_request("control_action", {}))
try:
assert await asyncio.to_thread(started.wait, 1)
operation.cancel()
await asyncio.sleep(0)
finally:
release.set()
with pytest.raises(asyncio.CancelledError):
await operation