Skip to content

Commit a2574e6

Browse files
committed
Add test on max_inflights packet
This test is currently broken, PR #698 should fix/improve the situation
1 parent 790f9db commit a2574e6

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import logging
2+
3+
import paho.mqtt.client as mqtt
4+
5+
from tests.paho_test import get_test_server_port, loop_until_keyboard_interrupt
6+
7+
def expected_payload(i: int) -> bytes:
8+
return f"message{i}".encode("utf8")
9+
10+
11+
def on_message(mqttc, obj, msg):
12+
assert msg.mid == 123, f"Invalid mid: ({msg.mid})"
13+
assert msg.topic == "pub/qos1/receive", f"Invalid topic: ({msg.topic})"
14+
assert msg.payload == expected_payload, f"Invalid payload: ({msg.payload})"
15+
assert msg.qos == 1, f"Invalid qos: ({msg.qos})"
16+
assert msg.retain is not False, f"Invalid retain: ({msg.retain})"
17+
18+
19+
def on_connect(mqttc, obj, flags, rc):
20+
assert rc == 0, f"Connect failed ({rc})"
21+
for i in range(12):
22+
mqttc.publish("topic", expected_payload(i), qos=1)
23+
24+
def on_disconnect(mqttc, rc, properties):
25+
logging.info("disconnected")
26+
mqttc.reconnect()
27+
28+
logging.basicConfig(level=logging.DEBUG)
29+
logging.info(str(mqtt))
30+
mqttc = mqtt.Client("publish-qos1-test")
31+
mqttc.max_inflight_messages_set(10)
32+
mqttc.on_connect = on_connect
33+
mqttc.on_disconnect = on_disconnect
34+
mqttc.on_message = on_message
35+
mqttc.enable_logger()
36+
37+
mqttc.connect("localhost", get_test_server_port())
38+
loop_until_keyboard_interrupt(mqttc)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Test whether a client responds to max-inflight and reconnect when max-inflight is reached
2+
3+
# The client should connect with keepalive=60, clean session set,
4+
# and client id publish-fill-inflight
5+
# The test will send a CONNACK message to the client with rc=0. Upon receiving
6+
# the CONNACK the client should verify that rc==0.
7+
# Then client should send 10 PUBLISH with QoS == 1. On client side 12 message will be
8+
# submitted, so 2 will be queued.
9+
# The test will wait 0.5 seconds after received the 10 PUBLISH. After this wait, it will
10+
# disconnect the client.
11+
# The client should re-connect and re-sent the first 10 messages.
12+
# The test will PUBACK one message, it should receive another PUBLISH.
13+
# The test will wait 0.5 seconds and expect no PUBLISH.
14+
# The test will then PUBACK all message.
15+
# The client should disconnect once everything is acked.
16+
17+
import pytest
18+
19+
import tests.paho_test as paho_test
20+
21+
def expected_payload(i: int) -> bytes:
22+
return f"message{i}"
23+
24+
connect_packet = paho_test.gen_connect("publish-qos1-test", keepalive=60)
25+
connack_packet = paho_test.gen_connack(rc=0)
26+
27+
disconnect_packet = paho_test.gen_disconnect()
28+
29+
first_connection_publishs = [
30+
paho_test.gen_publish(
31+
"topic", qos=1, mid=i+1, payload=expected_payload(i),
32+
)
33+
for i in range(10)
34+
]
35+
second_connection_publishs = [
36+
paho_test.gen_publish(
37+
# I'm not sure we should have the mid+13.
38+
# Currently on reconnection client will do two wrong thing:
39+
# * it sent more than max_inflight packet
40+
# * it re-send message both with mid = old_mid + 12 AND with mid = old_mid & dup=1
41+
"topic", qos=1, mid=i+13, payload=expected_payload(i),
42+
)
43+
for i in range(12)
44+
]
45+
second_connection_pubacks = [
46+
paho_test.gen_puback(i+13)
47+
for i in range(12)
48+
]
49+
50+
@pytest.mark.xfail
51+
def test_03_publish_fill_inflight(server_socket, start_client):
52+
start_client("03-publish-fill-inflight.py")
53+
54+
(conn, address) = server_socket.accept()
55+
conn.settimeout(10)
56+
57+
paho_test.expect_packet(conn, "connect", connect_packet)
58+
conn.send(connack_packet)
59+
60+
for packet in first_connection_publishs:
61+
paho_test.expect_packet(conn, "publish", packet)
62+
63+
paho_test.expect_no_packet(conn, 0.5)
64+
65+
conn.close()
66+
67+
(conn, address) = server_socket.accept()
68+
conn.settimeout(10)
69+
70+
paho_test.expect_packet(conn, "connect", connect_packet)
71+
conn.send(connack_packet)
72+
73+
for packet in second_connection_publishs[:10]:
74+
paho_test.expect_packet(conn, "publish", packet)
75+
76+
paho_test.expect_no_packet(conn, 0.2)
77+
78+
conn.send(second_connection_pubacks[0])
79+
paho_test.expect_packet(conn, "publish", second_connection_publishs[10])
80+
81+
paho_test.expect_no_packet(conn, 0.5)
82+
83+
for packet in second_connection_pubacks[1:11]:
84+
conn.send(packet)
85+
86+
paho_test.expect_packet(conn, "publish", second_connection_publishs[11])
87+
88+
paho_test.expect_no_packet(conn, 0.5)
89+

tests/paho_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,27 @@ def expect_packet(sock, name, expected):
8484
assert packet_matches(name, packet_recvd, expected)
8585
return True
8686

87+
def expect_no_packet(sock, delay=1):
88+
""" expect that nothing is received within given delay
89+
"""
90+
sock.settimeout(delay)
91+
try:
92+
previous_timeout = sock.gettimeout()
93+
data = sock.recv(1024)
94+
except socket.timeout:
95+
data = None
96+
finally:
97+
sock.settimeout(previous_timeout)
98+
99+
if data is not None:
100+
try:
101+
print("Received: " + to_string(data))
102+
except struct.error:
103+
print("Received (not decoded): 0x" +
104+
binascii.b2a_hex(data).decode('utf8'))
105+
106+
assert data is None, "shouldn't receive any data"
107+
87108

88109
def packet_matches(name, recvd, expected):
89110
if recvd != expected:

0 commit comments

Comments
 (0)