fix: bound task failures and release stalled workers

This commit is contained in:
chenmingxuan committed 2026-10-08 16:10:10 +08:00
1 parent 606ed94160
commit 1fdf7c0d1d
32 files changed
+1121 -93

No files matched your search

+50 -6
View File
@@ -14,7 +14,9 @@
"""Unit tests for Unified Base Device Driver and implementations."""
import asyncio
import base64
import threading
from io import BytesIO
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock
@@ -36,6 +38,48 @@ _ONE_PIXEL_PNG = base64.b64encode(
).decode("ascii")
def _valid_png():
buffer = BytesIO()
Image.new("RGB", (64, 64), "white").save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode("ascii")
_VALID_PNG = _valid_png()
@pytest.mark.asyncio
async def test_android_driver_rejects_placeholder_without_returning_stale_screen():
client = MagicMock()
client.get_screen_data.return_value = SimpleNamespace(base64=_ONE_PIXEL_PNG)
driver = AndroidAdbDriver("test-device", MagicMock(), ui_adb_client=client)
with pytest.raises(RuntimeError, match="占位图"):
await driver.get_screen_data(skip_settling=True)
@pytest.mark.asyncio
async def test_screen_capture_timeout_does_not_start_overlapping_sdk_calls(monkeypatch):
released = threading.Event()
client = MagicMock()
def blocked_capture():
released.wait(2)
return SimpleNamespace(base64=_VALID_PNG, width=64, height=64, elements=[])
client.get_screen_data.side_effect = blocked_capture
driver = AndroidAdbDriver("test-device", MagicMock(), ui_adb_client=client)
monkeypatch.setattr(
"artemis.drivers.android.adb_driver.settings.ARTEMIS_OBSERVATION_TIMEOUT_SECONDS", 0.02
)
try:
for _ in range(3):
with pytest.raises(TimeoutError, match="观测超时"):
await driver.get_screen_data(skip_settling=True)
assert client.get_screen_data.call_count == 1
finally:
released.set()
await asyncio.wait_for(driver._screen_capture_task, 2)
def test_screenshot_limit_keeps_small_and_invalid_images_unchanged():
small_image = base64.b64decode(_ONE_PIXEL_PNG)
assert limit_screenshot_long_edge(small_image, 2048) is small_image
@@ -100,16 +144,16 @@ async def test_android_driver_with_mock_adb():
# Test tap
await driver.tap(540, 1200)
mock_adb_device.shell.assert_called_with("input tap 540 1200")
mock_adb_device.shell.assert_called_with("input tap 540 1200", timeout=10.0)
# Test multi-tap
await driver.tap(540, 1200, times=3, delay_ms=100)
expected_multi = "input tap 540 1200 && sleep 0.100 && input tap 540 1200 && sleep 0.100 && input tap 540 1200"
mock_adb_device.shell.assert_called_with(expected_multi)
mock_adb_device.shell.assert_called_with(expected_multi, timeout=10.0)
# Test press key
await driver.press_key(KeyCode.BACK)
mock_adb_device.shell.assert_called_with("input keyevent 4")
mock_adb_device.shell.assert_called_with("input keyevent 4", timeout=10.0)
@pytest.mark.asyncio
@@ -132,7 +176,7 @@ async def test_android_driver_preserves_elements_from_combined_screen_data():
},
]
mock_ui_client.get_screen_data.return_value = SimpleNamespace(
base64=_ONE_PIXEL_PNG,
base64=_VALID_PNG,
hierarchy_xml="<hierarchy />",
elements=expected_elements,
width=1080,
@@ -188,7 +232,7 @@ async def test_android_driver_parses_xml_hierarchy_fallback():
mock_adb_client = MagicMock()
mock_ui_client = MagicMock()
mock_ui_client.get_screen_data.return_value = SimpleNamespace(
base64=_ONE_PIXEL_PNG,
base64=_VALID_PNG,
width=1080,
height=2400,
)
@@ -216,7 +260,7 @@ async def test_find_element_prefers_fresh_bounds_over_stale_center():
driver.get_screen_data = AsyncMock(
return_value=ScreenData(
screenshot_bytes=base64.b64decode(_ONE_PIXEL_PNG),
screenshot_base64=_ONE_PIXEL_PNG,
screenshot_base64=_VALID_PNG,
ui_elements=[
{
"resource_id": "app:id/digit_4",