mirror of
https://github.com/OMGeeky/flucto-heisskleber.git
synced 2025-12-28 15:28:11 +01:00
* WIP: Added async file reader. * Async resampling and synchronization refactored. * Add async mqtt publisher. Remove queue from joint. * Add async zmq publisher and subscriber. * Modify integration tests for streaming. * Name refactoring resampler. * Added async source/sink to factory. * Refactor joint and add integration tests. * Add termcolor dev dependency * Add conosole source and sink * Add cli interface for different protocols * Removed files unfit for merge. * Fix review requests. * Restore use of $MSB_CONFIG_DIR for now. It seems that the default behaviour is not looking for .config/heisskleber * Remove version test, causing unnecessary failures.
154 lines
5.6 KiB
Python
154 lines
5.6 KiB
Python
import json
|
|
from queue import SimpleQueue
|
|
from unittest.mock import call, patch
|
|
|
|
import pytest
|
|
from paho.mqtt.client import MQTTMessage
|
|
|
|
from heisskleber.mqtt.config import MqttConf
|
|
from heisskleber.mqtt.mqtt_base import MqttBase
|
|
from heisskleber.mqtt.subscriber import MqttSubscriber
|
|
|
|
|
|
# Mock configuration for MQTT_Base
|
|
@pytest.fixture
|
|
def mock_mqtt_conf() -> MqttConf:
|
|
return MqttConf(
|
|
broker="localhost",
|
|
port=1883,
|
|
user="user",
|
|
password="passwd", # noqa: S106, this is a test password
|
|
ssl=False,
|
|
verbose=False,
|
|
qos=1,
|
|
)
|
|
|
|
|
|
# Mock the paho mqtt client
|
|
@pytest.fixture
|
|
def mock_mqtt_client():
|
|
with patch("heisskleber.mqtt.mqtt_base.mqtt_client", autospec=True) as mock:
|
|
yield mock
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_queue():
|
|
with patch("heisskleber.mqtt.subscriber.SimpleQueue", spec=SimpleQueue) as mock:
|
|
yield mock
|
|
|
|
|
|
def test_mqtt_base_intialization(mock_mqtt_client, mock_mqtt_conf):
|
|
"""Test that the intialization of the mqtt client is as expected."""
|
|
base = MqttBase(config=mock_mqtt_conf)
|
|
|
|
mock_mqtt_client.assert_called_once()
|
|
mock_mqtt_client.return_value.loop_start.assert_called_once()
|
|
mock_client_instance = mock_mqtt_client.return_value
|
|
mock_client_instance.username_pw_set.assert_called_with(mock_mqtt_conf.user, mock_mqtt_conf.password)
|
|
mock_client_instance.connect.assert_called_with(mock_mqtt_conf.broker, mock_mqtt_conf.port)
|
|
assert base.client.on_connect == base._on_connect
|
|
assert base.client.on_disconnect == base._on_disconnect
|
|
assert base.client.on_publish == base._on_publish
|
|
assert base.client.on_message == base._on_message
|
|
|
|
|
|
def test_mqtt_base_on_connect(mock_mqtt_client, mock_mqtt_conf, capsys):
|
|
base = MqttBase(config=mock_mqtt_conf)
|
|
base._on_connect(None, None, {}, 0)
|
|
captured = capsys.readouterr()
|
|
assert f"MQTT node connected to {mock_mqtt_conf.broker}:{mock_mqtt_conf.port}" in captured.out
|
|
|
|
|
|
def test_mqtt_base_on_disconnect_with_error(mock_mqtt_client, mock_mqtt_conf, capsys):
|
|
"""Assert that the mqtt client shuts down when disconnect callback is received."""
|
|
base = MqttBase(config=mock_mqtt_conf)
|
|
with pytest.raises(SystemExit):
|
|
base._on_disconnect(None, None, 1)
|
|
captured = capsys.readouterr()
|
|
assert "Killing this service" in captured.out
|
|
print(captured.out)
|
|
|
|
|
|
def test_mqtt_subscribes_single_topic(mock_mqtt_client, mock_mqtt_conf):
|
|
"""Test that the mqtt client subscribes to a single topic."""
|
|
_ = MqttSubscriber(topics="singleTopic", config=mock_mqtt_conf)
|
|
|
|
actual_calls = mock_mqtt_client.return_value.subscribe.call_args_list
|
|
assert actual_calls == [call("singleTopic", mock_mqtt_conf.qos)]
|
|
|
|
|
|
def test_mqtt_subscribes_multiple_topics(mock_mqtt_client, mock_mqtt_conf):
|
|
"""Test that the mqtt client subscribes to multiple topics passed as list.
|
|
|
|
I would love to do this via parametrization, but the call argument is built differently for single size lists and longer lists.
|
|
"""
|
|
_ = MqttSubscriber(topics=["multiple1", "multiple2"], config=mock_mqtt_conf)
|
|
|
|
actual_calls = mock_mqtt_client.return_value.subscribe.call_args_list
|
|
assert actual_calls == [
|
|
call([("multiple1", mock_mqtt_conf.qos), ("multiple2", mock_mqtt_conf.qos)]),
|
|
]
|
|
|
|
|
|
def test_mqtt_subscribes_multiple_topics_tuple(mock_mqtt_client, mock_mqtt_conf):
|
|
"""Test that the mqtt client subscribes to multiple topics passed as tuple."""
|
|
_ = MqttSubscriber(topics=("multiple1", "multiple2"), config=mock_mqtt_conf)
|
|
|
|
actual_calls = mock_mqtt_client.return_value.subscribe.call_args_list
|
|
assert actual_calls == [
|
|
call([("multiple1", mock_mqtt_conf.qos), ("multiple2", mock_mqtt_conf.qos)]),
|
|
]
|
|
|
|
|
|
def create_fake_mqtt_message(topic: bytes, payload: bytes) -> MQTTMessage:
|
|
msg = MQTTMessage()
|
|
msg.topic = topic
|
|
msg.payload = payload
|
|
return msg
|
|
|
|
|
|
def test_receive_with_message(mock_mqtt_conf: MqttConf, mock_mqtt_client, mock_queue):
|
|
"""Test the mqtt receive function with fake MQTT messages."""
|
|
topic = b"test/topic"
|
|
payload = json.dumps({"key": "value"}).encode()
|
|
fake_message = create_fake_mqtt_message(topic, payload)
|
|
|
|
mock_queue.return_value.get.side_effect = [fake_message]
|
|
subscriber = MqttSubscriber(topics=[topic.decode()], config=mock_mqtt_conf)
|
|
|
|
received_topic, received_payload = subscriber.receive()
|
|
|
|
assert received_topic == "test/topic"
|
|
assert received_payload == {"key": "value"}
|
|
|
|
|
|
def test_message_is_put_into_queue(mock_mqtt_conf: MqttConf, mock_mqtt_client, mock_queue):
|
|
"""Test that values a put into a queue when on_message callback is called."""
|
|
topic = b"test/topic"
|
|
payload = json.dumps({"key": "value"}).encode()
|
|
fake_message = create_fake_mqtt_message(topic, payload)
|
|
|
|
mock_queue.return_value.get.side_effect = [fake_message]
|
|
subscriber = MqttSubscriber(topics=[topic.decode()], config=mock_mqtt_conf)
|
|
|
|
subscriber._on_message(None, None, fake_message)
|
|
|
|
mock_queue.return_value.put.assert_called_once_with(fake_message)
|
|
|
|
|
|
def test_message_is_put_into_queue_with_actual_queue(mock_mqtt_conf, mock_mqtt_client):
|
|
"""Test that the buffering via queue works as expected."""
|
|
topic = b"test/topic"
|
|
payload = json.dumps({"key": "value"}).encode()
|
|
fake_message = create_fake_mqtt_message(topic, payload)
|
|
|
|
# mock_queue.return_value.get.side_effect = [fake_message]
|
|
subscriber = MqttSubscriber(topics=[topic.decode()], config=mock_mqtt_conf)
|
|
|
|
subscriber._on_message(None, None, fake_message)
|
|
|
|
topic, return_dict = subscriber.receive()
|
|
|
|
assert topic == "test/topic"
|
|
assert return_dict == {"key": "value"}
|