test(ha_adb_common): fixture-driven foreground-parser tests — TiviMate capture, R4 launcher, wrap join, topResumed fallback ordering, duplicates tolerated (P3-2a)

This commit is contained in:
James Mackay committed 2026-10-08 10:39:43 +01:00
1 parent 8885ddd5b5
commit bb2f787fcd
3 files changed
+266 -6

No files matched your search

+130
View File
@@ -123,6 +123,136 @@ class TestStateStore:
assert store.get(FIELD_AWAKE) is None
class TestForegroundFallback:
async def test_stamps_field_foreground_when_protocol_silent(self):
poller = FakePoller()
poller.awake = True
poller.foreground = "ar.tvplayer.tv" # TiviMate, no session (R2)
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
assert poller.foreground_calls == 1
assert manager.store.get("foreground") == "ar.tvplayer.tv"
# store priority: protocol push wins over the ADB parse
assert manager.foreground_app == "ar.tvplayer.tv"
async def test_protocol_push_overrides_adb_foreground(self):
poller = FakePoller()
poller.awake = True
poller.foreground = "ar.tvplayer.tv"
manager = _manager(poller)
manager.store.set("current_app", "com.netflix.ninja") # live push
await manager._watchdog_cycle(5.0)
assert poller.foreground_calls == 0 # skipped — push is fresh
assert manager.foreground_app == "com.netflix.ninja"
async def test_no_foreground_query_when_asleep(self):
poller = FakePoller()
poller.awake = False
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
assert poller.foreground_calls == 0
assert manager.store.get("foreground") is None
class TestAudioPlaybackFilter:
async def test_system_media_packages_filtered(self):
poller = FakePoller()
poller.awake = True
poller.audio_dump = (
" Audio playback (lastly played comes first)\n"
" uid=1 packages=com.google.android.apps.mediashell\n"
" uid=2 packages=ar.tvplayer.tv\n"
" uid=3 packages=com.android.systemui\n"
)
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
assert manager.audio_playback == ["ar.tvplayer.tv"]
class TestLastKnownStateCache:
async def test_serves_last_known_when_no_session(self):
poller = FakePoller()
poller.awake = True
poller.sessions = [MediaSessionInfo(package="ar.tvplayer.tv", playing=True)]
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
# later: TiviMate stops publishing; foreground has no session
poller.sessions = []
await manager._watchdog_cycle(5.0)
served = manager.best_session("ar.tvplayer.tv")
assert served is not None
assert served.playing is True # the last known state
info, stamp = manager.last_known_state("ar.tvplayer.tv")
assert info is served
assert stamp is not None
async def test_expiry_never_resurrects_playing(self):
"""P3-2d expiry contract, deterministic via the injected clock."""
now = 1000.0
poller = FakePoller()
poller.awake = True
poller.sessions = [MediaSessionInfo(package="ar.tvplayer.tv", playing=True)]
manager = _manager(poller, clock=lambda: now)
await manager._watchdog_cycle(5.0)
assert manager.last_known_session("ar.tvplayer.tv") is not None
# TTL passes with no further caching — 'playing' must NOT come back
now += manager.store.ttl + 0.05
assert manager.last_known_session("ar.tvplayer.tv") is None
assert manager.last_known_state("ar.tvplayer.tv") == (None, None)
assert manager.best_session("ar.tvplayer.tv") is None
async def test_state_inside_ttl_is_served(self):
now = 1000.0
poller = FakePoller()
poller.awake = True
poller.sessions = [MediaSessionInfo(package="ar.tvplayer.tv", playing=True)]
manager = _manager(poller, clock=lambda: now)
await manager._watchdog_cycle(5.0)
now += manager.store.ttl - 1.0 # inside the TTL
info, stamp = manager.last_known_state("ar.tvplayer.tv")
assert info is not None and info.playing is True
assert stamp == 1000.0 # the cycle's cache stamp
async def test_live_session_beats_last_known(self):
poller = FakePoller()
poller.awake = True
poller.sessions = [MediaSessionInfo(package="app.old", playing=True)]
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
# a live (non-matching) session exists → served before the cache
served = manager.best_session("ar.tvplayer.tv")
assert served is not None and served.package == "app.old"
async def test_cache_cleared_on_stop(self):
poller = FakePoller()
poller.awake = True
poller.sessions = [MediaSessionInfo(package="ar.tvplayer.tv", playing=True)]
manager = _manager(poller)
await manager._watchdog_cycle(5.0)
await manager.async_stop()
assert manager._last_known == {}
class TestConnectAndRefresh:
async def test_cycle_connects_and_populates_store(self):
poller = FakePoller()