Skip to content

Commit 201f4ea

Browse files
committed
Fix final unit tests
1 parent 4d342e1 commit 201f4ea

File tree

4 files changed

+100
-101
lines changed

4 files changed

+100
-101
lines changed

tests/application/test_requests.py

Lines changed: 30 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@
44
import zigpy.zdo
55
import zigpy.endpoint
66
import zigpy.profiles
7-
from zigpy.zdo.types import ZDOCmd
7+
import zigpy.zdo.types as zdo_t
88
from zigpy.exceptions import DeliveryError
99

1010
import zigpy_znp.types as t
1111
import zigpy_znp.config as conf
1212
import zigpy_znp.commands as c
1313
from zigpy_znp.exceptions import InvalidCommandResponse
1414

15-
from ..conftest import FORMED_DEVICES, CoroutineMock, FormedLaunchpadCC26X2R1
15+
from ..conftest import (
16+
FORMED_DEVICES,
17+
CoroutineMock,
18+
FormedLaunchpadCC26X2R1,
19+
zdo_request_matcher,
20+
serialize_zdo_command,
21+
)
1622

1723

1824
@pytest.mark.parametrize("device", FORMED_DEVICES)
@@ -177,52 +183,6 @@ async def test_request_addr_mode(device, addr, make_application, mocker):
177183
await app.shutdown()
178184

179185

180-
@pytest.mark.parametrize("device", FORMED_DEVICES)
181-
@pytest.mark.parametrize("status", [t.ZDOStatus.SUCCESS, t.ZDOStatus.TIMEOUT, None])
182-
async def test_remove(device, make_application, status, mocker):
183-
app, znp_server = make_application(server_cls=device)
184-
app._config[conf.CONF_ZNP_CONFIG][conf.CONF_ARSP_TIMEOUT] = 0.1
185-
186-
# Only zigpy>=0.29.0 has this method
187-
if hasattr(app, "_remove_device"):
188-
mocker.spy(app, "_remove_device")
189-
190-
await app.startup(auto_form=False)
191-
device = app.add_initialized_device(ieee=t.EUI64(range(8)), nwk=0xAABB)
192-
193-
responses = [c.ZDO.MgmtLeaveReq.Rsp(Status=t.Status.SUCCESS)]
194-
195-
if status is not None:
196-
responses.append(c.ZDO.MgmtLeaveRsp.Callback(Src=0x0000, Status=status))
197-
198-
# Normal ZDO leave must fail
199-
normal_remove_req = znp_server.reply_once_to(
200-
request=c.ZDO.MgmtLeaveReq.Req(
201-
DstAddr=device.nwk, IEEE=device.ieee, partial=True
202-
),
203-
responses=[
204-
c.ZDO.MgmtLeaveReq.Rsp(Status=t.Status.SUCCESS),
205-
c.ZDO.MgmtLeaveRsp.Callback(Src=device.nwk, Status=t.ZDOStatus.TIMEOUT),
206-
],
207-
)
208-
209-
# Make sure the device exists
210-
assert app.get_device(nwk=device.nwk) is device
211-
212-
await app.remove(device.ieee)
213-
await normal_remove_req
214-
215-
if hasattr(app, "_remove_device"):
216-
# Make sure the device is going to be removed
217-
assert app._remove_device.call_count == 1
218-
else:
219-
# Make sure the device is gone
220-
with pytest.raises(KeyError):
221-
app.get_device(ieee=device.ieee)
222-
223-
await app.shutdown()
224-
225-
226186
@pytest.mark.parametrize("device", FORMED_DEVICES)
227187
async def test_mrequest(device, make_application, mocker):
228188
app, znp_server = make_application(server_cls=device)
@@ -274,25 +234,6 @@ async def test_mrequest_doesnt_block(device, make_application, event_loop):
274234
await app.shutdown()
275235

276236

277-
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
278-
async def test_unimplemented_zdo_converter(device, make_application, mocker):
279-
app, znp_server = make_application(server_cls=device)
280-
await app.startup()
281-
282-
with pytest.raises(RuntimeError):
283-
await zigpy.zdo.broadcast(
284-
app,
285-
ZDOCmd.Remove_node_cache_req,
286-
0x0000,
287-
0x00,
288-
t.NWK(0x1234),
289-
t.EUI64.convert("11:22:33:44:55:66:77:88"),
290-
broadcast_address=0xFFFC,
291-
)
292-
293-
await app.shutdown()
294-
295-
296237
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
297238
async def test_broadcast(device, make_application, mocker):
298239
app, znp_server = make_application(server_cls=device)
@@ -595,28 +536,46 @@ def set_route_discovered(req):
595536
return c.ZDO.ExtRouteDisc.Rsp(Status=t.Status.SUCCESS)
596537

597538
znp_server.reply_to(
598-
c.ZDO.ExtRouteChk.Req(Dst=device.nwk, partial=True),
539+
request=c.ZDO.ExtRouteChk.Req(Dst=device.nwk, partial=True),
599540
responses=[route_replier],
600541
override=True,
601542
)
602543

603544
was_route_discovered = znp_server.reply_once_to(
604-
c.ZDO.ExtRouteDisc.Req(
545+
request=c.ZDO.ExtRouteDisc.Req(
605546
Dst=device.nwk, Options=c.zdo.RouteDiscoveryOptions.UNICAST, partial=True
606547
),
607548
responses=[set_route_discovered],
608549
)
609550

610551
zdo_req = znp_server.reply_once_to(
611-
c.ZDO.ActiveEpReq.Req(DstAddr=device.nwk, NWKAddrOfInterest=device.nwk),
552+
request=zdo_request_matcher(
553+
dst_addr=t.AddrModeAddress(t.AddrMode.NWK, device.nwk),
554+
command_id=zdo_t.ZDOCmd.Active_EP_req,
555+
TSN=7,
556+
zdo_NWKAddrOfInterest=device.nwk,
557+
),
612558
responses=[
613-
c.ZDO.ActiveEpReq.Rsp(Status=t.Status.SUCCESS),
614559
c.ZDO.ActiveEpRsp.Callback(
615560
Src=device.nwk,
616561
Status=t.ZDOStatus.SUCCESS,
617562
NWK=device.nwk,
618563
ActiveEndpoints=[],
619564
),
565+
c.ZDO.MsgCbIncoming.Callback(
566+
Src=device.nwk,
567+
IsBroadcast=t.Bool.false,
568+
ClusterId=zdo_t.ZDOCmd.Active_EP_rsp,
569+
SecurityUse=0,
570+
TSN=7,
571+
MacDst=device.nwk,
572+
Data=serialize_zdo_command(
573+
command_id=zdo_t.ZDOCmd.Active_EP_rsp,
574+
Status=t.ZDOStatus.SUCCESS,
575+
NWKAddrOfInterest=device.nwk,
576+
ActiveEPList=[],
577+
),
578+
),
620579
],
621580
)
622581

tests/application/test_zigpy_callbacks.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
import logging
33

44
import pytest
5-
from zigpy.zdo.types import ZDOCmd
5+
import zigpy.zdo.types as zdo_t
66

77
import zigpy_znp.types as t
88
import zigpy_znp.commands as c
99

10-
from ..conftest import FORMED_DEVICES, CoroutineMock
10+
from ..conftest import FORMED_DEVICES, CoroutineMock, serialize_zdo_command
1111

1212

1313
def awaitable_mock(*, return_value=None, side_effect=None):
@@ -74,6 +74,24 @@ async def test_on_zdo_device_announce_nwk_change(device, make_application, mocke
7474
new_nwk = device.nwk + 1
7575

7676
# Assume its NWK changed and we're just finding out
77+
znp_server.send(
78+
c.ZDO.MsgCbIncoming.Callback(
79+
Src=0x0001,
80+
IsBroadcast=t.Bool.false,
81+
ClusterId=zdo_t.ZDOCmd.Device_annce,
82+
SecurityUse=0,
83+
TSN=123,
84+
MacDst=0x0000,
85+
Data=serialize_zdo_command(
86+
command_id=zdo_t.ZDOCmd.Device_annce,
87+
NWKAddr=new_nwk,
88+
IEEEAddr=device.ieee,
89+
Capability=c.zdo.MACCapabilities.Router,
90+
Status=t.ZDOStatus.SUCCESS,
91+
),
92+
)
93+
)
94+
7795
znp_server.send(
7896
c.ZDO.EndDeviceAnnceInd.Callback(
7997
Src=0x0001,
@@ -83,11 +101,13 @@ async def test_on_zdo_device_announce_nwk_change(device, make_application, mocke
83101
)
84102
)
85103

104+
await asyncio.sleep(0.1)
105+
86106
app.handle_join.assert_called_once_with(
87107
nwk=new_nwk, ieee=device.ieee, parent_nwk=None
88108
)
89109
assert app.handle_message.call_count == 1
90-
assert app.handle_message.mock_calls[0][2]["cluster"] == ZDOCmd.Device_annce
110+
assert app.handle_message.mock_calls[0][2]["cluster"] == zdo_t.ZDOCmd.Device_annce
91111

92112
# The device's NWK updated
93113
assert device.nwk == new_nwk

tests/tools/test_energy_scan.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import asyncio
22

33
import pytest
4+
import zigpy.zdo.types as zdo_t
45

56
import zigpy_znp.types as t
67
import zigpy_znp.commands as c
78
from zigpy_znp.tools.energy_scan import main as energy_scan
89

9-
from ..conftest import EMPTY_DEVICES, FORMED_DEVICES
10+
from ..conftest import (
11+
EMPTY_DEVICES,
12+
FORMED_DEVICES,
13+
serialize_zdo_command,
14+
deserialize_zdo_command,
15+
)
1016

1117

1218
@pytest.mark.parametrize("device", EMPTY_DEVICES)
@@ -23,32 +29,52 @@ async def test_energy_scan_formed(device, make_znp_server, capsys):
2329

2430
def fake_scanner(request):
2531
async def response(request):
26-
znp_server.send(c.ZDO.MgmtNWKUpdateReq.Rsp(Status=t.Status.SUCCESS))
27-
28-
delay = 2 ** request.ScanDuration
29-
num_channels = len(list(request.Channels))
30-
31-
for i in range(request.ScanCount):
32-
await asyncio.sleep(delay / 100)
33-
34-
znp_server.send(
35-
c.ZDO.MgmtNWKUpdateNotify.Callback(
36-
Src=0x0000,
32+
znp_server.send(c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS))
33+
34+
params = deserialize_zdo_command(request.ClusterId, request.Data[1:])
35+
channels = params["NwkUpdate"].ScanChannels
36+
num_channels = len(list(channels))
37+
38+
await asyncio.sleep(0.1)
39+
40+
znp_server.send(
41+
c.ZDO.MsgCbIncoming.Callback(
42+
Src=0x0000,
43+
IsBroadcast=t.Bool.false,
44+
ClusterId=zdo_t.ZDOCmd.Mgmt_NWK_Update_rsp,
45+
SecurityUse=0,
46+
TSN=request.TSN,
47+
MacDst=0x0000,
48+
Data=serialize_zdo_command(
49+
command_id=zdo_t.ZDOCmd.Mgmt_NWK_Update_rsp,
3750
Status=t.ZDOStatus.SUCCESS,
38-
ScannedChannels=request.Channels,
51+
ScannedChannels=channels,
3952
TotalTransmissions=998,
4053
TransmissionFailures=2,
41-
EnergyValues=list(range(num_channels)),
42-
)
54+
EnergyValues=list(range(11, 26 + 1))[:num_channels],
55+
),
56+
)
57+
)
58+
59+
znp_server.send(
60+
c.ZDO.MgmtNWKUpdateNotify.Callback(
61+
Src=0x0000,
62+
Status=t.ZDOStatus.SUCCESS,
63+
ScannedChannels=channels,
64+
TotalTransmissions=998,
65+
TransmissionFailures=2,
66+
EnergyValues=list(range(11, 26 + 1))[:num_channels],
4367
)
68+
)
4469

4570
asyncio.create_task(response(request))
4671

4772
znp_server.callback_for_response(
48-
c.ZDO.MgmtNWKUpdateReq.Req(
49-
Dst=0x0000,
50-
DstAddrMode=t.AddrMode.NWK,
51-
NwkManagerAddr=0x0000,
73+
c.AF.DataRequestExt.Req(
74+
DstAddrModeAddress=t.AddrModeAddress(mode=t.AddrMode.NWK, address=0x0000),
75+
DstEndpoint=0,
76+
SrcEndpoint=0,
77+
ClusterId=zdo_t.ZDOCmd.Mgmt_NWK_Update_req,
5278
partial=True,
5379
),
5480
fake_scanner,

zigpy_znp/zigbee/application.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -528,13 +528,6 @@ async def mrequest(
528528
data=data,
529529
)
530530

531-
async def force_remove(self, device: zigpy.device.Device) -> None:
532-
"""
533-
Attempts to forcibly remove a device from the network.
534-
"""
535-
536-
LOGGER.warning("Z-Stack does not support force remove")
537-
538531
async def permit(self, time_s=60, node=None):
539532
"""
540533
Permit joining the network via a specific node or via all router nodes.
@@ -696,10 +689,11 @@ async def on_zdo_message(self, msg: c.ZDO.MsgCbIncoming.Callback) -> None:
696689
hdr, data = zdo_t.ZDOHeader.deserialize(msg.ClusterId, message)
697690
names, types = zdo_t.CLUSTERS[msg.ClusterId]
698691
args, data = list_deserialize(data, types)
699-
# kwargs = dict(zip(names, args))
692+
kwargs = dict(zip(names, args))
700693

701694
if msg.ClusterId == zdo_t.ZDOCmd.Device_annce:
702695
self.on_zdo_device_announce(*args)
696+
device = self.get_device(ieee=kwargs["IEEEAddr"])
703697
elif msg.ClusterId == zdo_t.ZDOCmd.IEEE_addr_rsp:
704698
device = next((d for d in self._temp_devices if d.nwk == msg.Src), None)
705699
else:

0 commit comments

Comments
 (0)