Files
Artemis-Eapil/tests/unit/runtime/test_awake_service.py
T
somew1nd 12d7902a82 fix: correct task scheduling and simplify agent internals
Fix queue cancellation, concurrency limits and worker status updates.

Use direct Explorer imports, split the Diagnoser loop into helpers and remove unused tool registration and prompt-builder code.

Correct model caching, endpoint selection and retry handling.
2026-09-02 22:58:00 -07:00

189 lines
6.5 KiB
Python

from unittest.mock import MagicMock, patch
from artemis.runtime.awake_service import (
AWAKE_STRATEGY_HEARTBEAT,
AWAKE_STRATEGY_USB,
ScreenAwakeService,
_configure_usb_stay_awake,
_discover_connected_device_ids,
)
def completed(stdout="", returncode=0, stderr=""):
return MagicMock(returncode=returncode, stdout=stdout, stderr=stderr)
@patch("artemis.runtime.awake_service.ScreenAwakeLease")
@patch("artemis.runtime.awake_service.subprocess.run")
def test_usb_policy_is_primary_when_android_reports_it_active(mock_run, lease_type):
mock_run.side_effect = [
completed(),
completed(),
completed(),
completed("2\n"),
completed(" mIsPowered=true\n mPlugType=2\n mStayOn=true\n"),
]
assert _configure_usb_stay_awake("device-123") == AWAKE_STRATEGY_USB
lease_type.assert_called_once_with("device-123")
lease_type.return_value.cleanup_unowned_references.assert_called_once_with()
commands = [call.args[0] for call in mock_run.call_args_list]
# Commands are endpoint-qualified (adb -H host -P port -s serial ...);
# assert on the payload after the serial rather than a fixed prefix width.
payloads = [command[command.index("-s") + 2 :] for command in commands if "-s" in command]
assert ["shell", "svc", "power", "stayon", "usb"] in payloads
assert not any("SCREEN_BRIGHT_WAKE_LOCK" in command for command in commands)
assert not any("KEYCODE_UNKNOWN" in command for command in commands)
@patch("artemis.runtime.awake_service.ScreenAwakeLease")
@patch("artemis.runtime.awake_service.subprocess.run")
def test_inactive_usb_policy_falls_back_to_effective_host_heartbeat(mock_run, _lease_type):
mock_run.side_effect = [
completed(),
completed(),
completed(),
completed("2\n"),
completed(" mIsPowered=true\n mPlugType=2\n mStayOn=false\n"),
completed(),
]
assert _configure_usb_stay_awake("device-123") == AWAKE_STRATEGY_HEARTBEAT
assert mock_run.call_args_list[-1].args[0][-1] == "KEYCODE_UNKNOWN"
@patch.dict("os.environ", {"ARTEMIS_KEEP_DEVICE_AWAKE": "false"})
@patch("artemis.runtime.awake_service.subprocess.run")
def test_awake_strategy_can_be_disabled(mock_run):
assert _configure_usb_stay_awake("device-123") is None
mock_run.assert_not_called()
@patch("artemis.runtime.awake_service.threading.Thread")
@patch("artemis.runtime.awake_service.threading.Event")
@patch(
"artemis.runtime.awake_service._configure_usb_stay_awake",
return_value=AWAKE_STRATEGY_HEARTBEAT,
)
def test_host_heartbeat_lives_until_host_shutdown(configure, event_type, thread_type):
service = ScreenAwakeService()
stop_event = event_type.return_value
thread = thread_type.return_value
service.ensure_device("device-123")
service.ensure_device("device-123")
configure.assert_called_once_with("device-123")
thread.start.assert_called_once_with()
stop_event.set.assert_not_called()
service.shutdown()
service.shutdown()
stop_event.set.assert_called_once_with()
thread.join.assert_called_once_with(timeout=2.0)
@patch("artemis.runtime.awake_service._run_awake_adb_command")
@patch("artemis.runtime.awake_service.threading.Thread")
@patch("artemis.runtime.awake_service.threading.Event")
@patch(
"artemis.runtime.awake_service._configure_usb_stay_awake",
return_value=AWAKE_STRATEGY_HEARTBEAT,
)
def test_heartbeat_loop_uses_verified_user_activity_key(
_configure, event_type, thread_type, run_command
):
stop_event = event_type.return_value
stop_event.wait.side_effect = [False, True]
service = ScreenAwakeService()
service.ensure_device("device-123")
heartbeat_target = thread_type.call_args.kwargs["target"]
heartbeat_target()
run_command.assert_called_once_with(
"device-123",
["shell", "input", "keyevent", "KEYCODE_UNKNOWN"],
"send the host stay-awake heartbeat",
)
@patch("artemis.runtime.awake_service.threading.Thread")
@patch("artemis.runtime.awake_service.threading.Event")
@patch("artemis.runtime.awake_service._discover_connected_device_ids")
@patch(
"artemis.runtime.awake_service._configure_usb_stay_awake",
return_value=AWAKE_STRATEGY_USB,
)
def test_service_monitor_enrolls_a_device_attached_after_start(
configure, discover, event_type, thread_type
):
discover.side_effect = [[], ["device-late"]]
stop_event = event_type.return_value
stop_event.wait.side_effect = [False, True]
stop_event.is_set.return_value = False
service = ScreenAwakeService()
service.start()
monitor_target = thread_type.call_args.kwargs["target"]
monitor_target()
configure.assert_called_once_with("device-late")
assert service.device_ids == ("device-late",)
@patch("artemis.runtime.awake_service.threading.Thread")
@patch("artemis.runtime.awake_service.threading.Event")
@patch(
"artemis.runtime.awake_service._configure_usb_stay_awake",
return_value=AWAKE_STRATEGY_HEARTBEAT,
)
def test_disconnect_reconciliation_stops_heartbeat_and_allows_reenrollment(
configure, event_type, thread_type
):
service = ScreenAwakeService()
stop_event = event_type.return_value
thread = thread_type.return_value
service.ensure_device("device-123")
service._reconcile_connected_devices(set())
stop_event.set.assert_called_once_with()
thread.join.assert_called_once_with(timeout=2.0)
assert service.device_ids == ()
service.ensure_device("device-123")
assert configure.call_count == 2
@patch("artemis.runtime.device_pool.device_pool.get_claimed_serials")
@patch("artemis.runtime.awake_service.AdbClient")
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() == []