test(media_session,connection): logcat START parsing (cmp=, wrapped records, null/non-START ignored, u-prefixes), instant stamp + notify, duplicate START suppression, 5-in-10-min auto-disable, OFF = no stream task, stream never touches the poller socket (P5-3)
This commit is contained in:
1 parent
07cb73fbb7
commit
f863496ce5
2 files changed
+146
No files matched your search
@@ -179,6 +179,109 @@ class TestAppLabelCache:
|
||||
assert manager.app_label("com.unknown.app") is not None or True
|
||||
|
||||
|
||||
class TestLogcatStream:
|
||||
"""P5-3: the dedicated logcat fast-path behind CONF_LOGCAT_EVENTS."""
|
||||
|
||||
def _logcat_manager(self, lines, clock=None):
|
||||
from types import SimpleNamespace as LEntry
|
||||
|
||||
now = 1000.0
|
||||
poller = FakePoller()
|
||||
poller.awake = True
|
||||
manager = ShieldConnectionManager(
|
||||
hass=None, entry=None, poller=poller, clock=(clock or (lambda: now))
|
||||
)
|
||||
manager.entry = LEntry(options={"logcat_events": bool(lines)})
|
||||
lines = lines or []
|
||||
|
||||
async def _open():
|
||||
for line in lines:
|
||||
yield line
|
||||
|
||||
manager._open_logcat_stream = _open
|
||||
return manager, now
|
||||
|
||||
async def test_start_stamps_foreground_instantly(self):
|
||||
manager, _now = self._logcat_manager(
|
||||
[
|
||||
"03-21 10:19:41.792 3104 3456 I ActivityTaskManager:"
|
||||
" START u0 {cmp=com.netflix.ninja/x}",
|
||||
]
|
||||
)
|
||||
notified = []
|
||||
manager.register_listener(lambda: notified.append(1))
|
||||
|
||||
await manager._watchdog_cycle(5.0) # starts the consumer
|
||||
|
||||
import asyncio
|
||||
|
||||
await asyncio.sleep(0) # drain the task
|
||||
assert manager.store.get("foreground") == "com.netflix.ninja"
|
||||
assert notified # immediate listener notification (sub-heartbeat)
|
||||
|
||||
async def test_duplicate_start_suppressed_inside_window(self):
|
||||
stamps = [1000.0, 1005.0] # 5 s apart — inside the 15 s window
|
||||
tick = {"i": 0}
|
||||
|
||||
def advancing():
|
||||
tick["i"] = min(tick["i"] + 1, len(stamps)) - 1
|
||||
return stamps[tick["i"]]
|
||||
|
||||
manager, _now = self._logcat_manager(
|
||||
[
|
||||
"03-21 10:19:41.792 I ActivityTaskManager: START u0 {cmp=com.netflix.ninja/x}",
|
||||
"03-21 10:19:43.000 I ActivityTaskManager: START u0 {cmp=com.netflix.ninja/x}",
|
||||
],
|
||||
clock=advancing,
|
||||
)
|
||||
store_sets = {"n": 0}
|
||||
original_set = manager.store.set
|
||||
|
||||
def counting(name, value):
|
||||
if name == "foreground":
|
||||
store_sets["n"] += 1
|
||||
return original_set(name, value)
|
||||
|
||||
manager.store.set = counting
|
||||
|
||||
await manager._watchdog_cycle(5.0)
|
||||
await manager._run_logcat_stream() # drains the whole stream once
|
||||
# two identical STARTs inside the window stamp once
|
||||
assert store_sets["n"] == 1
|
||||
manager._logcat_task = None # the loop raised stream-ended already
|
||||
|
||||
async def test_repeated_failures_auto_disable(self):
|
||||
manager, _now = self._logcat_manager(
|
||||
["cmp=x"] # content is irrelevant: the stream ends after 1 line each run
|
||||
)
|
||||
# the stream rnux: ``_open`` raises — ladder counts the failure
|
||||
# starve the ladder: instant (no real sleep between reconnects)
|
||||
manager._open_logcat_stream = None
|
||||
|
||||
# drive the ladder manually: 5 failures in the 10-min window
|
||||
for index in range(6):
|
||||
manager._note_logcat_failure(1000.0 + index)
|
||||
|
||||
assert manager._logcat_disabled is True # auto-disable at 5
|
||||
assert manager._entry_options_logcat() is True # option unchanged
|
||||
|
||||
async def test_option_off_means_no_stream_task(self):
|
||||
manager, _now = self._logcat_manager(None) # logcat_events: falsy
|
||||
await manager._watchdog_cycle(5.0)
|
||||
await manager._watchdog_cycle(5.0)
|
||||
assert manager._logcat_task is None # zero behavior change
|
||||
|
||||
async def test_stream_never_touches_the_poller_socket(self):
|
||||
manager, _now = self._logcat_manager(
|
||||
[
|
||||
"03-21 10:19:41.792 3104 3456 I ActivityTaskManager:"
|
||||
" START u0 {cmp=com.netflix.ninja/x}",
|
||||
]
|
||||
)
|
||||
await manager._watchdog_cycle(5.0)
|
||||
assert manager._poller.shell_calls == [] # dedicated connection, not the poller
|
||||
|
||||
|
||||
class TestForegroundFallback:
|
||||
async def test_stamps_field_foreground_when_protocol_silent(self):
|
||||
poller = FakePoller()
|
||||
|
||||
@@ -209,3 +209,46 @@ def test_parse_application_label_tolerance():
|
||||
assert parse_application_label("application-label: null") is None
|
||||
assert parse_application_label("") is None
|
||||
assert parse_application_label("nothing here") is None
|
||||
|
||||
|
||||
def _logcat_lines():
|
||||
"""Synthetic logcat list covering START shapes + noise + wrapping."""
|
||||
return [
|
||||
"03-21 10:19:40.100 3104 3456 I NotificationService: noise",
|
||||
"03-21 10:19:41.792 3104 3456 I ActivityTaskManager: START u0 "
|
||||
"{cmp=com.netflix.ninja/com.netflix.ui.main flg=0x10000000}",
|
||||
"03-21 10:19:45.100 3104 3456 I ActivityTaskManager: START u0 {cmp=null}",
|
||||
"03-21 10:19:47.000 3104 3456 I ActivityTaskManager: START u10 "
|
||||
"{cmp=ar.tvplayer.tv/.ui.MainActivity",
|
||||
" xflg=214 abi=arm64-v8a}",
|
||||
"03-21 10:19:50.000 3104 3456 I ActivityTaskManager: Displayed",
|
||||
]
|
||||
|
||||
|
||||
def test_logcat_start_records_parse_cmp():
|
||||
from nsh.ha_adb_common.logcat_events import foreground_from_logcat, foreground_packages
|
||||
|
||||
lines = _logcat_lines()
|
||||
assert foreground_packages(lines) == ["com.netflix.ninja", "ar.tvplayer.tv"]
|
||||
# LAST valid START wins
|
||||
assert foreground_from_logcat(lines) == "ar.tvplayer.tv"
|
||||
|
||||
|
||||
def test_logcat_non_start_and_null_ignored():
|
||||
from nsh.ha_adb_common.logcat_events import foreground_from_logcat
|
||||
|
||||
assert foreground_from_logcat([
|
||||
"03-21 10:19:50.000 3104 3456 I ActivityTaskManager: Displayed",
|
||||
"plain noise",
|
||||
]) is None
|
||||
lines = _logcat_lines()
|
||||
assert foreground_from_logcat(lines) == "ar.tvplayer.tv" # null skipped
|
||||
|
||||
|
||||
def test_logcat_multi_user_prefix_tolerated():
|
||||
from nsh.ha_adb_common.logcat_events import foreground_from_logcat
|
||||
|
||||
assert foreground_from_logcat(
|
||||
["03-21 10:19:41.792 3104 3456 I ActivityTaskManager: START u123 {cmp=net.whatsapp/"] + [
|
||||
" flg=0x1}"]
|
||||
) == "net.whatsapp"
|
||||
Reference in new issue
Block a user