Merge pull request #190 from ajmirsky/test_paho

resolve #170. add tests to verify compatibility with paho-mqtt library
pull/193/head
Andrew Mirsky 2025-06-01 11:17:52 -04:00 zatwierdzone przez GitHub
commit 76661e4625
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
3 zmienionych plików z 142 dodań i 0 usunięć

Wyświetl plik

@ -36,6 +36,7 @@ dev = [
"hatch>=1.14.1",
"hypothesis>=6.130.8",
"mypy>=1.15.0",
"paho-mqtt>=2.1.0",
"poethepoet>=0.34.0",
"pre-commit>=4.2.0", # https://pypi.org/project/pre-commit
"psutil>=7.0.0", # https://pypi.org/project/psutil

130
tests/test_paho.py 100644
Wyświetl plik

@ -0,0 +1,130 @@
import asyncio
import logging
import random
from unittest.mock import MagicMock, call, patch
import pytest
from paho.mqtt import client as mqtt_client
from amqtt.broker import EVENT_BROKER_CLIENT_CONNECTED, EVENT_BROKER_CLIENT_DISCONNECTED, EVENT_BROKER_PRE_START, \
EVENT_BROKER_POST_START
from amqtt.client import MQTTClient
from amqtt.mqtt.constants import QOS_1, QOS_2
logger = logging.getLogger(__name__)
paho_logger = logging.getLogger("paho_client")
# monkey patch MagicMock
# taken from https://stackoverflow.com/questions/51394411/python-object-magicmock-cant-be-used-in-await-expression
async def async_magic():
pass
MagicMock.__await__ = lambda _: async_magic().__await__()
@pytest.mark.asyncio
async def test_paho_connect(broker, mock_plugin_manager):
test_complete = asyncio.Event()
host = "localhost"
port = 1883
client_id = f'python-mqtt-{random.randint(0, 1000)}'
def on_connect(client, userdata, flags, rc, properties=None):
assert rc == 0, f"Connection failed with result code {rc}"
client.disconnect()
def on_disconnect(client, userdata, flags, rc, properties=None):
assert rc == 0, f"Disconnect failed with result code {rc}"
test_complete.set()
test_client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2, client_id=client_id)
test_client.enable_logger(paho_logger)
test_client.on_connect = on_connect
test_client.on_disconnect = on_disconnect
test_client.connect(host, port)
test_client.loop_start()
await asyncio.wait_for(test_complete.wait(), timeout=5)
await asyncio.sleep(0.1)
broker.plugins_manager.assert_has_calls(
[
call.fire_event(
EVENT_BROKER_CLIENT_CONNECTED,
client_id=client_id,
),
call.fire_event(
EVENT_BROKER_CLIENT_DISCONNECTED,
client_id=client_id,
),
],
any_order=True,
)
test_client.loop_stop()
@pytest.mark.asyncio
async def test_paho_qos1(broker, mock_plugin_manager):
sub_client = MQTTClient()
await sub_client.connect("mqtt://127.0.0.1")
ret = await sub_client.subscribe(
[("/qos1", QOS_1),],
)
host = "localhost"
port = 1883
client_id = f'python-mqtt-{random.randint(0, 1000)}'
test_client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2, client_id=client_id)
test_client.enable_logger(paho_logger)
test_client.connect(host, port)
test_client.loop_start()
await asyncio.sleep(0.1)
test_client.publish("/qos1", "test message", qos=1)
await asyncio.sleep(0.1)
test_client.loop_stop()
message = await sub_client.deliver_message()
assert message is not None
assert message.qos == 1
assert message.topic == "/qos1"
assert message.data == b"test message"
await sub_client.disconnect()
await asyncio.sleep(0.1)
@pytest.mark.asyncio
async def test_paho_qos2(broker, mock_plugin_manager):
sub_client = MQTTClient()
await sub_client.connect("mqtt://127.0.0.1")
ret = await sub_client.subscribe(
[("/qos2", QOS_2), ],
)
host = "localhost"
port = 1883
client_id = f'python-mqtt-{random.randint(0, 1000)}'
test_client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2, client_id=client_id)
test_client.enable_logger(paho_logger)
test_client.connect(host, port)
test_client.loop_start()
await asyncio.sleep(0.1)
test_client.publish("/qos2", "test message", qos=2)
await asyncio.sleep(0.1)
test_client.loop_stop()
message = await sub_client.deliver_message()
assert message is not None
assert message.qos == 2
assert message.topic == "/qos2"
assert message.data == b"test message"
await sub_client.disconnect()
await asyncio.sleep(0.1)

11
uv.lock
Wyświetl plik

@ -29,6 +29,7 @@ dev = [
{ name = "hatch" },
{ name = "hypothesis" },
{ name = "mypy" },
{ name = "paho-mqtt" },
{ name = "poethepoet" },
{ name = "pre-commit" },
{ name = "psutil" },
@ -76,6 +77,7 @@ dev = [
{ name = "hatch", specifier = ">=1.14.1" },
{ name = "hypothesis", specifier = ">=6.130.8" },
{ name = "mypy", specifier = ">=1.15.0" },
{ name = "paho-mqtt", specifier = ">=2.1.0" },
{ name = "poethepoet", specifier = ">=0.34.0" },
{ name = "pre-commit", specifier = ">=4.2.0" },
{ name = "psutil", specifier = ">=7.0.0" },
@ -1264,6 +1266,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" },
]
[[package]]
name = "paho-mqtt"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/39/15/0a6214e76d4d32e7f663b109cf71fb22561c2be0f701d67f93950cd40542/paho_mqtt-2.1.0.tar.gz", hash = "sha256:12d6e7511d4137555a3f6ea167ae846af2c7357b10bc6fa4f7c3968fc1723834", size = 148848, upload-time = "2024-04-29T19:52:55.591Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219, upload-time = "2024-04-29T19:52:48.345Z" },
]
[[package]]
name = "passlib"
version = "1.7.4"