Skip to content

Commit 00dc971

Browse files
Copilotpuddly
andcommitted
Add test coverage for debug logging in security.py
Co-authored-by: puddly <32534428+puddly@users.noreply.github.com>
1 parent 8c1e649 commit 00dc971

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""Test coverage for security.py logging statements."""
2+
import logging
3+
4+
5+
import zigpy_znp.types as t
6+
from zigpy_znp.znp import security
7+
from zigpy_znp.types.nvids import ExNvIds, OsalNvIds
8+
9+
from ..conftest import BaseZStack3CC2531
10+
11+
12+
async def test_read_devices_skips_unknown_link_keys(make_connected_znp, caplog):
13+
"""Test that read_devices logs debug messages for link keys without matching devices.
14+
15+
This test covers the debug logging statements in read_devices():
16+
- "Skipping hashed link key ... for unknown device"
17+
- "Skipping unhashed link key ... for unknown device"
18+
19+
These occur when link keys exist in NVRAM but don't have corresponding
20+
entries in the address manager table.
21+
"""
22+
znp, znp_server = await make_connected_znp(BaseZStack3CC2531)
23+
24+
# Initialize LEGACY section if not exists
25+
if ExNvIds.LEGACY not in znp_server._nvram:
26+
znp_server._nvram[ExNvIds.LEGACY] = {}
27+
28+
# Set up IEEEs for test
29+
known_ieee = t.EUI64.convert("11:22:33:44:55:66:77:88")
30+
unknown_hashed_ieee = t.EUI64.convert("aa:bb:cc:dd:ee:ff:00:11")
31+
32+
# Set up address manager with only the known device - must be serialized
33+
addr_mgr_table = t.AddressManagerTable([
34+
t.AddrMgrEntry(
35+
type=t.AddrMgrUserType.Security,
36+
nwkAddr=t.NWK(0x1234),
37+
extAddr=known_ieee,
38+
),
39+
# Fill with empty entries
40+
*[t.AddrMgrEntry(
41+
type=t.AddrMgrUserType.Default,
42+
nwkAddr=t.NWK(0xFFFF),
43+
extAddr=t.EUI64.convert("00:00:00:00:00:00:00:00"),
44+
) for _ in range(15)],
45+
])
46+
znp_server._nvram[ExNvIds.LEGACY][OsalNvIds.ADDRMGR] = addr_mgr_table.serialize()
47+
48+
# Add a hashed link key for an unknown device (not in address manager)
49+
znp_server._nvram[ExNvIds.LEGACY][OsalNvIds.LEGACY_TCLK_TABLE_START] = (
50+
t.TCLKDevEntry(
51+
extAddr=unknown_hashed_ieee,
52+
txFrmCntr=100,
53+
rxFrmCntr=200,
54+
keyAttributes=t.KeyAttributes.VERIFIED_KEY,
55+
keyType=t.KeyType.NONE,
56+
SeedShift_IcIndex=0,
57+
).serialize()
58+
)
59+
60+
# Add another hashed link key for a second unknown device to verify logging
61+
znp_server._nvram[ExNvIds.LEGACY][OsalNvIds.LEGACY_TCLK_TABLE_START + 1] = (
62+
t.TCLKDevEntry(
63+
extAddr=t.EUI64.convert("bb:bb:bb:bb:bb:bb:bb:bb"),
64+
txFrmCntr=150,
65+
rxFrmCntr=250,
66+
keyAttributes=t.KeyAttributes.VERIFIED_KEY,
67+
keyType=t.KeyType.NONE,
68+
SeedShift_IcIndex=1,
69+
).serialize()
70+
)
71+
72+
# For ZStack 3.0, also need APS link key table (even if empty)
73+
znp_server._nvram[ExNvIds.LEGACY][OsalNvIds.APS_LINK_KEY_TABLE] = b"\x00" * 16
74+
75+
tclk_seed = t.KeyData(b"\xAA" * 16)
76+
77+
# Capture debug logs
78+
caplog.set_level(logging.DEBUG, logger="zigpy_znp.znp.security")
79+
80+
# Call read_devices - should log debug messages for unknown devices
81+
devices = await security.read_devices(znp, tclk_seed=tclk_seed)
82+
83+
# Verify that debug messages were logged for hashed keys
84+
assert "Skipping hashed link key" in caplog.text
85+
assert str(unknown_hashed_ieee) in caplog.text
86+
87+
# Verify messages are at DEBUG level
88+
debug_records = [r for r in caplog.records if "Skipping" in r.message and "link key" in r.message]
89+
assert len(debug_records) >= 2 # At least 2 unknown devices
90+
assert all(r.levelname == "DEBUG" for r in debug_records)
91+
92+
# Verify that only the known device is returned (no orphan keys)
93+
assert len(devices) == 1
94+
assert devices[0].node_info.ieee == known_ieee
95+
96+
# For ZStack 3.0, also need APS link key table (even if empty)
97+
znp_server._nvram[ExNvIds.LEGACY][OsalNvIds.APS_LINK_KEY_TABLE] = b"\x00" * 16

0 commit comments

Comments
 (0)