def test_publish_preparing_for_shutdown_homeassistant_config( topic_prefix, discovery_prefix, node_id, hostname ): state = systemctl_mqtt._State( mqtt_topic_prefix=topic_prefix, homeassistant_discovery_prefix=discovery_prefix, homeassistant_node_id=node_id, poweroff_delay=datetime.timedelta(), ) mqtt_client = unittest.mock.MagicMock() with unittest.mock.patch( "systemctl_mqtt._utils.get_hostname", return_value=hostname ): state.publish_preparing_for_shutdown_homeassistant_config( mqtt_client=mqtt_client ) assert mqtt_client.publish.call_count == 1 publish_args, publish_kwargs = mqtt_client.publish.call_args assert not publish_args assert publish_kwargs["retain"] assert ( publish_kwargs["topic"] == discovery_prefix + "/binary_sensor/" + node_id + "/preparing-for-shutdown/config" ) assert json.loads(publish_kwargs["payload"]) == { "unique_id": "systemctl-mqtt/" + node_id + "/logind/preparing-for-shutdown", "state_topic": topic_prefix + "/preparing-for-shutdown", "payload_on": "true", "payload_off": "false", "name": node_id + " preparing for shutdown", }
def test_poweroff_trigger(delay): action = systemctl_mqtt._MQTTActionSchedulePoweroff() with unittest.mock.patch("systemctl_mqtt._dbus.schedule_shutdown" ) as schedule_shutdown_mock: action.trigger(state=systemctl_mqtt._State( mqtt_topic_prefix="systemctl/hostname", homeassistant_discovery_prefix="homeassistant", homeassistant_node_id="node", poweroff_delay=delay, )) schedule_shutdown_mock.assert_called_once_with(action="poweroff", delay=delay)
def test_mqtt_topic_suffix_action_mapping_poweroff(topic_suffix, expected_action_arg): mqtt_action = systemctl_mqtt._MQTT_TOPIC_SUFFIX_ACTION_MAPPING[ topic_suffix] login_manager_mock = unittest.mock.MagicMock() with unittest.mock.patch("systemctl_mqtt._dbus.get_login_manager", return_value=login_manager_mock): mqtt_action.trigger(state=systemctl_mqtt._State( mqtt_topic_prefix="systemctl/hostname", homeassistant_discovery_prefix="homeassistant", homeassistant_node_id="node", poweroff_delay=datetime.timedelta(), )) assert login_manager_mock.ScheduleShutdown.call_count == 1 schedule_args, schedule_kwargs = login_manager_mock.ScheduleShutdown.call_args assert len(schedule_args) == 2 assert schedule_args[0] == expected_action_arg assert not schedule_kwargs
def test_shutdown_lock(): lock_fd = unittest.mock.MagicMock() with unittest.mock.patch("systemctl_mqtt._dbus.get_login_manager"): state = systemctl_mqtt._State( mqtt_topic_prefix="any", homeassistant_discovery_prefix=None, homeassistant_node_id=None, poweroff_delay=datetime.timedelta(), ) state._login_manager.Inhibit.return_value = lock_fd state.acquire_shutdown_lock() state._login_manager.Inhibit.assert_called_once_with( "shutdown", "systemctl-mqtt", "Report shutdown via MQTT", "delay" ) assert state._shutdown_lock == lock_fd # https://dbus.freedesktop.org/doc/dbus-python/dbus.types.html#dbus.types.UnixFd.take lock_fd.take.return_value = "fdnum" with unittest.mock.patch("os.close") as close_mock: state.release_shutdown_lock() close_mock.assert_called_once_with("fdnum")
def test_publish_preparing_for_shutdown_get_fail(caplog): login_manager_mock = unittest.mock.MagicMock() login_manager_mock.Get.side_effect = dbus.DBusException("mocked") with unittest.mock.patch( "systemctl_mqtt._dbus.get_login_manager", return_value=login_manager_mock ): state = systemctl_mqtt._State( mqtt_topic_prefix="any", homeassistant_discovery_prefix=None, homeassistant_node_id=None, poweroff_delay=datetime.timedelta(), ) mqtt_client_mock = unittest.mock.MagicMock() state.publish_preparing_for_shutdown(mqtt_client=None) mqtt_client_mock.publish.assert_not_called() assert len(caplog.records) == 1 assert caplog.records[0].levelno == logging.ERROR assert ( caplog.records[0].message == "failed to read logind's PreparingForShutdown property: mocked" )
def test_prepare_for_shutdown_handler(caplog, active): with unittest.mock.patch("systemctl_mqtt._dbus.get_login_manager"): state = systemctl_mqtt._State( mqtt_topic_prefix="any", homeassistant_discovery_prefix=None, homeassistant_node_id=None, poweroff_delay=datetime.timedelta(), ) mqtt_client_mock = unittest.mock.MagicMock() state.register_prepare_for_shutdown_handler(mqtt_client=mqtt_client_mock) # pylint: disable=no-member,comparison-with-callable connect_to_signal_kwargs = state._login_manager.connect_to_signal.call_args[1] assert connect_to_signal_kwargs["signal_name"] == "PrepareForShutdown" handler_function = connect_to_signal_kwargs["handler_function"] assert handler_function.func == state._prepare_for_shutdown_handler with unittest.mock.patch.object( state, "acquire_shutdown_lock" ) as acquire_lock_mock, unittest.mock.patch.object( state, "release_shutdown_lock" ) as release_lock_mock: handler_function(dbus.types.Boolean(active)) if active: acquire_lock_mock.assert_not_called() release_lock_mock.assert_called_once_with() else: acquire_lock_mock.assert_called_once_with() release_lock_mock.assert_not_called() mqtt_client_mock.publish.assert_called_once_with( topic="any/preparing-for-shutdown", payload="true" if active else "false", retain=True, ) assert len(caplog.records) == 1 assert caplog.records[0].levelno == logging.ERROR assert caplog.records[0].message.startswith( "failed to publish on any/preparing-for-shutdown" )