Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ jobs:
with:
CODE_FOLDER: zigpy
CACHE_VERSION: 3
PRE_COMMIT_CACHE_PATH: ~/.cache/pre-commit
PYTHON_VERSION_DEFAULT: 3.11.0
MINIMUM_COVERAGE_PERCENTAGE: 99
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
7 changes: 6 additions & 1 deletion tests/test_datastructures_cpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ async def test_semaphore(self):

with self.assertRaisesRegex(
TypeError,
"object RequestLimiter can't be used in 'await' expression",
(
# Used up until 3.14
r"object RequestLimiter can't be used in 'await' expression"
# 3.14+
r"|'RequestLimiter' object can't be awaited"
),
):
await sem

Expand Down
80 changes: 65 additions & 15 deletions tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1642,19 +1642,53 @@ async def mock_ep_get_model_info(self):
assert dev.begin_fast_polling.mock_calls == [call()]


async def test_device_flipped_cluster_warning(dev: device.Device, caplog) -> None:
"""Test that a warning is logged when a cluster is flipped."""
ep1 = dev.add_endpoint(1)
ep1.add_input_cluster(OnOff.cluster_id)
@pytest.mark.parametrize(
(
"has_input_cluster",
"has_output_cluster",
"packet_direction",
"expected_cluster_type",
),
[
# Correct cluster matching
(True, False, foundation.Direction.Server_to_Client, ClusterType.Server),
(False, True, foundation.Direction.Client_to_Server, ClusterType.Client),
# Direction flipping: only one cluster type exists, packet has wrong direction
(True, False, foundation.Direction.Client_to_Server, ClusterType.Server),
(False, True, foundation.Direction.Server_to_Client, ClusterType.Client),
# Both clusters exist: should match based on direction, no flipping
(True, True, foundation.Direction.Server_to_Client, ClusterType.Server),
(True, True, foundation.Direction.Client_to_Server, ClusterType.Client),
# Cluster doesn't exist
(False, False, foundation.Direction.Server_to_Client, None),
(False, False, foundation.Direction.Client_to_Server, None),
],
)
async def test_device_cluster_direction_flipping(
dev: device.Device,
has_input_cluster: bool,
has_output_cluster: bool,
packet_direction: foundation.Direction,
expected_cluster_type: ClusterType | None,
) -> None:
"""Test that cluster direction flipping routes messages to the correct cluster."""
ep = dev.add_endpoint(1)

ep2 = dev.add_endpoint(2)
ep2.add_output_cluster(OnOff.cluster_id)
if has_input_cluster:
input_cluster = ep.add_input_cluster(OnOff.cluster_id)
else:
input_cluster = None

if has_output_cluster:
output_cluster = ep.add_output_cluster(OnOff.cluster_id)
else:
output_cluster = None

zcl_hdr = foundation.ZCLHeader(
frame_control=foundation.FrameControl(
frame_type=foundation.FrameType.CLUSTER_COMMAND,
is_manufacturer_specific=False,
direction=foundation.Direction.Client_to_Server,
direction=packet_direction,
disable_default_response=1,
reserved=0,
),
Expand All @@ -1676,14 +1710,30 @@ async def test_device_flipped_cluster_warning(dev: device.Device, caplog) -> Non
rssi=-30,
)

# Correct
with caplog.at_level(logging.WARNING):
dev.packet_received(packet.replace(src_ep=2))
captured_result = []

original_match = dev._match_packet_endpoint_cluster

def capture_match(*args, **kwargs):
result = original_match(*args, **kwargs)
captured_result.append(result)
return result

assert "has incorrect direction" not in caplog.text
with patch.object(
dev, "_match_packet_endpoint_cluster", side_effect=capture_match
) as spy:
dev.packet_received(packet)

# Incorrect
with caplog.at_level(logging.WARNING):
dev.packet_received(packet.replace(src_ep=1))
assert spy.call_count == 1
assert len(captured_result) == 1

assert "has incorrect direction" in caplog.text
_, returned_cluster = captured_result[0]

if expected_cluster_type is None:
assert returned_cluster is None
elif expected_cluster_type is ClusterType.Server:
assert returned_cluster is input_cluster
elif expected_cluster_type is ClusterType.Client:
assert returned_cluster is output_cluster
else:
pytest.fail("Unexpected cluster type")
2 changes: 1 addition & 1 deletion zigpy/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ def _find_zcl_cluster(
),
packet,
)
LOGGER.warning(
LOGGER.debug(
(
"Cluster 0x%04x on %r has incorrect direction (got %r for %r cluster)."
" Please report this here: https://github.com/zigpy/zigpy/issues/1640"
Expand Down
Loading