amqtt/tests/mqtt/protocol/test_handler.py

499 wiersze
20 KiB
Python
Czysty Zwykły widok Historia

2015-09-12 12:47:36 +00:00
# Copyright (c) 2015 Nicolas JOUANIN
#
# See the file license.txt for copying permission.
import asyncio
2015-09-13 20:36:22 +00:00
import logging
2015-11-01 20:55:24 +00:00
import random
import unittest
from amqtt.adapters import StreamReaderAdapter, StreamWriterAdapter
2021-03-27 12:16:42 +00:00
from amqtt.mqtt.constants import QOS_0, QOS_1, QOS_2
from amqtt.mqtt.protocol.handler import ProtocolHandler
2021-03-27 12:16:42 +00:00
from amqtt.mqtt.puback import PubackPacket
from amqtt.mqtt.pubcomp import PubcompPacket
from amqtt.mqtt.publish import PublishPacket
2021-03-27 12:16:42 +00:00
from amqtt.mqtt.pubrec import PubrecPacket
from amqtt.mqtt.pubrel import PubrelPacket
from amqtt.plugins.manager import PluginManager
from amqtt.session import (
IncomingApplicationMessage,
OutgoingApplicationMessage,
Session,
)
formatter = "[%(asctime)s] %(name)s {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
2015-09-15 19:47:42 +00:00
logging.basicConfig(level=logging.DEBUG, format=formatter)
2015-09-13 20:36:22 +00:00
log = logging.getLogger(__name__)
2015-11-01 20:55:24 +00:00
def rand_packet_id():
return random.randint(0, 65535)
2015-09-13 20:36:22 +00:00
def adapt(reader, writer):
return StreamReaderAdapter(reader), StreamWriterAdapter(writer)
2015-09-12 12:47:36 +00:00
class ProtocolHandlerTest(unittest.TestCase):
def setUp(self):
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.plugin_manager = PluginManager("amqtt.test.plugins", context=None)
2015-09-12 12:47:36 +00:00
2015-09-13 20:36:22 +00:00
def tearDown(self):
self.loop.close()
2015-09-12 12:47:36 +00:00
def test_init_handler(self):
Session()
handler = ProtocolHandler(self.plugin_manager)
assert handler.session is None
assert handler._loop is self.loop
2015-09-13 20:36:22 +00:00
self.check_empty_waiters(handler)
2015-09-12 13:28:40 +00:00
def test_start_stop(self):
async def server_mock(reader, writer) -> None:
2015-09-12 13:28:40 +00:00
pass
async def test_coro() -> None:
2015-09-14 20:08:14 +00:00
try:
s = Session()
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
handler = ProtocolHandler(self.plugin_manager)
handler.attach(s, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(handler, s)
await self.stop_handler(handler, s)
2015-09-14 20:08:14 +00:00
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:08:14 +00:00
future.set_exception(ae)
2015-09-13 20:36:22 +00:00
future = asyncio.Future()
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-13 20:36:22 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()
2015-09-13 20:36:22 +00:00
def test_publish_qos0(self):
async def server_mock(reader, writer) -> None:
2015-09-14 19:18:08 +00:00
try:
2020-12-31 00:16:45 +00:00
packet = await PublishPacket.from_stream(reader)
assert packet.variable_header.topic_name == "/topic"
assert packet.qos == QOS_0
assert packet.packet_id is None
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 19:18:08 +00:00
future.set_exception(ae)
2015-09-13 20:36:22 +00:00
async def test_coro() -> None:
2015-09-14 20:08:14 +00:00
try:
s = Session()
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
handler = ProtocolHandler(self.plugin_manager)
handler.attach(s, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(handler, s)
message = await handler.mqtt_publish(
"/topic",
b"test_data",
QOS_0,
False,
)
assert isinstance(message, OutgoingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is None
assert message.pubrec_packet is None
assert message.pubrel_packet is None
assert message.pubcomp_packet is None
2020-12-31 00:16:45 +00:00
await self.stop_handler(handler, s)
2015-09-14 20:08:14 +00:00
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:08:14 +00:00
future.set_exception(ae)
2015-09-13 20:36:22 +00:00
future = asyncio.Future()
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-13 20:36:22 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
2015-09-14 20:31:16 +00:00
if future.exception():
raise future.exception()
def test_publish_qos1(self):
async def server_mock(reader, writer) -> None:
2020-12-31 00:16:45 +00:00
packet = await PublishPacket.from_stream(reader)
2015-09-14 20:31:16 +00:00
try:
assert packet.variable_header.topic_name == "/topic"
assert packet.qos == QOS_1
assert packet.packet_id is not None
assert packet.packet_id in self.session.inflight_out
assert packet.packet_id in self.handler._puback_waiters
2015-09-23 19:18:09 +00:00
puback = PubackPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await puback.to_stream(writer)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:31:16 +00:00
future.set_exception(ae)
async def test_coro() -> None:
2015-09-14 20:31:16 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(self.handler, self.session)
message = await self.handler.mqtt_publish(
"/topic",
b"test_data",
QOS_1,
False,
)
assert isinstance(message, OutgoingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is not None
assert message.pubrec_packet is None
assert message.pubrel_packet is None
assert message.pubcomp_packet is None
2020-12-31 00:16:45 +00:00
await self.stop_handler(self.handler, self.session)
2015-09-14 20:31:16 +00:00
if not future.done():
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:31:16 +00:00
future.set_exception(ae)
2015-09-14 20:31:16 +00:00
self.handler = None
self.session = Session()
future = asyncio.Future()
2015-09-14 20:31:16 +00:00
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-14 20:31:16 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
2015-09-14 20:56:22 +00:00
if future.exception():
raise future.exception()
def test_publish_qos2(self):
async def server_mock(reader, writer) -> None:
2015-09-14 20:56:22 +00:00
try:
2020-12-31 00:16:45 +00:00
packet = await PublishPacket.from_stream(reader)
assert packet.topic_name == "/topic"
assert packet.qos == QOS_2
assert packet.packet_id is not None
assert packet.packet_id in self.session.inflight_out
assert packet.packet_id in self.handler._pubrec_waiters
2015-09-14 20:56:22 +00:00
pubrec = PubrecPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await pubrec.to_stream(writer)
2015-09-14 20:56:22 +00:00
2020-12-31 00:16:45 +00:00
await PubrelPacket.from_stream(reader)
assert packet.packet_id in self.handler._pubcomp_waiters
2015-09-14 20:56:22 +00:00
pubcomp = PubcompPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await pubcomp.to_stream(writer)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:56:22 +00:00
future.set_exception(ae)
async def test_coro() -> None:
2015-09-14 20:56:22 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(self.handler, self.session)
message = await self.handler.mqtt_publish(
"/topic",
b"test_data",
QOS_2,
False,
)
assert isinstance(message, OutgoingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is None
assert message.pubrec_packet is not None
assert message.pubrel_packet is not None
assert message.pubcomp_packet is not None
2020-12-31 00:16:45 +00:00
await self.stop_handler(self.handler, self.session)
2015-09-14 20:56:22 +00:00
if not future.done():
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-14 20:56:22 +00:00
future.set_exception(ae)
2015-09-14 20:56:22 +00:00
self.handler = None
self.session = Session()
future = asyncio.Future()
2015-09-14 20:56:22 +00:00
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-14 20:56:22 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
2015-09-14 19:18:08 +00:00
if future.exception():
raise future.exception()
2015-09-13 20:36:22 +00:00
2015-09-15 19:31:07 +00:00
def test_receive_qos0(self):
async def server_mock(reader, writer) -> None:
packet = PublishPacket.build(
"/topic",
b"test_data",
rand_packet_id(),
False,
QOS_0,
False,
)
2020-12-31 00:16:45 +00:00
await packet.to_stream(writer)
2015-09-15 19:31:07 +00:00
async def test_coro() -> None:
2015-09-15 19:47:42 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(self.handler, self.session)
message = await self.handler.mqtt_deliver_next_message()
assert isinstance(message, IncomingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is None
assert message.pubrec_packet is None
assert message.pubrel_packet is None
assert message.pubcomp_packet is None
2020-12-31 00:16:45 +00:00
await self.stop_handler(self.handler, self.session)
2015-09-15 19:47:42 +00:00
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-15 19:47:42 +00:00
future.set_exception(ae)
2015-09-15 21:17:55 +00:00
self.handler = None
self.session = Session()
future = asyncio.Future()
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-15 19:47:42 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()
def test_receive_qos1(self):
async def server_mock(reader, writer) -> None:
2015-09-15 19:47:42 +00:00
try:
packet = PublishPacket.build(
"/topic",
b"test_data",
rand_packet_id(),
False,
QOS_1,
False,
)
2020-12-31 00:16:45 +00:00
await packet.to_stream(writer)
puback = await PubackPacket.from_stream(reader)
assert puback is not None
assert packet.packet_id == puback.packet_id
2015-09-15 21:17:55 +00:00
except Exception as ae:
future.set_exception(ae)
async def test_coro() -> None:
2015-09-15 21:17:55 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-29 20:28:05 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(self.handler, self.session)
message = await self.handler.mqtt_deliver_next_message()
assert isinstance(message, IncomingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is not None
assert message.pubrec_packet is None
assert message.pubrel_packet is None
assert message.pubcomp_packet is None
2020-12-31 00:16:45 +00:00
await self.stop_handler(self.handler, self.session)
2015-09-15 21:17:55 +00:00
future.set_result(True)
except Exception as ae:
future.set_exception(ae)
self.handler = None
self.session = Session()
future = asyncio.Future()
self.event = asyncio.Event()
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-15 21:17:55 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()
def test_receive_qos2(self):
async def server_mock(reader, writer) -> None:
2015-09-15 21:17:55 +00:00
try:
packet = PublishPacket.build(
"/topic",
b"test_data",
rand_packet_id(),
False,
QOS_2,
False,
)
2020-12-31 00:16:45 +00:00
await packet.to_stream(writer)
pubrec = await PubrecPacket.from_stream(reader)
assert pubrec is not None
assert packet.packet_id == pubrec.packet_id
assert packet.packet_id in self.handler._pubrel_waiters
2015-09-15 21:17:55 +00:00
pubrel = PubrelPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await pubrel.to_stream(writer)
pubcomp = await PubcompPacket.from_stream(reader)
assert pubcomp is not None
assert packet.packet_id == pubcomp.packet_id
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-15 19:47:42 +00:00
future.set_exception(ae)
async def test_coro() -> None:
2015-09-15 19:31:07 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.start_handler(self.handler, self.session)
message = await self.handler.mqtt_deliver_next_message()
assert isinstance(message, IncomingApplicationMessage)
assert message.publish_packet is not None
assert message.puback_packet is None
assert message.pubrec_packet is not None
assert message.pubrel_packet is not None
assert message.pubcomp_packet is not None
2020-12-31 00:16:45 +00:00
await self.stop_handler(self.handler, self.session)
2015-09-15 19:31:07 +00:00
future.set_result(True)
2015-09-15 21:17:55 +00:00
except Exception as ae:
2015-09-15 19:31:07 +00:00
future.set_exception(ae)
2015-09-15 21:17:55 +00:00
self.handler = None
self.session = Session()
future = asyncio.Future()
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-15 19:31:07 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()
2020-12-31 00:16:45 +00:00
async def start_handler(self, handler, session):
2015-09-14 20:08:14 +00:00
self.check_empty_waiters(handler)
self.check_no_message(session)
2020-12-31 00:16:45 +00:00
await handler.start()
2021-03-06 17:37:23 +00:00
assert handler._reader_ready
2015-09-13 20:36:22 +00:00
2020-12-31 00:16:45 +00:00
async def stop_handler(self, handler, session):
await handler.stop()
2021-03-06 17:37:23 +00:00
assert handler._reader_stopped
2015-09-14 20:08:14 +00:00
self.check_empty_waiters(handler)
self.check_no_message(session)
def check_empty_waiters(self, handler):
assert not handler._puback_waiters
assert not handler._pubrec_waiters
assert not handler._pubrel_waiters
assert not handler._pubcomp_waiters
2015-09-14 20:08:14 +00:00
def check_no_message(self, session):
assert not session.inflight_out
assert not session.inflight_in
2015-09-30 19:22:46 +00:00
def test_publish_qos1_retry(self):
async def server_mock(reader, writer) -> None:
2020-12-31 00:16:45 +00:00
packet = await PublishPacket.from_stream(reader)
2015-09-30 19:22:46 +00:00
try:
assert packet.topic_name == "/topic"
assert packet.qos == QOS_1
assert packet.packet_id is not None
assert packet.packet_id in self.session.inflight_out
assert packet.packet_id in self.handler._puback_waiters
2015-09-30 19:22:46 +00:00
puback = PubackPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await puback.to_stream(writer)
2015-09-30 19:22:46 +00:00
except Exception as ae:
future.set_exception(ae)
async def test_coro() -> None:
2015-09-30 19:22:46 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-30 19:22:46 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.handler.start()
await self.stop_handler(self.handler, self.session)
2015-09-30 19:22:46 +00:00
if not future.done():
future.set_result(True)
except Exception as ae:
future.set_exception(ae)
2015-09-30 19:22:46 +00:00
self.handler = None
self.session = Session()
message = OutgoingApplicationMessage(1, "/topic", QOS_1, b"test_data", False)
message.publish_packet = PublishPacket.build(
"/topic",
b"test_data",
rand_packet_id(),
False,
QOS_1,
False,
)
2015-09-30 19:22:46 +00:00
self.session.inflight_out[1] = message
future = asyncio.Future()
2015-09-30 19:22:46 +00:00
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-30 19:22:46 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()
def test_publish_qos2_retry(self):
async def server_mock(reader, writer) -> None:
2015-09-30 19:22:46 +00:00
try:
2020-12-31 00:16:45 +00:00
packet = await PublishPacket.from_stream(reader)
assert packet.topic_name == "/topic"
assert packet.qos == QOS_2
assert packet.packet_id is not None
assert packet.packet_id in self.session.inflight_out
assert packet.packet_id in self.handler._pubrec_waiters
2015-09-30 19:22:46 +00:00
pubrec = PubrecPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await pubrec.to_stream(writer)
2015-09-30 19:22:46 +00:00
2020-12-31 00:16:45 +00:00
await PubrelPacket.from_stream(reader)
assert packet.packet_id in self.handler._pubcomp_waiters
2015-09-30 19:22:46 +00:00
pubcomp = PubcompPacket.build(packet.packet_id)
2020-12-31 00:16:45 +00:00
await pubcomp.to_stream(writer)
2015-09-30 19:22:46 +00:00
except Exception as ae:
future.set_exception(ae)
async def test_coro() -> None:
2015-09-30 19:22:46 +00:00
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
2015-09-30 19:22:46 +00:00
reader_adapted, writer_adapted = adapt(reader, writer)
self.handler = ProtocolHandler(self.plugin_manager)
self.handler.attach(self.session, reader_adapted, writer_adapted)
2020-12-31 00:16:45 +00:00
await self.handler.start()
await self.stop_handler(self.handler, self.session)
2015-09-30 19:22:46 +00:00
if not future.done():
future.set_result(True)
except Exception as ae:
future.set_exception(ae)
2015-09-30 19:22:46 +00:00
self.handler = None
self.session = Session()
message = OutgoingApplicationMessage(1, "/topic", QOS_2, b"test_data", False)
message.publish_packet = PublishPacket.build(
"/topic",
b"test_data",
rand_packet_id(),
False,
QOS_2,
False,
)
2015-09-30 19:22:46 +00:00
self.session.inflight_out[1] = message
future = asyncio.Future()
2015-09-30 19:22:46 +00:00
coro = asyncio.start_server(server_mock, "127.0.0.1", 8888)
2015-09-30 19:22:46 +00:00
server = self.loop.run_until_complete(coro)
self.loop.run_until_complete(test_coro())
server.close()
self.loop.run_until_complete(server.wait_closed())
if future.exception():
raise future.exception()