test_mqtt.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import json
  2. import logging
  3. import pathlib
  4. import unittest.mock
  5. import pytest
  6. import intertechno_cc1101_mqtt
  7. # pylint: disable=protected-access
  8. @pytest.mark.parametrize("mqtt_host", ["mqtt-broker.local"])
  9. @pytest.mark.parametrize("mqtt_port", [1833])
  10. @pytest.mark.parametrize("power_setting", [0xC6, 0x34])
  11. def test__run(caplog, mqtt_host, mqtt_port, power_setting):
  12. with unittest.mock.patch(
  13. "paho.mqtt.client.Client"
  14. ) as mqtt_client_mock, caplog.at_level(logging.DEBUG):
  15. intertechno_cc1101_mqtt._run(
  16. mqtt_host=mqtt_host,
  17. mqtt_port=mqtt_port,
  18. mqtt_username=None,
  19. mqtt_password=None,
  20. alias_file_path=None,
  21. power_setting=power_setting,
  22. )
  23. assert mqtt_client_mock.call_count == 1
  24. assert not mqtt_client_mock.call_args[0]
  25. assert set(mqtt_client_mock.call_args[1]) == {"userdata"}
  26. event_userdata = mqtt_client_mock.call_args[1]["userdata"]
  27. assert event_userdata.aliases == {}
  28. assert event_userdata.power_setting == power_setting
  29. assert not mqtt_client_mock().username_pw_set.called
  30. mqtt_client_mock().connect.assert_called_once_with(host=mqtt_host, port=mqtt_port)
  31. mqtt_client_mock().socket().getpeername.return_value = (mqtt_host, mqtt_port)
  32. with caplog.at_level(logging.DEBUG):
  33. mqtt_client_mock().on_connect(mqtt_client_mock(), event_userdata, {}, 0)
  34. # pylint: disable=comparison-with-callable
  35. assert mqtt_client_mock().on_message == intertechno_cc1101_mqtt._mqtt_on_message
  36. mqtt_client_mock().subscribe.assert_called_once_with("intertechno-cc1101/+/+/set")
  37. mqtt_client_mock().loop_forever.assert_called_once_with()
  38. assert caplog.record_tuples == [
  39. (
  40. "intertechno_cc1101_mqtt",
  41. logging.INFO,
  42. "connecting to MQTT broker {}:{}".format(mqtt_host, mqtt_port),
  43. ),
  44. (
  45. "intertechno_cc1101_mqtt",
  46. logging.DEBUG,
  47. "connected to MQTT broker {}:{}".format(mqtt_host, mqtt_port),
  48. ),
  49. (
  50. "intertechno_cc1101_mqtt",
  51. logging.INFO,
  52. "subscribing to MQTT topic 'intertechno-cc1101/+/+/set' (address & button index)",
  53. ),
  54. ]
  55. @pytest.mark.parametrize("mqtt_host", ["mqtt-broker.local"])
  56. @pytest.mark.parametrize("mqtt_port", [1833])
  57. @pytest.mark.parametrize("mqtt_username", ["me"])
  58. @pytest.mark.parametrize("mqtt_password", [None, "secret"])
  59. def test__run_authentication(mqtt_host, mqtt_port, mqtt_username, mqtt_password):
  60. with unittest.mock.patch("paho.mqtt.client.Client") as mqtt_client_mock:
  61. intertechno_cc1101_mqtt._run(
  62. mqtt_host=mqtt_host,
  63. mqtt_port=mqtt_port,
  64. mqtt_username=mqtt_username,
  65. mqtt_password=mqtt_password,
  66. alias_file_path=None,
  67. power_setting=0xC6,
  68. )
  69. assert mqtt_client_mock.call_count == 1
  70. mqtt_client_mock().username_pw_set.assert_called_once_with(
  71. username=mqtt_username, password=mqtt_password
  72. )
  73. @pytest.mark.parametrize("mqtt_host", ["mqtt-broker.local"])
  74. @pytest.mark.parametrize("mqtt_port", [1833])
  75. @pytest.mark.parametrize("mqtt_password", ["secret"])
  76. def test__run_authentication_missing_username(mqtt_host, mqtt_port, mqtt_password):
  77. with unittest.mock.patch("paho.mqtt.client.Client"):
  78. with pytest.raises(ValueError):
  79. intertechno_cc1101_mqtt._run(
  80. mqtt_host=mqtt_host,
  81. mqtt_port=mqtt_port,
  82. mqtt_username=None,
  83. mqtt_password=mqtt_password,
  84. alias_file_path=None,
  85. power_setting=0xC6,
  86. )
  87. @pytest.mark.parametrize("mqtt_host", ["mqtt-broker.local"])
  88. @pytest.mark.parametrize("mqtt_port", [1833])
  89. @pytest.mark.parametrize(
  90. "aliases", [{}, {"some-alias": {"address": 12345678, "button-index": 0}}]
  91. )
  92. def test__run_alias_file_path(caplog, tmp_path, mqtt_host, mqtt_port, aliases):
  93. alias_file_path = tmp_path.joinpath("aliases.json")
  94. alias_file_path.write_text(json.dumps(aliases))
  95. assert isinstance(alias_file_path, pathlib.Path)
  96. with unittest.mock.patch("paho.mqtt.client.Client") as mqtt_client_mock:
  97. intertechno_cc1101_mqtt._run(
  98. mqtt_host=mqtt_host,
  99. mqtt_port=mqtt_port,
  100. mqtt_username=None,
  101. mqtt_password=None,
  102. alias_file_path=alias_file_path,
  103. power_setting=0xC6,
  104. )
  105. assert mqtt_client_mock.call_count == 1
  106. event_userdata = mqtt_client_mock.call_args[1]["userdata"]
  107. assert event_userdata.aliases == aliases
  108. mqtt_client_mock().socket().getpeername.return_value = (mqtt_host, mqtt_port)
  109. with unittest.mock.patch(
  110. "intertechno_cc1101_mqtt._publish_homeassistant_discovery_configs"
  111. ) as publish_discovery_config_mock, caplog.at_level(logging.INFO):
  112. mqtt_client_mock().on_connect(mqtt_client_mock(), event_userdata, {}, 0)
  113. assert mqtt_client_mock().subscribe.call_args_list[0] == unittest.mock.call(
  114. "intertechno-cc1101/+/+/set"
  115. )
  116. assert caplog.record_tuples[0] == (
  117. "intertechno_cc1101_mqtt",
  118. logging.INFO,
  119. "subscribing to MQTT topic 'intertechno-cc1101/+/+/set' (address & button index)",
  120. )
  121. if len(aliases) == 0:
  122. assert mqtt_client_mock().subscribe.call_count == 1
  123. assert len(caplog.records) == 1
  124. publish_discovery_config_mock.assert_not_called()
  125. else:
  126. assert mqtt_client_mock().subscribe.call_count == 2
  127. assert len(caplog.records) == 2
  128. assert mqtt_client_mock().subscribe.call_args_list[1] == unittest.mock.call(
  129. "intertechno-cc1101/+/set"
  130. )
  131. assert caplog.record_tuples[1] == (
  132. "intertechno_cc1101_mqtt",
  133. logging.INFO,
  134. "subscribing to MQTT topic 'intertechno-cc1101/+/set' (alias)",
  135. )
  136. publish_discovery_config_mock.assert_called_once_with(
  137. mqtt_client=mqtt_client_mock(), aliases=aliases
  138. )