2.15.26
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
|
||||
class _StopMonitor(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class _FakeTime:
|
||||
now_ms = 0
|
||||
stop_at_ms = None
|
||||
|
||||
@classmethod
|
||||
def reset(cls, stop_at_ms=None):
|
||||
cls.now_ms = 0
|
||||
cls.stop_at_ms = stop_at_ms
|
||||
|
||||
@classmethod
|
||||
def ticks_ms(cls):
|
||||
return cls.now_ms
|
||||
|
||||
@classmethod
|
||||
def sleep_ms(cls, milliseconds):
|
||||
cls.now_ms += milliseconds
|
||||
if cls.stop_at_ms is not None and cls.now_ms >= cls.stop_at_ms:
|
||||
raise _StopMonitor()
|
||||
|
||||
|
||||
def _load_power_module():
|
||||
module_path = Path(__file__).resolve().parents[1] / "power.py"
|
||||
module_name = "power_charging_shutdown_test"
|
||||
maix_module = types.ModuleType("maix")
|
||||
maix_module.time = _FakeTime
|
||||
|
||||
previous_maix = sys.modules.get("maix")
|
||||
sys.modules["maix"] = maix_module
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
finally:
|
||||
if previous_maix is None:
|
||||
sys.modules.pop("maix", None)
|
||||
else:
|
||||
sys.modules["maix"] = previous_maix
|
||||
|
||||
|
||||
power = _load_power_module()
|
||||
|
||||
|
||||
class ChargingShutdownTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.config_patch = mock.patch.multiple(
|
||||
power.config,
|
||||
CHARGING_SHUTDOWN_ENABLED=True,
|
||||
CHARGING_DIAGNOSTIC_LOG_ENABLED=False,
|
||||
CHARGING_CHECK_INTERVAL_MS=5000,
|
||||
CHARGING_CURRENT_THRESHOLD_MA=100.0,
|
||||
CHARGING_CONFIRM_COUNT=2,
|
||||
CHARGING_NOTIFY_TIMEOUT_MS=30000,
|
||||
CHARGING_EXIT_SCRIPT="/tmp/charging_exit.sh",
|
||||
)
|
||||
self.config_patch.start()
|
||||
self.network_manager = mock.Mock()
|
||||
self.network_manager.safe_enqueue_and_wait.return_value = True
|
||||
network_module = types.ModuleType("network")
|
||||
network_module.network_manager = self.network_manager
|
||||
self.network_module_patch = mock.patch.dict(
|
||||
sys.modules,
|
||||
{"network": network_module},
|
||||
)
|
||||
self.network_module_patch.start()
|
||||
_FakeTime.reset()
|
||||
|
||||
def tearDown(self):
|
||||
self.network_module_patch.stop()
|
||||
self.config_patch.stop()
|
||||
|
||||
def test_two_charging_samples_notify_server_and_exit(self):
|
||||
popen_calls = []
|
||||
with (
|
||||
mock.patch.object(power, "get_current", return_value=-200.0),
|
||||
mock.patch.object(power.os.path, "isfile", return_value=True),
|
||||
mock.patch.object(
|
||||
power.subprocess,
|
||||
"Popen",
|
||||
side_effect=lambda args: popen_calls.append(args),
|
||||
),
|
||||
):
|
||||
power.charging_shutdown_monitor()
|
||||
|
||||
self.assertEqual(_FakeTime.now_ms, 5000)
|
||||
self.assertEqual(len(popen_calls), 1)
|
||||
self.network_manager.safe_enqueue_and_wait.assert_called_once_with(
|
||||
{"poweroff": "充电中"}, 2, high=True, timeout_ms=30000
|
||||
)
|
||||
|
||||
def test_discharging_does_not_notify_or_exit(self):
|
||||
_FakeTime.reset(stop_at_ms=10000)
|
||||
popen_calls = []
|
||||
|
||||
with (
|
||||
mock.patch.object(power, "get_current", return_value=200.0),
|
||||
mock.patch.object(power.os.path, "isfile", return_value=True),
|
||||
mock.patch.object(
|
||||
power.subprocess,
|
||||
"Popen",
|
||||
side_effect=lambda args: popen_calls.append(args),
|
||||
),
|
||||
self.assertRaises(_StopMonitor),
|
||||
):
|
||||
power.charging_shutdown_monitor()
|
||||
|
||||
self.assertEqual(popen_calls, [])
|
||||
self.network_manager.safe_enqueue_and_wait.assert_not_called()
|
||||
|
||||
def test_failed_sample_resets_confirmation_count(self):
|
||||
popen_calls = []
|
||||
currents = iter((-200.0, 0.0, -200.0, -200.0))
|
||||
with (
|
||||
mock.patch.object(power, "get_current", side_effect=lambda: next(currents)),
|
||||
mock.patch.object(power.os.path, "isfile", return_value=True),
|
||||
mock.patch.object(
|
||||
power.subprocess,
|
||||
"Popen",
|
||||
side_effect=lambda args: popen_calls.append(args),
|
||||
),
|
||||
):
|
||||
power.charging_shutdown_monitor()
|
||||
|
||||
self.assertEqual(_FakeTime.now_ms, 15000)
|
||||
self.assertEqual(len(popen_calls), 1)
|
||||
self.network_manager.safe_enqueue_and_wait.assert_called_once_with(
|
||||
{"poweroff": "充电中"}, 2, high=True, timeout_ms=30000
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user