|
@@ -77,6 +77,13 @@ async def test__run(
|
|
|
assert isinstance(mqtt_client_init_kwargs.pop("tls_context"), ssl.SSLContext)
|
|
|
assert mqtt_client_init_kwargs.pop("username") is None
|
|
|
assert mqtt_client_init_kwargs.pop("password") is None
|
|
|
+ assert mqtt_client_init_kwargs.pop("will") == aiomqtt.Will(
|
|
|
+ topic=mqtt_topic_prefix + "/status",
|
|
|
+ payload="offline",
|
|
|
+ qos=0,
|
|
|
+ retain=True,
|
|
|
+ properties=None,
|
|
|
+ )
|
|
|
assert not mqtt_client_init_kwargs
|
|
|
login_manager_mock.Inhibit.assert_called_once_with(
|
|
|
what="shutdown",
|
|
@@ -87,7 +94,7 @@ async def test__run(
|
|
|
login_manager_mock.Get.assert_called_once_with("PreparingForShutdown")
|
|
|
async with mqtt_client_class_mock() as mqtt_client_mock:
|
|
|
pass
|
|
|
- assert mqtt_client_mock.publish.call_count == 2
|
|
|
+ assert mqtt_client_mock.publish.call_count == 4
|
|
|
assert (
|
|
|
mqtt_client_mock.publish.call_args_list[0][1]["topic"]
|
|
|
== f"{homeassistant_discovery_prefix}/device/{homeassistant_discovery_object_id}/config"
|
|
@@ -97,6 +104,16 @@ async def test__run(
|
|
|
payload="false",
|
|
|
retain=False,
|
|
|
)
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[2][1] == {
|
|
|
+ "topic": mqtt_topic_prefix + "/status",
|
|
|
+ "payload": "online",
|
|
|
+ "retain": True,
|
|
|
+ }
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[3][1] == {
|
|
|
+ "topic": mqtt_topic_prefix + "/status",
|
|
|
+ "payload": "offline",
|
|
|
+ "retain": True,
|
|
|
+ }
|
|
|
assert sorted(mqtt_client_mock.subscribe.call_args_list) == [
|
|
|
unittest.mock.call(mqtt_topic_prefix + "/lock-all-sessions"),
|
|
|
unittest.mock.call(mqtt_topic_prefix + "/poweroff"),
|
|
@@ -160,9 +177,7 @@ async def test__run_tls(caplog, mqtt_host, mqtt_port, mqtt_disable_tls):
|
|
|
assert mqtt_client_init_kwargs.pop("tls_context") is None
|
|
|
else:
|
|
|
assert isinstance(mqtt_client_init_kwargs.pop("tls_context"), ssl.SSLContext)
|
|
|
- assert mqtt_client_init_kwargs.pop("username") is None
|
|
|
- assert mqtt_client_init_kwargs.pop("password") is None
|
|
|
- assert not mqtt_client_init_kwargs
|
|
|
+ assert set(mqtt_client_init_kwargs.keys()) == {"username", "password", "will"}
|
|
|
assert caplog.records[0].levelno == logging.INFO
|
|
|
assert caplog.records[0].message == (
|
|
|
f"connecting to MQTT broker {mqtt_host}:{mqtt_port}"
|
|
@@ -256,6 +271,51 @@ async def test__run_authentication_missing_username(
|
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
+@pytest.mark.parametrize("mqtt_topic_prefix", ["systemctl/host"])
|
|
|
+async def test__run_sigint(mqtt_topic_prefix: str):
|
|
|
+ login_manager_mock = unittest.mock.MagicMock()
|
|
|
+ with unittest.mock.patch(
|
|
|
+ "aiomqtt.Client", autospec=False
|
|
|
+ ) as mqtt_client_class_mock, unittest.mock.patch(
|
|
|
+ "systemctl_mqtt._dbus.get_login_manager_proxy", return_value=login_manager_mock
|
|
|
+ ), unittest.mock.patch(
|
|
|
+ "asyncio.gather", side_effect=KeyboardInterrupt
|
|
|
+ ):
|
|
|
+ login_manager_mock.Inhibit.return_value = (jeepney.fds.FileDescriptor(-1),)
|
|
|
+ login_manager_mock.Get.return_value = (("b", False),)
|
|
|
+ with pytest.raises(KeyboardInterrupt):
|
|
|
+ await systemctl_mqtt._run(
|
|
|
+ mqtt_host="mqtt-broker.local",
|
|
|
+ mqtt_port=1883,
|
|
|
+ mqtt_username=None,
|
|
|
+ mqtt_password=None,
|
|
|
+ mqtt_topic_prefix=mqtt_topic_prefix,
|
|
|
+ homeassistant_discovery_prefix="homeassistant",
|
|
|
+ homeassistant_discovery_object_id="host",
|
|
|
+ poweroff_delay=datetime.timedelta(),
|
|
|
+ )
|
|
|
+ async with mqtt_client_class_mock() as mqtt_client_mock:
|
|
|
+ pass
|
|
|
+ assert mqtt_client_mock.publish.call_count == 4
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[0][1]["topic"].endswith("/config")
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[1][1]["topic"].endswith(
|
|
|
+ "/preparing-for-shutdown"
|
|
|
+ )
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[2][1] == {
|
|
|
+ "topic": mqtt_topic_prefix + "/status",
|
|
|
+ "payload": "online",
|
|
|
+ "retain": True,
|
|
|
+ }
|
|
|
+ assert mqtt_client_mock.publish.call_args_list[3][1] == {
|
|
|
+ "topic": mqtt_topic_prefix + "/status",
|
|
|
+ "payload": "offline",
|
|
|
+ "retain": True,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+@pytest.mark.asyncio
|
|
|
+@pytest.mark.filterwarnings("ignore:coroutine '_dbus_signal_loop' was never awaited")
|
|
|
+@pytest.mark.filterwarnings("ignore:coroutine '_mqtt_message_loop' was never awaited")
|
|
|
@pytest.mark.parametrize("mqtt_topic_prefix", ["systemctl/host", "system/command"])
|
|
|
async def test__mqtt_message_loop_trigger_poweroff(
|
|
|
caplog: pytest.LogCaptureFixture, mqtt_topic_prefix: str
|