Skip to content

Commit 333841d

Browse files
committed
Use DeliveryError instead of RuntimeError where appropriate
1 parent 47579d9 commit 333841d

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

tests/application/test_requests.py

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
import zigpy.zdo
55
from zigpy.zdo.types import ZDOCmd, SizePrefixedSimpleDescriptor
6+
from zigpy.exceptions import DeliveryError
67

78
import zigpy_znp.types as t
89
import zigpy_znp.config as conf
@@ -319,10 +320,11 @@ async def test_broadcast(device, make_application, mocker):
319320
await app.shutdown()
320321

321322

322-
@pytest.mark.parametrize("device", FORMED_DEVICES)
323+
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
323324
async def test_request_concurrency(device, make_application, mocker):
324325
app, znp_server = make_application(
325-
server_cls=device, client_config={conf.CONF_MAX_CONCURRENT_REQUESTS: 2}
326+
server_cls=device,
327+
client_config={"znp_config": {conf.CONF_MAX_CONCURRENT_REQUESTS: 2}},
326328
)
327329

328330
await app.startup()
@@ -331,10 +333,16 @@ async def test_request_concurrency(device, make_application, mocker):
331333

332334
# Keep track of how many requests we receive at once
333335
in_flight_requests = 0
336+
did_lock = False
334337

335338
def make_response(req):
336339
async def callback(req):
337340
nonlocal in_flight_requests
341+
nonlocal did_lock
342+
343+
if app._concurrent_requests_semaphore.locked():
344+
did_lock = True
345+
338346
in_flight_requests += 1
339347
assert in_flight_requests <= 2
340348

@@ -369,13 +377,71 @@ async def callback(req):
369377
sequence=seq,
370378
data=b"\x00",
371379
)
372-
for seq in range(20)
380+
for seq in range(10)
373381
]
374382
)
375383

376384
assert all(status == t.Status.SUCCESS for status, msg in responses)
385+
assert in_flight_requests == 0
386+
assert did_lock
387+
388+
await app.shutdown()
389+
390+
391+
"""
392+
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
393+
async def test_request_concurrency_overflow(device, make_application, mocker):
394+
mocker.patch("zigpy_znp.zigbee.application.MAX_WAITING_REQUESTS", new=1)
395+
396+
app, znp_server = make_application(
397+
server_cls=device, client_config={
398+
'znp_config': {conf.CONF_MAX_CONCURRENT_REQUESTS: 1}
399+
}
400+
)
401+
402+
await app.startup()
403+
404+
device = app.add_initialized_device(ieee=t.EUI64(range(8)), nwk=0xAABB)
405+
406+
def make_response(req):
407+
async def callback(req):
408+
await asyncio.sleep(0.01 * req.TSN)
409+
410+
znp_server.send(c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS))
411+
znp_server.send(
412+
c.AF.DataConfirm.Callback(
413+
Status=t.Status.SUCCESS, Endpoint=1, TSN=req.TSN
414+
)
415+
)
416+
417+
asyncio.create_task(callback(req))
418+
419+
znp_server.reply_to(
420+
request=c.AF.DataRequestExt.Req(partial=True), responses=[make_response]
421+
)
422+
423+
# We can only handle 1 in-flight request and 1 enqueued request. Last one will fail.
424+
responses = await asyncio.gather(
425+
*[
426+
app.request(
427+
device,
428+
profile=260,
429+
cluster=1,
430+
src_ep=1,
431+
dst_ep=1,
432+
sequence=seq,
433+
data=b"\x00",
434+
)
435+
for seq in range(3)
436+
], return_exceptions=True)
437+
438+
(rsp1, stat1), (rsp2, stat2), error3 = responses
439+
440+
assert rsp1 == rsp2 == t.Status.SUCCESS
441+
assert isinstance(error3, ValueError)
377442
378443
await app.shutdown()
444+
"""
379445

380446

381447
@pytest.mark.parametrize("device", FORMED_DEVICES)
@@ -717,7 +783,7 @@ def assoc_remove(req):
717783
if can_assoc_remove and final_status == t.Status.SUCCESS:
718784
await req
719785
else:
720-
with pytest.raises(RuntimeError):
786+
with pytest.raises(DeliveryError):
721787
await req
722788

723789
await did_assoc_get
@@ -804,7 +870,7 @@ def data_confirm_replier(req):
804870
if succeed:
805871
await req
806872
else:
807-
with pytest.raises(RuntimeError):
873+
with pytest.raises(DeliveryError):
808874
await req
809875

810876
# In either case only one source routing attempt is performed

zigpy_znp/zigbee/application.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from zigpy.zcl import clusters
2020
from zigpy.types import ExtendedPanId, deserialize as list_deserialize
2121
from zigpy.zdo.types import CLUSTERS as ZDO_CLUSTERS, ZDOCmd, ZDOHeader, MultiAddress
22+
from zigpy.exceptions import DeliveryError
2223

2324
import zigpy_znp.types as t
2425
import zigpy_znp.config as conf
@@ -1521,7 +1522,7 @@ async def _send_request(
15211522
# We've tried everything already so at this point just wait
15221523
await asyncio.sleep(REQUEST_ERROR_RETRY_DELAY)
15231524
else:
1524-
raise RuntimeError(
1525+
raise DeliveryError(
15251526
f"Request failed after {REQUEST_MAX_RETRIES} attempts:"
15261527
f" {status!r}"
15271528
)

0 commit comments

Comments
 (0)