71 lines
2.5 KiB
Python
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
|