Skip to content

Commit 57f303c

Browse files
puddlydmulcahey
andauthored
Fix unit tests failing with latest zigpy additions (#210)
* Fix unit tests failing with latest zigpy additions * Increase pytest timeout to 30s * Speed up unit tests * Allow reset requests to bypass the SREQ lock * Make `make_application` synchronous * fix ci * Tweak slow TC device indication/ZDO announce unit test * Disable request retries in failing unit test --------- Co-authored-by: David Mulcahey <[email protected]>
1 parent 3f6ba1b commit 57f303c

File tree

9 files changed

+122
-77
lines changed

9 files changed

+122
-77
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
key: >-
3636
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
3737
steps.python.outputs.python-version }}-${{
38-
hashFiles('setup.cfg') }}
38+
hashFiles('pyproject.toml') }}
3939
restore-keys: |
4040
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-
4141
- name: Create Python virtual environment
@@ -66,7 +66,7 @@ jobs:
6666
key: >-
6767
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
6868
steps.python.outputs.python-version }}-${{
69-
hashFiles('setup.cfg') }}
69+
hashFiles('pyproject.toml') }}
7070
- name: Fail job if Python cache restore failed
7171
if: steps.cache-venv.outputs.cache-hit != 'true'
7272
run: |
@@ -107,7 +107,7 @@ jobs:
107107
key: >-
108108
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
109109
steps.python.outputs.python-version }}-${{
110-
hashFiles('setup.cfg') }}
110+
hashFiles('pyproject.toml') }}
111111
- name: Fail job if Python cache restore failed
112112
if: steps.cache-venv.outputs.cache-hit != 'true'
113113
run: |
@@ -150,7 +150,7 @@ jobs:
150150
key: >-
151151
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
152152
steps.python.outputs.python-version }}-${{
153-
hashFiles('setup.cfg') }}
153+
hashFiles('pyproject.toml') }}
154154
- name: Fail job if Python cache restore failed
155155
if: steps.cache-venv.outputs.cache-hit != 'true'
156156
run: |
@@ -196,7 +196,7 @@ jobs:
196196
key: >-
197197
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
198198
steps.python.outputs.python-version }}-${{
199-
hashFiles('setup.cfg') }}
199+
hashFiles('pyproject.toml') }}
200200
- name: Fail job if Python cache restore failed
201201
if: steps.cache-venv.outputs.cache-hit != 'true'
202202
run: |
@@ -243,7 +243,7 @@ jobs:
243243
key: >-
244244
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
245245
steps.python.outputs.python-version }}-${{
246-
hashFiles('setup.cfg') }}
246+
hashFiles('pyproject.toml') }}
247247
- name: Fail job if Python cache restore failed
248248
if: steps.cache-venv.outputs.cache-hit != 'true'
249249
run: |
@@ -264,7 +264,7 @@ jobs:
264264
. venv/bin/activate
265265
pytest \
266266
-qq \
267-
--timeout=20 \
267+
--timeout=30 \
268268
--durations=10 \
269269
--cov zigpy_znp \
270270
--cov-config pyproject.toml \
@@ -298,7 +298,7 @@ jobs:
298298
key: >-
299299
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
300300
steps.python.outputs.python-version }}-${{
301-
hashFiles('setup.cfg') }}
301+
hashFiles('pyproject.toml') }}
302302
- name: Fail job if Python cache restore failed
303303
if: steps.cache-venv.outputs.cache-hit != 'true'
304304
run: |

tests/application/test_connect.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ async def test_probe_multiple(device, make_znp_server):
120120

121121
@pytest.mark.parametrize("device", FORMED_DEVICES)
122122
async def test_reconnect(device, make_application):
123-
app, znp_server = await make_application(
123+
app, znp_server = make_application(
124124
server_cls=device,
125125
client_config={
126126
# Make auto-reconnection happen really fast
@@ -162,7 +162,7 @@ async def test_reconnect(device, make_application):
162162

163163
@pytest.mark.parametrize("device", FORMED_DEVICES)
164164
async def test_shutdown_from_app(device, mocker, make_application):
165-
app, znp_server = await make_application(server_cls=device)
165+
app, znp_server = make_application(server_cls=device)
166166

167167
await app.startup(auto_form=False)
168168

@@ -178,7 +178,7 @@ async def test_shutdown_from_app(device, mocker, make_application):
178178

179179

180180
async def test_clean_shutdown(make_application):
181-
app, znp_server = await make_application(server_cls=FormedLaunchpadCC26X2R1)
181+
app, znp_server = make_application(server_cls=FormedLaunchpadCC26X2R1)
182182
await app.startup(auto_form=False)
183183

184184
# This should not throw
@@ -189,7 +189,7 @@ async def test_clean_shutdown(make_application):
189189

190190

191191
async def test_multiple_shutdown(make_application):
192-
app, znp_server = await make_application(server_cls=FormedLaunchpadCC26X2R1)
192+
app, znp_server = make_application(server_cls=FormedLaunchpadCC26X2R1)
193193
await app.startup(auto_form=False)
194194

195195
await app.shutdown()
@@ -201,7 +201,7 @@ async def test_multiple_shutdown(make_application):
201201
async def test_reconnect_lockup(device, make_application, mocker):
202202
mocker.patch("zigpy_znp.zigbee.application.WATCHDOG_PERIOD", 0.1)
203203

204-
app, znp_server = await make_application(
204+
app, znp_server = make_application(
205205
server_cls=device,
206206
client_config={
207207
# Make auto-reconnection happen really fast
@@ -242,7 +242,7 @@ async def test_reconnect_lockup(device, make_application, mocker):
242242
async def test_reconnect_lockup_pyserial(device, make_application, mocker):
243243
mocker.patch("zigpy_znp.zigbee.application.WATCHDOG_PERIOD", 0.1)
244244

245-
app, znp_server = await make_application(
245+
app, znp_server = make_application(
246246
server_cls=device,
247247
client_config={
248248
conf.CONF_ZNP_CONFIG: {
@@ -293,7 +293,7 @@ async def patched_start_network(old_start_network=app.start_network, **kwargs):
293293

294294
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
295295
async def test_disconnect(device, make_application):
296-
app, znp_server = await make_application(
296+
app, znp_server = make_application(
297297
server_cls=device,
298298
client_config={
299299
conf.CONF_ZNP_CONFIG: {
@@ -316,7 +316,7 @@ async def test_disconnect(device, make_application):
316316

317317
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
318318
async def test_disconnect_failure(device, make_application):
319-
app, znp_server = await make_application(
319+
app, znp_server = make_application(
320320
server_cls=device,
321321
client_config={
322322
conf.CONF_ZNP_CONFIG: {

tests/application/test_joining.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import asyncio
22
import contextlib
3+
from unittest import mock
34

45
import pytest
56
import zigpy.util
67
import zigpy.types
8+
import zigpy.device
79
import zigpy.zdo.types as zdo_t
810

911
import zigpy_znp.types as t
@@ -21,7 +23,7 @@
2123

2224
@pytest.mark.parametrize("device", FORMED_DEVICES)
2325
async def test_permit_join(device, mocker, make_application):
24-
app, znp_server = await make_application(server_cls=device)
26+
app, znp_server = make_application(server_cls=device)
2527

2628
permit_join_coordinator = znp_server.reply_once_to(
2729
request=c.ZDO.MgmtPermitJoinReq.Req(
@@ -38,7 +40,7 @@ async def test_permit_join(device, mocker, make_application):
3840
request=zdo_request_matcher(
3941
dst_addr=t.AddrModeAddress(t.AddrMode.Broadcast, 0xFFFC),
4042
command_id=zdo_t.ZDOCmd.Mgmt_Permit_Joining_req,
41-
TSN=6,
43+
TSN=7,
4244
zdo_PermitDuration=10,
4345
zdo_TC_Significant=0,
4446
),
@@ -74,7 +76,7 @@ async def test_permit_join(device, mocker, make_application):
7476

7577
@pytest.mark.parametrize("device", FORMED_DEVICES)
7678
async def test_join_coordinator(device, make_application):
77-
app, znp_server = await make_application(server_cls=device)
79+
app, znp_server = make_application(server_cls=device)
7880

7981
# Handle us opening joins on the coordinator
8082
permit_join_coordinator = znp_server.reply_once_to(
@@ -100,7 +102,7 @@ async def test_join_device(device, make_application):
100102
ieee = t.EUI64.convert("EC:1B:BD:FF:FE:54:4F:40")
101103
nwk = 0x1234
102104

103-
app, znp_server = await make_application(server_cls=device)
105+
app, znp_server = make_application(server_cls=device)
104106
device = app.add_initialized_device(ieee=ieee, nwk=nwk)
105107

106108
permit_join = znp_server.reply_once_to(
@@ -115,7 +117,7 @@ async def test_join_device(device, make_application):
115117
IsBroadcast=t.Bool.false,
116118
ClusterId=32822,
117119
SecurityUse=0,
118-
TSN=6,
120+
TSN=7,
119121
MacDst=0x0000,
120122
Data=b"\x00",
121123
),
@@ -133,7 +135,7 @@ async def test_join_device(device, make_application):
133135
@pytest.mark.parametrize("device", FORMED_ZSTACK3_DEVICES)
134136
@pytest.mark.parametrize("permit_result", [None, asyncio.TimeoutError()])
135137
async def test_permit_join_with_key(device, permit_result, make_application, mocker):
136-
app, znp_server = await make_application(server_cls=device)
138+
app, znp_server = make_application(server_cls=device)
137139

138140
# Consciot bulb
139141
ieee = t.EUI64.convert("EC:1B:BD:FF:FE:54:4F:40")
@@ -183,7 +185,7 @@ async def test_permit_join_with_key(device, permit_result, make_application, moc
183185

184186
@pytest.mark.parametrize("device", FORMED_ZSTACK3_DEVICES)
185187
async def test_permit_join_with_invalid_key(device, make_application):
186-
app, znp_server = await make_application(server_cls=device)
188+
app, znp_server = make_application(server_cls=device)
187189

188190
# Consciot bulb
189191
ieee = t.EUI64.convert("EC:1B:BD:FF:FE:54:4F:40")
@@ -197,10 +199,10 @@ async def test_permit_join_with_invalid_key(device, make_application):
197199

198200
@pytest.mark.parametrize("device", FORMED_DEVICES)
199201
async def test_on_zdo_device_join(device, make_application, mocker):
200-
app, znp_server = await make_application(server_cls=device)
202+
app, znp_server = make_application(server_cls=device)
201203
await app.startup(auto_form=False)
202204

203-
mocker.patch.object(app, "handle_join")
205+
mocker.patch.object(app, "handle_join", wraps=app.handle_join)
204206
mocker.patch("zigpy_znp.zigbee.application.DEVICE_JOIN_MAX_DELAY", new=0)
205207

206208
nwk = 0x1234
@@ -217,10 +219,10 @@ async def test_on_zdo_device_join(device, make_application, mocker):
217219

218220
@pytest.mark.parametrize("device", FORMED_DEVICES)
219221
async def test_on_zdo_device_join_and_announce_fast(device, make_application, mocker):
220-
app, znp_server = await make_application(server_cls=device)
222+
app, znp_server = make_application(server_cls=device)
221223
await app.startup(auto_form=False)
222224

223-
mocker.patch.object(app, "handle_join")
225+
mocker.patch.object(app, "handle_join", wraps=app.handle_join)
224226
mocker.patch("zigpy_znp.zigbee.application.DEVICE_JOIN_MAX_DELAY", new=0.5)
225227

226228
nwk = 0x1234
@@ -272,18 +274,22 @@ async def test_on_zdo_device_join_and_announce_fast(device, make_application, mo
272274
await app.shutdown()
273275

274276

277+
@mock.patch("zigpy_znp.zigbee.application.DEVICE_JOIN_MAX_DELAY", new=0.1)
278+
@mock.patch(
279+
"zigpy.device.Device._initialize",
280+
new=zigpy.device.Device._initialize.__wrapped__, # to disable retries
281+
)
275282
@pytest.mark.parametrize("device", FORMED_DEVICES)
276283
async def test_on_zdo_device_join_and_announce_slow(device, make_application, mocker):
277-
app, znp_server = await make_application(server_cls=device)
284+
app, znp_server = make_application(server_cls=device)
278285
await app.startup(auto_form=False)
279286

280287
znp_server.reply_to(
281288
c.ZDO.ExtRouteDisc.Req(partial=True),
282289
responses=[c.ZDO.ExtRouteDisc.Rsp(Status=t.Status.SUCCESS)],
283290
)
284291

285-
mocker.patch.object(app, "handle_join")
286-
mocker.patch("zigpy_znp.zigbee.application.DEVICE_JOIN_MAX_DELAY", new=0.1)
292+
mocker.patch.object(app, "handle_join", wraps=app.handle_join)
287293

288294
nwk = 0x1234
289295
ieee = t.EUI64.convert("11:22:33:44:55:66:77:88")
@@ -295,11 +301,13 @@ async def test_on_zdo_device_join_and_announce_slow(device, make_application, mo
295301
# We're waiting for the device to announce itself
296302
assert app.handle_join.call_count == 0
297303

298-
await asyncio.sleep(0.3)
304+
# Wait for the trust center join timeout to elapse
305+
while app.handle_join.call_count == 0:
306+
await asyncio.sleep(0.1)
299307

300-
# Too late, it already happened
301308
app.handle_join.assert_called_once_with(nwk=nwk, ieee=ieee, parent_nwk=0x0001)
302309

310+
# Finally, send the device announcement
303311
znp_server.send(
304312
c.ZDO.MsgCbIncoming.Callback(
305313
Src=nwk,
@@ -327,9 +335,10 @@ async def test_on_zdo_device_join_and_announce_slow(device, make_application, mo
327335
)
328336
)
329337

330-
await asyncio.sleep(0.1)
338+
await asyncio.sleep(0.5)
331339

332340
# The announcement will trigger another join indication
333341
assert app.handle_join.call_count == 2
334342

343+
app.get_device(ieee=ieee).cancel_initialization()
335344
await app.shutdown()

0 commit comments

Comments
 (0)