Skip to content

Commit 4bcd430

Browse files
committed
test(dispatcher): cover defensive while-loop in mint path
Add a test that exercises the while-loop body in DirectDispatcher._dispatch_request which skips past in-flight IDs when minting. CI was failing with 99.99% coverage (fail-under=100%) because line 264 was unreachable through normal API usage — the max() advancement on caller-supplied IDs prevents natural collisions. The test injects synthetic in-flight keys to prove the guard works.
1 parent 47b655c commit 4bcd430

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

tests/shared/test_dispatcher.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,38 @@ async def parked() -> None:
482482
assert [request_id for request_id in seen_ids if request_id != "3"] == [4, 5, 6]
483483

484484

485+
@pytest.mark.anyio
486+
async def test_minted_id_skips_injected_consecutive_in_flight_ids():
487+
"""Defensive guard: if _in_flight_ids contains the next sequential
488+
candidates, the while-loop advances past all of them."""
489+
490+
async def noop(
491+
ctx: DispatchContext[TransportContext], method: str, params: Mapping[str, Any] | None
492+
) -> dict[str, Any]:
493+
return {}
494+
495+
client, server, close = direct_pair()
496+
try:
497+
async with anyio.create_task_group() as tg:
498+
await tg.start(client.run, noop, noop)
499+
await tg.start(server.run, noop, noop)
500+
# send_raw_request on client dispatches on the server's peer
501+
# (_dispatch_request runs on server). Inject synthetic in-flight
502+
# keys into the SERVER so the mint loop must skip them.
503+
# _next_id is 0, so mint increments to 1, finds it occupied,
504+
# increments to 2, finds it occupied, increments to 3, finds it
505+
# occupied, and finally lands on 4.
506+
server._in_flight_ids.update({1, 2, 3})
507+
result = await client.send_raw_request("ping", None)
508+
assert result == {}
509+
# After completion the id is discarded from in_flight, but the
510+
# counter must have advanced to 4 (skipping 1, 2, 3).
511+
assert server._next_id == 4
512+
tg.cancel_scope.cancel()
513+
finally:
514+
close()
515+
516+
485517
@pytest.mark.anyio
486518
async def test_supplied_numeric_string_id_collides_with_its_int_twin(pair_factory: PairFactory):
487519
""" "7" and 7 are one id in the collision domain on BOTH dispatchers, so the

0 commit comments

Comments
 (0)