mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-01 08:48:05 +00:00
perf(wifi): one status fetch per monitor tick instead of three (#411)
* perf(wifi): one status fetch per monitor tick instead of three The wifi monitor daemon fetched WiFi status + ethernet state before its AP-mode check, the check internally fetched the same state again (with retry), and the daemon fetched a third time afterwards — each fetch is several nmcli subprocess forks, every 30s, forever, even on a perfectly healthy link. check_and_manage_ap_mode's decision logic is extracted to _manage_ap_mode(status, ethernet, ap_active); the new check_and_manage_ap_mode_with_state() runs the single (retrying) fetch battery and returns (changed, status, ethernet, ap_active_after) — the post-state is derivable because state only ever flips via one enable or one disable. The original bool-returning method delegates, so existing callers are untouched. The daemon's dead pre-fetch is removed and its post-check reads use the returned state; the AP-enable retry semantics (_get_wifi_status_with_retry) are preserved exactly. ~10-15 forks/30s drops to ~4-6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam * fix(wifi): add missing type hints on AP-mode state helpers, fix unused-var lint in tests - check_and_manage_ap_mode_with_state now declares its Tuple[bool, WiFiStatus, bool, bool] return type instead of being untyped. - _manage_ap_mode's status/ethernet_connected/ap_active parameters are now typed (WiFiStatus, bool, bool), matching its existing -> bool return hint. - test_wifi_check_state.py: rename unused unpacked variables (status/ ethernet/ap_after) to underscore-prefixed names at the three call sites that don't use them, leaving the used ones untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ --------- Co-authored-by: Chuck <chuck@example.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
Chuck
parent
bff13129c4
commit
14a59c863c
@@ -0,0 +1,92 @@
|
||||
"""Tests for check_and_manage_ap_mode_with_state (src/wifi_manager.py).
|
||||
|
||||
The wifi monitor daemon used to fetch WiFi status before AND after each
|
||||
check on top of the check's own internal fetch — every fetch is several
|
||||
nmcli subprocess forks, every 30s, forever. The new API returns the state
|
||||
the check observed, so the daemon runs exactly one fetch battery per tick.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
from src.wifi_manager import WiFiManager, WiFiStatus # noqa: E402
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wm(tmp_path):
|
||||
with patch.object(WiFiManager, "_load_config", return_value={}, create=True):
|
||||
manager = WiFiManager.__new__(WiFiManager)
|
||||
# minimal attribute setup without running the real __init__
|
||||
manager.config = {"auto_enable_ap_mode": True}
|
||||
manager._disconnected_checks = 0
|
||||
manager._disconnected_checks_required = 3
|
||||
manager._ap_enabled_at = None
|
||||
return manager
|
||||
|
||||
|
||||
def _wire(wm, connected, ethernet, ap_active):
|
||||
wm._get_wifi_status_with_retry = MagicMock(
|
||||
return_value=WiFiStatus(connected=connected, ssid="net" if connected else None))
|
||||
wm._is_ethernet_connected = MagicMock(return_value=ethernet)
|
||||
wm._is_ap_mode_active = MagicMock(return_value=ap_active)
|
||||
wm.enable_ap_mode = MagicMock(return_value=(True, "ok"))
|
||||
wm.disable_ap_mode = MagicMock(return_value=(True, "ok"))
|
||||
wm.scan_networks = MagicMock(return_value=([], False))
|
||||
wm._save_cached_scan = MagicMock()
|
||||
wm._FORCE_AP_FLAG_PATH = MagicMock()
|
||||
wm._FORCE_AP_FLAG_PATH.exists.return_value = False
|
||||
|
||||
|
||||
class TestWithState:
|
||||
def test_single_fetch_per_call(self, wm):
|
||||
_wire(wm, connected=True, ethernet=False, ap_active=False)
|
||||
wm.check_and_manage_ap_mode_with_state()
|
||||
assert wm._get_wifi_status_with_retry.call_count == 1
|
||||
assert wm._is_ethernet_connected.call_count == 1
|
||||
assert wm._is_ap_mode_active.call_count == 1
|
||||
|
||||
def test_returns_observed_state(self, wm):
|
||||
_wire(wm, connected=True, ethernet=True, ap_active=False)
|
||||
changed, status, ethernet, ap_after = wm.check_and_manage_ap_mode_with_state()
|
||||
assert changed is False
|
||||
assert status.connected is True
|
||||
assert ethernet is True
|
||||
assert ap_after is False
|
||||
|
||||
def test_ap_after_inverts_on_disable(self, wm):
|
||||
"""WiFi reconnects while AP is up -> auto-disable -> ap_after False."""
|
||||
_wire(wm, connected=True, ethernet=False, ap_active=True)
|
||||
changed, _status, _ethernet, ap_after = wm.check_and_manage_ap_mode_with_state()
|
||||
assert changed is True
|
||||
assert ap_after is False
|
||||
wm.disable_ap_mode.assert_called_once()
|
||||
|
||||
def test_ap_after_inverts_on_enable(self, wm):
|
||||
"""Grace period exhausted with nothing connected -> enable -> True."""
|
||||
_wire(wm, connected=False, ethernet=False, ap_active=False)
|
||||
wm._disconnected_checks = 2 # this call is the 3rd
|
||||
changed, _status, _ethernet, ap_after = wm.check_and_manage_ap_mode_with_state()
|
||||
assert changed is True
|
||||
assert ap_after is True
|
||||
wm.enable_ap_mode.assert_called_once()
|
||||
|
||||
def test_bool_wrapper_is_back_compatible(self, wm):
|
||||
_wire(wm, connected=True, ethernet=False, ap_active=False)
|
||||
assert wm.check_and_manage_ap_mode() is False
|
||||
_wire(wm, connected=True, ethernet=False, ap_active=True)
|
||||
assert wm.check_and_manage_ap_mode() is True
|
||||
|
||||
def test_exception_path_never_raises(self, wm):
|
||||
wm._get_wifi_status_with_retry = MagicMock(side_effect=RuntimeError("nmcli gone"))
|
||||
changed, status, _ethernet, _ap_after = wm.check_and_manage_ap_mode_with_state()
|
||||
assert changed is False
|
||||
assert status.connected is False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__, "-v"]))
|
||||
Reference in New Issue
Block a user