refactor(device): remove single-device state and test branches
This commit is contained in:
1 parent
cbe8f4f0c6
commit
33c4a0d112
12 files changed
+175
-88
No files matched your search
@@ -78,8 +78,8 @@ async def test_run_task_enqueues_when_device_is_unlocked(monkeypatch):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_task_switches_to_unlocked_device_and_syncs_engine(monkeypatch):
|
||||
"""When default device is locked, run_task should enqueue on verified fallback and update engine."""
|
||||
async def test_run_task_binds_probe_verified_device_when_no_serial_requested(monkeypatch):
|
||||
"""Without an explicit serial, run_task enqueues on the probe-verified live device."""
|
||||
unlocked_probe = ProbeResult(
|
||||
id="android_adb",
|
||||
category=ProbeCategory.DEVICE,
|
||||
@@ -100,9 +100,6 @@ async def test_run_task_switches_to_unlocked_device_and_syncs_engine(monkeypatch
|
||||
tasks.readiness_engine, "run_device_submission_probe", run_probe
|
||||
)
|
||||
monkeypatch.setattr(tasks.task_queue_service, "enqueue_tasks", enqueue_tasks)
|
||||
monkeypatch.setattr(tasks.readiness_engine, "get_active_device_serial", lambda: "device-locked-1")
|
||||
set_active_mock = AsyncMock()
|
||||
monkeypatch.setattr(tasks.readiness_engine, "set_active_device_serial", set_active_mock)
|
||||
|
||||
result = await tasks.run_task(RunRequest(goal="Run on any ready device"))
|
||||
|
||||
@@ -111,7 +108,6 @@ async def test_run_task_switches_to_unlocked_device_and_syncs_engine(monkeypatch
|
||||
# Check that device_serial passed to enqueue_tasks is the verified unlocked device
|
||||
_, kwargs = enqueue_tasks.call_args
|
||||
assert kwargs.get("device_serial") == "emulator-5556"
|
||||
set_active_mock.assert_called_once_with("emulator-5556")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -222,10 +222,6 @@ async def test_queue_worker_execution_lifecycle():
|
||||
patch("asyncio.create_subprocess_exec", side_effect=fake_subprocess_exec),
|
||||
patch("apps.admin_console.services.task_queue_service.session_repo") as mock_repo,
|
||||
patch("apps.admin_console.services.task_queue_service.media_service"),
|
||||
patch(
|
||||
"artemis.core.diagnostics.readiness_engine.get_active_device_serial",
|
||||
return_value=None,
|
||||
),
|
||||
patch(
|
||||
"artemis.runtime.device_pool.device_pool.select_device",
|
||||
return_value="emulator-5554",
|
||||
@@ -272,10 +268,6 @@ async def test_queue_worker_cmd_construction():
|
||||
patch("asyncio.create_subprocess_exec", side_effect=fake_subprocess_exec),
|
||||
patch("apps.admin_console.services.task_queue_service.session_repo") as mock_repo,
|
||||
patch("apps.admin_console.services.task_queue_service.media_service"),
|
||||
patch(
|
||||
"artemis.core.diagnostics.readiness_engine.get_active_device_serial",
|
||||
return_value=None,
|
||||
),
|
||||
patch(
|
||||
"artemis.runtime.device_pool.device_pool.select_device",
|
||||
return_value="emulator-5554",
|
||||
@@ -489,6 +481,48 @@ def test_stop_tasks_does_not_kill_stale_reused_pid():
|
||||
terminate_verified.assert_not_called()
|
||||
|
||||
|
||||
def test_stop_tasks_session_target_never_adopts_mismatched_fallback_owner():
|
||||
"""No live owners is a legal state: a session-targeted stop must not
|
||||
terminate a fallback owner that belongs to a different session."""
|
||||
other_owner = DeviceLockOwner(
|
||||
pid=24680,
|
||||
process_created_at=1234.5,
|
||||
token="other-owner-token",
|
||||
device_id="emulator-5554",
|
||||
description="Task for another session",
|
||||
acquired_at="2026-08-24T00:00:00+00:00",
|
||||
session_id="other-session",
|
||||
ingress="cli",
|
||||
)
|
||||
with (
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.DeviceExecutionLock.get_active_owners",
|
||||
return_value={},
|
||||
),
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.DeviceExecutionLock.get_active_owner",
|
||||
return_value=other_owner,
|
||||
),
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.DeviceExecutionLock.is_active_owner",
|
||||
return_value=True,
|
||||
),
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.process_supervisor.terminate_tree_verified"
|
||||
) as terminate_verified,
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.session_repo.update_session_status"
|
||||
),
|
||||
patch(
|
||||
"apps.admin_console.services.task_queue_service.session_repo.get_session_by_id",
|
||||
return_value=None,
|
||||
),
|
||||
):
|
||||
task_queue_service.stop_tasks(clear_all=False, session_id="wanted-session")
|
||||
|
||||
terminate_verified.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_status_reports_external_global_owner_without_ipc_connection():
|
||||
external_owner = DeviceLockOwner(
|
||||
@@ -548,10 +582,6 @@ async def test_cancel_task_triggers_next_pending_task():
|
||||
patch("asyncio.create_subprocess_exec", side_effect=fake_subprocess_exec),
|
||||
patch("apps.admin_console.services.task_queue_service.session_repo") as mock_repo,
|
||||
patch("apps.admin_console.services.task_queue_service.media_service"),
|
||||
patch(
|
||||
"artemis.core.diagnostics.readiness_engine.get_active_device_serial",
|
||||
return_value=None,
|
||||
),
|
||||
patch(
|
||||
"artemis.runtime.device_pool.device_pool.select_device",
|
||||
return_value="emulator-5554",
|
||||
@@ -603,10 +633,6 @@ async def test_immediate_cancel_ignores_stale_ipc_and_runs_next_task():
|
||||
patch("asyncio.create_subprocess_exec", side_effect=fake_subprocess_exec),
|
||||
patch("apps.admin_console.services.task_queue_service.session_repo") as mock_repo,
|
||||
patch("apps.admin_console.services.task_queue_service.media_service"),
|
||||
patch(
|
||||
"artemis.core.diagnostics.readiness_engine.get_active_device_serial",
|
||||
return_value=None,
|
||||
),
|
||||
patch(
|
||||
"artemis.runtime.device_pool.device_pool.select_device",
|
||||
return_value="emulator-5554",
|
||||
|
||||
@@ -392,11 +392,13 @@ async def test_toolchain_probe_structure():
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_active_device_selection():
|
||||
"""Verify selecting a device updates engine state."""
|
||||
async def test_probe_target_serial_forwards_to_adb_probe():
|
||||
"""Verify the probe target preference reaches the ADB probe and can be cleared."""
|
||||
engine = ReadinessEngine()
|
||||
engine.set_active_device_serial("test-emulator-1234")
|
||||
assert engine.get_active_device_serial() == "test-emulator-1234"
|
||||
engine.set_probe_target_serial("test-emulator-1234")
|
||||
assert engine._adb_probe._target_serial == "test-emulator-1234"
|
||||
engine.set_probe_target_serial(None)
|
||||
assert engine._adb_probe._target_serial is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -156,11 +156,30 @@ def test_disconnect_reconciliation_stops_heartbeat_and_allows_reenrollment(
|
||||
assert configure.call_count == 2
|
||||
|
||||
|
||||
@patch("artemis.runtime.device_pool.device_pool.get_claimed_serials")
|
||||
@patch("artemis.runtime.awake_service.AdbClient")
|
||||
def test_discovery_honors_single_device_policy(adb_client):
|
||||
def test_discovery_keeps_only_pool_claimed_devices(adb_client, claimed):
|
||||
"""The pool manages two devices while the ADB server lists three: only the
|
||||
two claimed devices are kept awake; the unrelated one is left untouched."""
|
||||
adb_client.return_value.device_list.return_value = [
|
||||
MagicMock(serial="device-1"),
|
||||
MagicMock(serial="device-2"),
|
||||
MagicMock(serial="device-3"),
|
||||
]
|
||||
claimed.return_value = {"device-1", "device-2"}
|
||||
|
||||
assert _discover_connected_device_ids() == ["device-1", "device-2"]
|
||||
|
||||
|
||||
@patch(
|
||||
"artemis.runtime.device_pool.device_pool.get_claimed_serials",
|
||||
return_value=set(),
|
||||
)
|
||||
@patch("artemis.runtime.awake_service.AdbClient")
|
||||
def test_discovery_returns_nothing_when_pool_claims_no_device(adb_client, _claimed):
|
||||
adb_client.return_value.device_list.return_value = [
|
||||
MagicMock(serial="device-1"),
|
||||
MagicMock(serial="device-2"),
|
||||
]
|
||||
|
||||
assert _discover_connected_device_ids() == ["device-1"]
|
||||
assert _discover_connected_device_ids() == []
|
||||
@@ -91,6 +91,33 @@ def test_device_pool_list_devices_and_busy_status(monkeypatch):
|
||||
lock.release()
|
||||
|
||||
|
||||
def test_get_claimed_serials_reflects_locks_and_reservations():
|
||||
pool = DevicePool()
|
||||
assert pool.get_claimed_serials() == set()
|
||||
|
||||
lock = DeviceExecutionLock("emulator-5554", "claimed by test")
|
||||
lock.acquire()
|
||||
bound_ticket = DeviceExecutionLock.reserve(
|
||||
description="queued task",
|
||||
device_id="pixel-8-pro",
|
||||
session_id="queued-session",
|
||||
)
|
||||
unbound_ticket = DeviceExecutionLock.reserve(
|
||||
description="unbound task",
|
||||
device_id="pending",
|
||||
session_id="pending-session",
|
||||
)
|
||||
try:
|
||||
# Locked and reserved serials are claimed; the unbound placeholder is not.
|
||||
assert pool.get_claimed_serials() == {"emulator-5554", "pixel-8-pro"}
|
||||
finally:
|
||||
DeviceExecutionLock.cancel_reservation(bound_ticket)
|
||||
DeviceExecutionLock.cancel_reservation(unbound_ticket)
|
||||
lock.release()
|
||||
|
||||
assert pool.get_claimed_serials() == set()
|
||||
|
||||
|
||||
RAW_DEVICE = ("emulator-5554", "device", "Emulator", "sdk")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user