mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-04-20 22:13:49 +00:00
feat: Refactor binary commands and apply BLE fixes
Refactored the BinaryCommandHandler to align with the other command handlers, inheriting from CommandHandlerBase. This resolves an AttributeError and simplifies the command structure. Moved binary_commands.py into the commands module. Applied fixes to the BLE connection handler based on feedback, improving reliability on macOS and ensuring the device address is correctly handled.
This commit is contained in:
parent
c19fd166f8
commit
36727f4ea3
22 changed files with 1603 additions and 1206 deletions
|
|
@ -2,10 +2,15 @@ import asyncio
|
|||
import unittest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from meshcore.ble_cx import BLEConnection, UART_SERVICE_UUID, UART_TX_CHAR_UUID, UART_RX_CHAR_UUID
|
||||
from meshcore.ble_cx import (
|
||||
BLEConnection,
|
||||
UART_TX_CHAR_UUID,
|
||||
UART_RX_CHAR_UUID,
|
||||
)
|
||||
|
||||
|
||||
class TestBLEConnection(unittest.TestCase):
|
||||
@patch('meshcore.ble_cx.BleakClient')
|
||||
@patch("meshcore.ble_cx.BleakClient")
|
||||
def test_ble_connection_and_disconnection(self, mock_bleak_client):
|
||||
"""
|
||||
Tests the BLEConnection class for connecting and disconnecting from a BLE device.
|
||||
|
|
@ -13,7 +18,7 @@ class TestBLEConnection(unittest.TestCase):
|
|||
# Arrange
|
||||
mock_client_instance = self._get_mock_bleak_client()
|
||||
mock_bleak_client.return_value = mock_client_instance
|
||||
|
||||
|
||||
address = "00:11:22:33:44:55"
|
||||
ble_conn = BLEConnection(address=address)
|
||||
|
||||
|
|
@ -23,10 +28,12 @@ class TestBLEConnection(unittest.TestCase):
|
|||
|
||||
# Assert
|
||||
mock_client_instance.connect.assert_called_once()
|
||||
mock_client_instance.start_notify.assert_called_once_with(UART_TX_CHAR_UUID, ble_conn.handle_rx)
|
||||
mock_client_instance.start_notify.assert_called_once_with(
|
||||
UART_TX_CHAR_UUID, ble_conn.handle_rx
|
||||
)
|
||||
mock_client_instance.disconnect.assert_called_once()
|
||||
|
||||
@patch('meshcore.ble_cx.BleakClient')
|
||||
@patch("meshcore.ble_cx.BleakClient")
|
||||
def test_send_data(self, mock_bleak_client):
|
||||
"""
|
||||
Tests the send method of the BLEConnection class.
|
||||
|
|
@ -34,7 +41,7 @@ class TestBLEConnection(unittest.TestCase):
|
|||
# Arrange
|
||||
mock_client_instance = self._get_mock_bleak_client()
|
||||
mock_bleak_client.return_value = mock_client_instance
|
||||
|
||||
|
||||
address = "00:11:22:33:44:55"
|
||||
ble_conn = BLEConnection(address=address)
|
||||
asyncio.run(ble_conn.connect())
|
||||
|
|
@ -44,7 +51,9 @@ class TestBLEConnection(unittest.TestCase):
|
|||
asyncio.run(ble_conn.send(data_to_send))
|
||||
|
||||
# Assert
|
||||
ble_conn.rx_char.write_gatt_char.assert_called_once_with(ble_conn.rx_char, data_to_send, response=False)
|
||||
ble_conn.rx_char.write_gatt_char.assert_called_once_with(
|
||||
ble_conn.rx_char, data_to_send, response=False
|
||||
)
|
||||
|
||||
def _get_mock_bleak_client(self):
|
||||
"""
|
||||
|
|
@ -60,12 +69,13 @@ class TestBLEConnection(unittest.TestCase):
|
|||
mock_service = MagicMock()
|
||||
mock_char = MagicMock()
|
||||
mock_char.uuid = UART_RX_CHAR_UUID
|
||||
mock_char.write_gatt_char = mock_client.write_gatt_char
|
||||
|
||||
mock_char.write_gatt_char = mock_client.write_gatt_char
|
||||
|
||||
mock_service.get_characteristic.return_value = mock_char
|
||||
mock_client.services.get_service.return_value = mock_service
|
||||
|
||||
|
||||
return mock_client
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import pytest
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock, patch, AsyncMock
|
||||
from unittest.mock import MagicMock, AsyncMock
|
||||
from meshcore.commands import CommandHandler
|
||||
from meshcore.events import EventType, Event
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
# Fixtures
|
||||
@pytest.fixture
|
||||
def mock_connection():
|
||||
|
|
@ -13,6 +14,7 @@ def mock_connection():
|
|||
connection.send = AsyncMock()
|
||||
return connection
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_dispatcher():
|
||||
dispatcher = MagicMock()
|
||||
|
|
@ -20,29 +22,36 @@ def mock_dispatcher():
|
|||
dispatcher.dispatch = AsyncMock()
|
||||
return dispatcher
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def command_handler(mock_connection, mock_dispatcher):
|
||||
handler = CommandHandler()
|
||||
|
||||
|
||||
async def sender(data):
|
||||
await mock_connection.send(data)
|
||||
|
||||
handler._sender_func = sender
|
||||
|
||||
|
||||
handler.dispatcher = mock_dispatcher
|
||||
return handler
|
||||
|
||||
|
||||
# Test helper
|
||||
def setup_event_response(mock_dispatcher, event_type, payload, attribute_filters=None):
|
||||
async def wait_response(requested_type, filters=None, timeout=None):
|
||||
if requested_type == event_type:
|
||||
if filters and attribute_filters:
|
||||
if not all(attribute_filters.get(key) == value for key, value in filters.items()):
|
||||
if not all(
|
||||
attribute_filters.get(key) == value
|
||||
for key, value in filters.items()
|
||||
):
|
||||
return None
|
||||
return Event(event_type, payload)
|
||||
return None
|
||||
|
||||
|
||||
mock_dispatcher.wait_for_event.side_effect = wait_response
|
||||
|
||||
|
||||
# Basic tests
|
||||
async def test_send_basic(command_handler, mock_connection):
|
||||
result = await command_handler.send(b"test_data")
|
||||
|
|
@ -50,141 +59,163 @@ async def test_send_basic(command_handler, mock_connection):
|
|||
assert result.type == EventType.OK
|
||||
assert result.payload == {}
|
||||
|
||||
|
||||
async def test_send_with_event(command_handler, mock_connection, mock_dispatcher):
|
||||
expected_payload = {"value": 42}
|
||||
setup_event_response(mock_dispatcher, EventType.OK, expected_payload)
|
||||
|
||||
|
||||
result = await command_handler.send(b"test_command", [EventType.OK])
|
||||
|
||||
|
||||
mock_connection.send.assert_called_once_with(b"test_command")
|
||||
assert result.type == EventType.OK
|
||||
assert result.payload == expected_payload
|
||||
|
||||
|
||||
async def test_send_timeout(command_handler, mock_connection, mock_dispatcher):
|
||||
mock_dispatcher.wait_for_event.side_effect = asyncio.TimeoutError
|
||||
|
||||
|
||||
result = await command_handler.send(b"test_command", [EventType.OK], timeout=0.1)
|
||||
assert result.type == EventType.ERROR
|
||||
assert result.payload == {"reason": "timeout"}
|
||||
|
||||
|
||||
# Destination validation tests
|
||||
async def test_validate_destination_bytes(command_handler, mock_connection):
|
||||
dst = b"123456789012" # 12 bytes
|
||||
await command_handler.send_msg(dst, "test message")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x02\x00\x00")
|
||||
assert b"123456" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_validate_destination_hex_string(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
dst = "0123456789abcdef"
|
||||
await command_handler.send_msg(dst, "test message")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x02\x00\x00")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_validate_destination_contact_object(command_handler, mock_connection):
|
||||
dst = {"public_key": "0123456789abcdef", "adv_name": "Test Contact"}
|
||||
await command_handler.send_msg(dst, "test message")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x02\x00\x00")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
# Command tests
|
||||
async def test_send_login(command_handler, mock_connection):
|
||||
await command_handler.send_login("0123456789abcdef", "password")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x1a")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
assert b"password" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_send_msg(command_handler, mock_connection):
|
||||
await command_handler.send_msg("0123456789abcdef", "hello")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x02\x00\x00")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
assert b"hello" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_send_cmd(command_handler, mock_connection):
|
||||
await command_handler.send_cmd("0123456789abcdef", "test_cmd")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x02\x01\x00")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
assert b"test_cmd" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
# Device settings tests
|
||||
async def test_set_name(command_handler, mock_connection):
|
||||
await command_handler.set_name("Test Device")
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x08")
|
||||
assert b"Test Device" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_set_coords(command_handler, mock_connection):
|
||||
await command_handler.set_coords(37.7749, -122.4194)
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0e")
|
||||
# Could add more detailed assertions for the byte encoding
|
||||
|
||||
|
||||
async def test_send_appstart(command_handler, mock_connection):
|
||||
await command_handler.send_appstart()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x01\x03")
|
||||
assert b"mccli" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_send_device_query(command_handler, mock_connection):
|
||||
await command_handler.send_device_query()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x16\x03")
|
||||
|
||||
|
||||
async def test_send_advert(command_handler, mock_connection):
|
||||
# Test without flood
|
||||
await command_handler.send_advert(flood=False)
|
||||
assert mock_connection.send.call_args[0][0] == b"\x07"
|
||||
|
||||
|
||||
# Test with flood
|
||||
mock_connection.reset_mock()
|
||||
await command_handler.send_advert(flood=True)
|
||||
assert mock_connection.send.call_args[0][0] == b"\x07\x01"
|
||||
|
||||
|
||||
async def test_reboot(command_handler, mock_connection):
|
||||
await command_handler.reboot()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x13reboot")
|
||||
|
||||
|
||||
async def test_get_bat(command_handler, mock_connection):
|
||||
await command_handler.get_bat()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x14")
|
||||
|
||||
|
||||
async def test_get_time(command_handler, mock_connection):
|
||||
await command_handler.get_time()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x05")
|
||||
|
||||
|
||||
async def test_set_time(command_handler, mock_connection):
|
||||
timestamp = 1620000000 # Example timestamp
|
||||
await command_handler.set_time(timestamp)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x06")
|
||||
|
||||
|
||||
async def test_set_tx_power(command_handler, mock_connection):
|
||||
await command_handler.set_tx_power(20)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0c")
|
||||
|
||||
|
||||
async def test_get_contacts(command_handler, mock_connection):
|
||||
await command_handler.get_contacts()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x04")
|
||||
|
||||
|
||||
async def test_reset_path(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
await command_handler.reset_path(dst)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0D")
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0d")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_share_contact(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
await command_handler.share_contact(dst)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x10")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_export_contact(command_handler, mock_connection):
|
||||
# Test exporting all contacts
|
||||
await command_handler.export_contact()
|
||||
assert mock_connection.send.call_args[0][0] == b"\x11"
|
||||
|
||||
|
||||
# Test exporting specific contact
|
||||
mock_connection.reset_mock()
|
||||
dst = "0123456789abcdef"
|
||||
|
|
@ -192,20 +223,23 @@ async def test_export_contact(command_handler, mock_connection):
|
|||
assert mock_connection.send.call_args[0][0].startswith(b"\x11")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_remove_contact(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
await command_handler.remove_contact(dst)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0f")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_get_msg(command_handler, mock_connection):
|
||||
await command_handler.get_msg()
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0A")
|
||||
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0a")
|
||||
|
||||
# Test with custom timeout
|
||||
mock_connection.reset_mock()
|
||||
await command_handler.get_msg(timeout=5.0)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0A")
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x0a")
|
||||
|
||||
|
||||
async def test_send_logout(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
|
|
@ -213,65 +247,74 @@ async def test_send_logout(command_handler, mock_connection):
|
|||
assert mock_connection.send.call_args[0][0].startswith(b"\x1d")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_send_statusreq(command_handler, mock_connection):
|
||||
dst = "0123456789abcdef"
|
||||
await command_handler.send_statusreq(dst)
|
||||
assert mock_connection.send.call_args[0][0].startswith(b"\x1b")
|
||||
assert b"\x01\x23\x45\x67\x89\xab" in mock_connection.send.call_args[0][0]
|
||||
|
||||
|
||||
async def test_send_trace(command_handler, mock_connection):
|
||||
# Test with minimal parameters
|
||||
await command_handler.send_trace()
|
||||
first_call = mock_connection.send.call_args[0][0]
|
||||
assert first_call.startswith(b"\x24") # 36 in decimal = 0x24 in hex
|
||||
|
||||
|
||||
# Test with all parameters
|
||||
mock_connection.reset_mock()
|
||||
await command_handler.send_trace(
|
||||
auth_code=12345,
|
||||
tag=67890,
|
||||
flags=1,
|
||||
path="01,23,45"
|
||||
auth_code=12345, tag=67890, flags=1, path="01,23,45"
|
||||
)
|
||||
second_call = mock_connection.send.call_args[0][0]
|
||||
assert second_call.startswith(b"\x24")
|
||||
|
||||
async def test_send_with_multiple_expected_events_returns_first_completed(command_handler, mock_connection, mock_dispatcher):
|
||||
|
||||
async def test_send_with_multiple_expected_events_returns_first_completed(
|
||||
command_handler, mock_connection, mock_dispatcher
|
||||
):
|
||||
# Setup the dispatcher to return an ERROR event
|
||||
error_payload = {"reason": "command_failed"}
|
||||
|
||||
|
||||
async def simulate_error_event(*args, **kwargs):
|
||||
# Simulate an ERROR event being returned
|
||||
return Event(EventType.ERROR, error_payload)
|
||||
|
||||
|
||||
# Patch the wait_for_event method to return our simulated event
|
||||
mock_dispatcher.wait_for_event.side_effect = simulate_error_event
|
||||
|
||||
|
||||
# Call send with both OK and ERROR in the expected_events list, with OK first
|
||||
result = await command_handler.send(b"test_command", [EventType.OK, EventType.ERROR])
|
||||
|
||||
result = await command_handler.send(
|
||||
b"test_command", [EventType.OK, EventType.ERROR]
|
||||
)
|
||||
|
||||
# Verify the command was sent
|
||||
mock_connection.send.assert_called_once_with(b"test_command")
|
||||
|
||||
|
||||
# Verify that even though OK was listed first, the ERROR event was returned
|
||||
assert result.type == EventType.ERROR
|
||||
assert result.payload == error_payload
|
||||
|
||||
|
||||
# Channel command tests
|
||||
async def test_get_channel(command_handler, mock_connection):
|
||||
await command_handler.get_channel(3)
|
||||
assert mock_connection.send.call_args[0][0] == b"\x1f\x03"
|
||||
|
||||
|
||||
async def test_set_channel(command_handler, mock_connection):
|
||||
channel_secret = bytes(range(16)) # 16 bytes: 0x00, 0x01, ..., 0x0f
|
||||
await command_handler.set_channel(5, "MyChannel", channel_secret)
|
||||
|
||||
|
||||
expected_data = b"\x20\x05" # CMD_SET_CHANNEL + channel_idx=5
|
||||
expected_data += b"MyChannel" + b"\x00" * (32 - len("MyChannel")) # 32-byte padded name
|
||||
expected_data += b"MyChannel" + b"\x00" * (
|
||||
32 - len("MyChannel")
|
||||
) # 32-byte padded name
|
||||
expected_data += channel_secret # 16-byte secret
|
||||
|
||||
|
||||
assert mock_connection.send.call_args[0][0] == expected_data
|
||||
|
||||
|
||||
async def test_set_channel_invalid_secret_length(command_handler):
|
||||
with pytest.raises(ValueError, match="Channel secret must be exactly 16 bytes"):
|
||||
await command_handler.set_channel(1, "Test", b"tooshort")
|
||||
await command_handler.set_channel(1, "Test", b"tooshort")
|
||||
|
|
|
|||
|
|
@ -1,127 +1,129 @@
|
|||
import pytest
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock, AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from meshcore.events import EventDispatcher, EventType, Event
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dispatcher():
|
||||
return EventDispatcher()
|
||||
|
||||
|
||||
async def test_subscribe_with_attribute_filter(dispatcher):
|
||||
callback = MagicMock()
|
||||
|
||||
|
||||
# Subscribe with attribute filters
|
||||
subscription = dispatcher.subscribe(
|
||||
EventType.MSG_SENT,
|
||||
dispatcher.subscribe(
|
||||
EventType.MSG_SENT,
|
||||
callback,
|
||||
attribute_filters={"type": 1, "expected_ack": "1234"}
|
||||
attribute_filters={"type": 1, "expected_ack": "1234"},
|
||||
)
|
||||
|
||||
|
||||
# Start the dispatcher
|
||||
await dispatcher.start()
|
||||
|
||||
|
||||
try:
|
||||
# Dispatch event that should NOT match (wrong type)
|
||||
await dispatcher.dispatch(Event(
|
||||
EventType.MSG_SENT,
|
||||
{"some": "data"},
|
||||
{"type": 2, "expected_ack": "1234"}
|
||||
))
|
||||
await dispatcher.dispatch(
|
||||
Event(
|
||||
EventType.MSG_SENT,
|
||||
{"some": "data"},
|
||||
{"type": 2, "expected_ack": "1234"},
|
||||
)
|
||||
)
|
||||
await asyncio.sleep(0.1) # Allow processing
|
||||
|
||||
|
||||
# Callback should NOT have been called
|
||||
assert callback.call_count == 0
|
||||
|
||||
|
||||
# Dispatch event that should match all filters
|
||||
await dispatcher.dispatch(Event(
|
||||
EventType.MSG_SENT,
|
||||
{"some": "data"},
|
||||
{"type": 1, "expected_ack": "1234"}
|
||||
))
|
||||
await dispatcher.dispatch(
|
||||
Event(
|
||||
EventType.MSG_SENT,
|
||||
{"some": "data"},
|
||||
{"type": 1, "expected_ack": "1234"},
|
||||
)
|
||||
)
|
||||
await asyncio.sleep(0.1) # Allow processing
|
||||
|
||||
|
||||
# Callback should have been called once
|
||||
assert callback.call_count == 1
|
||||
|
||||
|
||||
finally:
|
||||
await dispatcher.stop()
|
||||
|
||||
|
||||
async def test_wait_for_event_with_attribute_filter(dispatcher):
|
||||
await dispatcher.start()
|
||||
|
||||
|
||||
try:
|
||||
future_event = asyncio.create_task(
|
||||
dispatcher.wait_for_event(
|
||||
EventType.ACK,
|
||||
attribute_filters={"code": "1234"},
|
||||
timeout=3.0
|
||||
EventType.ACK, attribute_filters={"code": "1234"}, timeout=3.0
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
await dispatcher.dispatch(Event(
|
||||
EventType.ACK,
|
||||
{"some": "data"},
|
||||
{"code": "5678"}
|
||||
))
|
||||
|
||||
|
||||
await dispatcher.dispatch(
|
||||
Event(EventType.ACK, {"some": "data"}, {"code": "5678"})
|
||||
)
|
||||
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
await dispatcher.dispatch(Event(
|
||||
EventType.ACK,
|
||||
{"ack": "data"},
|
||||
{"code": "1234"}
|
||||
))
|
||||
|
||||
|
||||
await dispatcher.dispatch(
|
||||
Event(EventType.ACK, {"ack": "data"}, {"code": "1234"})
|
||||
)
|
||||
|
||||
result = await asyncio.wait_for(future_event, 3.0)
|
||||
|
||||
|
||||
assert result is not None
|
||||
assert result.type == EventType.ACK
|
||||
assert result.attributes["code"] == "1234"
|
||||
assert result.payload == {"ack": "data"}
|
||||
|
||||
|
||||
finally:
|
||||
await dispatcher.stop()
|
||||
|
||||
|
||||
async def test_wait_for_event_timeout_with_filter(dispatcher):
|
||||
await dispatcher.start()
|
||||
|
||||
|
||||
try:
|
||||
# Wait for an event that won't arrive
|
||||
result = await dispatcher.wait_for_event(
|
||||
EventType.ACK,
|
||||
attribute_filters={"code": "1234"},
|
||||
timeout=0.1
|
||||
EventType.ACK, attribute_filters={"code": "1234"}, timeout=0.1
|
||||
)
|
||||
|
||||
|
||||
# Should get None due to timeout
|
||||
assert result is None
|
||||
|
||||
|
||||
finally:
|
||||
await dispatcher.stop()
|
||||
|
||||
|
||||
async def test_event_init_with_kwargs():
|
||||
# Test creating an event with keyword attributes
|
||||
event = Event(EventType.ACK, {"data": "value"}, code="1234", status="ok")
|
||||
|
||||
|
||||
assert event.type == EventType.ACK
|
||||
assert event.payload == {"data": "value"}
|
||||
assert event.attributes == {"code": "1234", "status": "ok"}
|
||||
|
||||
|
||||
async def test_channel_info_event():
|
||||
# Test CHANNEL_INFO event type
|
||||
channel_payload = {
|
||||
"channel_idx": 3,
|
||||
"channel_name": "TestChannel",
|
||||
"channel_secret": b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
|
||||
"channel_secret": b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10",
|
||||
}
|
||||
|
||||
|
||||
event = Event(EventType.CHANNEL_INFO, channel_payload)
|
||||
|
||||
|
||||
assert event.type == EventType.CHANNEL_INFO
|
||||
assert event.payload["channel_idx"] == 3
|
||||
assert event.payload["channel_name"] == "TestChannel"
|
||||
assert len(event.payload["channel_secret"]) == 16
|
||||
assert len(event.payload["channel_secret"]) == 16
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue