Skip to content

Commit 641e4ef

Browse files
committed
Fix ignore test
1 parent 3895811 commit 641e4ef

File tree

3 files changed

+133
-103
lines changed

3 files changed

+133
-103
lines changed

tests/mqtt_util.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Utilities for testing MQTT."""
2+
import asyncio
3+
from collections.abc import Callable
4+
import datetime
5+
import json
6+
from unittest.mock import MagicMock, Mock
7+
8+
from aiomqtt import Client
9+
10+
from deebot_client.event_bus import EventBus
11+
from deebot_client.models import DeviceInfo
12+
from deebot_client.mqtt_client import MqttClient, SubscriberInfo
13+
14+
15+
async def verify_subscribe(
16+
test_client: Client, device_info: DeviceInfo, mock: Mock, *, expected_called: bool
17+
) -> None:
18+
command = "test"
19+
data = json.dumps({"test": str(datetime.datetime.now())}).encode("utf-8")
20+
topic = f"iot/atr/{command}/{device_info.did}/{device_info.get_class}/{device_info.resource}/j"
21+
await test_client.publish(topic, data)
22+
23+
await asyncio.sleep(0.1)
24+
if expected_called:
25+
mock.assert_called_with(command, data)
26+
else:
27+
mock.assert_not_called()
28+
29+
mock.reset_mock()
30+
31+
32+
async def subscribe(
33+
mqtt_client: MqttClient, device_info: DeviceInfo
34+
) -> tuple[Mock, Mock, Callable[[], None]]:
35+
events = Mock(spec=EventBus)
36+
callback = MagicMock()
37+
unsubscribe = await mqtt_client.subscribe(
38+
SubscriberInfo(device_info, events, callback)
39+
)
40+
await asyncio.sleep(0.1)
41+
return (events, callback, unsubscribe)

tests/test_mqtt_client.py

Lines changed: 13 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
from collections.abc import Callable
32
import datetime
43
import json
54
import logging
@@ -16,43 +15,11 @@
1615
from deebot_client.commands.json.battery import GetBattery
1716
from deebot_client.commands.json.volume import SetVolume
1817
from deebot_client.const import DataType
19-
from deebot_client.event_bus import EventBus
2018
from deebot_client.exceptions import AuthenticationError
2119
from deebot_client.models import Configuration, DeviceInfo
22-
from deebot_client.mqtt_client import MqttClient, MqttConfiguration, SubscriberInfo
20+
from deebot_client.mqtt_client import MqttClient, MqttConfiguration
2321

24-
from .fixtures.mqtt_server import MqttServer
25-
26-
_WAITING_AFTER_RESTART = 30
27-
28-
29-
async def _verify_subscribe(
30-
test_client: Client, device_info: DeviceInfo, mock: Mock, *, expected_called: bool
31-
) -> None:
32-
command = "test"
33-
data = json.dumps({"test": str(datetime.datetime.now())}).encode("utf-8")
34-
topic = f"iot/atr/{command}/{device_info.did}/{device_info.get_class}/{device_info.resource}/j"
35-
await test_client.publish(topic, data)
36-
37-
await asyncio.sleep(0.1)
38-
if expected_called:
39-
mock.assert_called_with(command, data)
40-
else:
41-
mock.assert_not_called()
42-
43-
mock.reset_mock()
44-
45-
46-
async def _subscribe(
47-
mqtt_client: MqttClient, device_info: DeviceInfo
48-
) -> tuple[Mock, Mock, Callable[[], None]]:
49-
events = Mock(spec=EventBus)
50-
callback = MagicMock()
51-
unsubscribe = await mqtt_client.subscribe(
52-
SubscriberInfo(device_info, events, callback)
53-
)
54-
await asyncio.sleep(0.1)
55-
return (events, callback, unsubscribe)
22+
from .mqtt_util import subscribe, verify_subscribe
5623

5724

5825
async def test_last_message_received_at(
@@ -75,63 +42,6 @@ async def test_last_message_received_at(
7542
assert mqtt_client.last_message_received_at == expected
7643

7744

78-
@pytest.mark.skip(reason="Wait for sbtinstruments/aiomqtt#232 be merged")
79-
@pytest.mark.timeout(_WAITING_AFTER_RESTART + 10)
80-
async def test_client_reconnect_on_broker_error(
81-
mqtt_client: MqttClient,
82-
mqtt_server: MqttServer,
83-
device_info: DeviceInfo,
84-
mqtt_config: MqttConfiguration,
85-
caplog: pytest.LogCaptureFixture,
86-
) -> None:
87-
(_, callback, _) = await _subscribe(mqtt_client, device_info)
88-
async with Client(
89-
hostname=mqtt_config.hostname,
90-
port=mqtt_config.port,
91-
identifier="Test-helper",
92-
tls_context=mqtt_config.ssl_context,
93-
) as client:
94-
# test client cannot be used as we restart the broker in this test
95-
await _verify_subscribe(client, device_info, callback, expected_called=True)
96-
97-
caplog.clear()
98-
mqtt_server.stop()
99-
await asyncio.sleep(0.1)
100-
101-
assert (
102-
"deebot_client.mqtt_client",
103-
logging.WARNING,
104-
"Connection lost; Reconnecting in 5 seconds ...",
105-
) in caplog.record_tuples
106-
caplog.clear()
107-
108-
mqtt_server.run()
109-
110-
expected_log_tuple = (
111-
"deebot_client.mqtt_client",
112-
logging.DEBUG,
113-
"All mqtt tasks created",
114-
)
115-
for i in range(_WAITING_AFTER_RESTART):
116-
print(f"Wait for success reconnect... {i}/{_WAITING_AFTER_RESTART}")
117-
if expected_log_tuple in caplog.record_tuples:
118-
async with Client(
119-
hostname=mqtt_config.hostname,
120-
port=mqtt_config.port,
121-
identifier="Test-helper",
122-
tls_context=mqtt_config.ssl_context,
123-
) as client:
124-
# test client cannot be used as we restart the broker in this test
125-
await _verify_subscribe(
126-
client, device_info, callback, expected_called=True
127-
)
128-
return
129-
130-
await asyncio.sleep(1)
131-
132-
pytest.fail("Reconnect failed")
133-
134-
13545
_test_MqttConfiguration_data = [
13646
("cn", None, "mq.ecouser.net"),
13747
("cn", "localhost", "localhost"),
@@ -182,38 +92,38 @@ def test_MqttConfiguration_hostname_none(config: Configuration) -> None:
18292
async def test_client_bot_subscription(
18393
mqtt_client: MqttClient, device_info: DeviceInfo, test_mqtt_client: Client
18494
) -> None:
185-
(_, callback, unsubscribe) = await _subscribe(mqtt_client, device_info)
95+
(_, callback, unsubscribe) = await subscribe(mqtt_client, device_info)
18696

187-
await _verify_subscribe(
97+
await verify_subscribe(
18898
test_mqtt_client, device_info, callback, expected_called=True
18999
)
190100

191101
unsubscribe()
192102
await asyncio.sleep(0.1)
193103

194-
await _verify_subscribe(
104+
await verify_subscribe(
195105
test_mqtt_client, device_info, callback, expected_called=False
196106
)
197107

198108

199109
async def test_client_reconnect_manual(
200110
mqtt_client: MqttClient, device_info: DeviceInfo, test_mqtt_client: Client
201111
) -> None:
202-
(_, callback, _) = await _subscribe(mqtt_client, device_info)
112+
(_, callback, _) = await subscribe(mqtt_client, device_info)
203113

204-
await _verify_subscribe(
114+
await verify_subscribe(
205115
test_mqtt_client, device_info, callback, expected_called=True
206116
)
207117

208118
await mqtt_client.disconnect()
209-
await _verify_subscribe(
119+
await verify_subscribe(
210120
test_mqtt_client, device_info, callback, expected_called=False
211121
)
212122

213123
await mqtt_client.connect()
214124
await asyncio.sleep(0.1)
215125

216-
await _verify_subscribe(
126+
await verify_subscribe(
217127
test_mqtt_client, device_info, callback, expected_called=True
218128
)
219129

@@ -244,7 +154,7 @@ async def test_p2p_success(
244154
test_mqtt_client: Client,
245155
) -> None:
246156
"""Test p2p workflow on SetVolume."""
247-
(events, _, _) = await _subscribe(mqtt_client, device_info)
157+
(events, _, _) = await subscribe(mqtt_client, device_info)
248158
assert len(mqtt_client._received_p2p_commands) == 0
249159

250160
command_object = Mock(spec=SetVolume)
@@ -293,7 +203,7 @@ async def test_p2p_not_supported(
293203
caplog: pytest.LogCaptureFixture,
294204
) -> None:
295205
"""Test that unsupported command will be logged."""
296-
await _subscribe(mqtt_client, device_info)
206+
await subscribe(mqtt_client, device_info)
297207
command_name: str = GetBattery.name
298208

299209
await _publish_p2p(
@@ -344,7 +254,7 @@ async def test_p2p_to_late(
344254
"""Test p2p when response comes in to late."""
345255
# reduce ttl to 1 seconds
346256
mqtt_client._received_p2p_commands = TTLCache(maxsize=60 * 60, ttl=1)
347-
await _subscribe(mqtt_client, device_info)
257+
await subscribe(mqtt_client, device_info)
348258
assert len(mqtt_client._received_p2p_commands) == 0
349259

350260
command_object = Mock(spec=SetVolume)
@@ -393,7 +303,7 @@ async def test_p2p_parse_error(
393303
caplog: pytest.LogCaptureFixture,
394304
) -> None:
395305
"""Test p2p parse error."""
396-
await _subscribe(mqtt_client, device_info)
306+
await subscribe(mqtt_client, device_info)
397307

398308
command_object = Mock(spec=SetVolume)
399309
command_name = SetVolume.name

tests/test_mqtt_client_reconnect.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import asyncio
2+
from collections.abc import Generator
3+
import logging
4+
5+
from aiomqtt import Client
6+
import pytest
7+
8+
from deebot_client.models import DeviceInfo
9+
from deebot_client.mqtt_client import MqttClient, MqttConfiguration
10+
11+
from .fixtures.mqtt_server import MqttServer
12+
from .mqtt_util import subscribe, verify_subscribe
13+
14+
_WAITING_AFTER_RESTART = 30
15+
16+
17+
@pytest.fixture
18+
def mqtt_server() -> Generator[MqttServer, None, None]:
19+
server = MqttServer()
20+
server.config.options["ports"] = {"1883/tcp": 54321}
21+
server.run()
22+
yield server
23+
server.stop()
24+
25+
26+
@pytest.mark.timeout(_WAITING_AFTER_RESTART + 10)
27+
async def test_client_reconnect_on_broker_error(
28+
mqtt_client: MqttClient,
29+
mqtt_server: MqttServer,
30+
device_info: DeviceInfo,
31+
mqtt_config: MqttConfiguration,
32+
caplog: pytest.LogCaptureFixture,
33+
) -> None:
34+
(_, callback, _) = await subscribe(mqtt_client, device_info)
35+
async with Client(
36+
hostname=mqtt_config.hostname,
37+
port=mqtt_config.port,
38+
identifier="Test-helper",
39+
tls_context=mqtt_config.ssl_context,
40+
) as client:
41+
# test client cannot be used as we restart the broker in this test
42+
await verify_subscribe(client, device_info, callback, expected_called=True)
43+
44+
caplog.clear()
45+
mqtt_server.stop()
46+
await asyncio.sleep(0.1)
47+
48+
assert (
49+
"deebot_client.mqtt_client",
50+
logging.WARNING,
51+
"Connection lost; Reconnecting in 5 seconds ...",
52+
) in caplog.record_tuples
53+
caplog.clear()
54+
55+
mqtt_server.run()
56+
57+
expected_log_tuple = (
58+
"deebot_client.mqtt_client",
59+
logging.DEBUG,
60+
"All mqtt tasks created",
61+
)
62+
for i in range(_WAITING_AFTER_RESTART):
63+
print(f"Wait for success reconnect... {i}/{_WAITING_AFTER_RESTART}")
64+
if expected_log_tuple in caplog.record_tuples:
65+
async with Client(
66+
hostname=mqtt_config.hostname,
67+
port=mqtt_config.port,
68+
identifier="Test-helper",
69+
tls_context=mqtt_config.ssl_context,
70+
) as client:
71+
# test client cannot be used as we restart the broker in this test
72+
await verify_subscribe(
73+
client, device_info, callback, expected_called=True
74+
)
75+
return
76+
77+
await asyncio.sleep(1)
78+
79+
pytest.fail("Reconnect failed")

0 commit comments

Comments
 (0)