1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
"""Unit test for value reader."""
import asyncio
from unittest.mock import MagicMock, patch
import pytest
from xknx import XKNX
from xknx.core import ValueReader
from xknx.dpt import DPTBinary
from xknx.telegram import GroupAddress, Telegram, TelegramDirection
from xknx.telegram.apci import GroupValueRead, GroupValueResponse, GroupValueWrite
class TestValueReader:
"""Test class for value reader."""
async def test_value_reader_read_success(self) -> None:
"""Test value reader: successful read."""
xknx = XKNX()
test_group_address = GroupAddress("0/0/1")
response_telegram = Telegram(
destination_address=test_group_address,
direction=TelegramDirection.INCOMING,
payload=GroupValueResponse(DPTBinary(1)),
)
value_reader = ValueReader(xknx, test_group_address)
# receive the response
value_reader.telegram_received(response_telegram)
# and yield the result
successful_read = await value_reader.read()
# GroupValueRead telegram is still in the queue because we are not actually processing it
assert xknx.telegrams.qsize() == 1
# Callback was removed again
assert not xknx.telegram_queue.telegram_received_cbs
# Telegram was received
assert value_reader.received_telegram == response_telegram
# successful read() returns the telegram
assert successful_read == response_telegram
@patch("logging.Logger.warning")
async def test_value_reader_read_timeout(
self, logger_warning_mock: MagicMock
) -> None:
"""Test value reader: read timeout."""
xknx = XKNX()
value_reader = ValueReader(xknx, GroupAddress("0/0/1"))
value_reader.response_received_event.wait = MagicMock(
side_effect=asyncio.TimeoutError()
)
timed_out_read = await value_reader.read()
# GroupValueRead telegram is still in the queue because we are not actually processing it
assert xknx.telegrams.qsize() == 1
# Warning was logged
logger_warning_mock.assert_called_once_with(
"Error: KNX bus did not respond in time (%s secs) to GroupValueRead request for: %s",
2.0,
GroupAddress("0/0/1"),
)
# Callback was removed again
assert not xknx.telegram_queue.telegram_received_cbs
# No telegram was received
assert value_reader.received_telegram is None
# Unsuccessful read() returns None
assert timed_out_read is None
async def test_value_reader_read_cancelled(self) -> None:
"""Test value reader: read cancelled."""
xknx = XKNX()
value_reader = ValueReader(xknx, GroupAddress("0/0/1"))
value_reader.response_received_event.wait = MagicMock(
side_effect=asyncio.CancelledError()
)
with pytest.raises(asyncio.CancelledError):
await value_reader.read()
# GroupValueRead telegram is still in the queue because we are not actually processing it
assert xknx.telegrams.qsize() == 1
# Callback was removed again
assert not xknx.telegram_queue.telegram_received_cbs
# No telegram was received
assert value_reader.received_telegram is None
async def test_value_reader_send_group_read(self) -> None:
"""Test value reader: send_group_read."""
xknx = XKNX()
value_reader = ValueReader(xknx, GroupAddress("0/0/1"))
value_reader.send_group_read()
assert xknx.telegrams.qsize() == 1
telegram = xknx.telegrams.get_nowait()
assert telegram == Telegram(
destination_address=GroupAddress("0/0/1"), payload=GroupValueRead()
)
async def test_value_reader_telegram_received(self) -> None:
"""Test value reader: telegram_received."""
xknx = XKNX()
test_group_address = GroupAddress("0/0/1")
expected_telegram_1 = Telegram(
destination_address=test_group_address,
direction=TelegramDirection.INCOMING,
payload=GroupValueResponse(DPTBinary(1)),
)
expected_telegram_2 = Telegram(
destination_address=test_group_address,
direction=TelegramDirection.INCOMING,
payload=GroupValueWrite(DPTBinary(1)),
)
telegram_wrong_address = Telegram(
destination_address=GroupAddress("0/0/2"),
direction=TelegramDirection.INCOMING,
payload=GroupValueResponse(DPTBinary(1)),
)
telegram_wrong_type = Telegram(
destination_address=test_group_address,
direction=TelegramDirection.INCOMING,
payload=GroupValueRead(),
)
value_reader = ValueReader(xknx, test_group_address)
value_reader.telegram_received(telegram_wrong_address)
assert value_reader.received_telegram is None
assert not value_reader.response_received_event.is_set()
value_reader.telegram_received(telegram_wrong_type)
assert value_reader.received_telegram is None
assert not value_reader.response_received_event.is_set()
value_reader.telegram_received(expected_telegram_1)
assert value_reader.received_telegram == expected_telegram_1
assert value_reader.response_received_event.is_set()
value_reader.telegram_received(expected_telegram_2)
assert value_reader.received_telegram == expected_telegram_2
assert value_reader.response_received_event.is_set()
|