test(moq-net): cover the announce loop's demand/linger state machine - #2429
Conversation
The lite-06 route-cost hysteresis in run_announce (defer the cold-cost restore by COST_LINGER after demand drains, cancel it when demand returns, supersede it on a route change) had no direct regression coverage; only the lower-level pieces (broadcast::Demand edges, the origin reselect gate, the RouteCost codec) were tested. Add an in-memory harness that runs run_announce against a sink session (writes captured for decoding, reads pending forever) and asserts the exact wire messages under paused tokio time: - draining demand while zero is advertised sends nothing immediately - demand returning within the linger cancels the restore silently - an expired linger sends exactly one ANNOUNCE_RESTART with the cold cost - a route change mid-linger supersedes the pending restore - a viewer arriving on a cold advertisement re-prices to zero immediately Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4a4b9a8 to
d83ec2b
Compare
…ry deadlines Review of the first pass found two ways the suite could pass for the wrong reason: - demand_return_cancels_the_restore asserted only silence, which a broken cancel also produces: an uncancelled linger fires while demand is back, recomputes the same zero cost, and hits the unchanged-route arm without writing. It now drains a second time inside the window, so a stale deadline sends the restart four seconds early. - The trailing assert_quiet in the expiry and route-change tests would pass if the announce task had panicked, since a dead task writes nothing. Harness::assert_idle now checks the JoinHandle too. Also adds staggered_lingers_restore_independently, covering the deadline scan across two entries (a single lingering broadcast can't tell min from max), and renames the terse const V to VERSION. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds a test module for the publisher announce loop using fake WebTransport sessions and streams that capture and decode emitted messages. A harness creates broadcasts with configurable viewer demand and runs the loop with paused Tokio time. Tests cover deferred and canceled cold-cost restoration, independent linger deadlines, one-shot expiry behavior, route-change supersession, and immediate repricing when demand arrives. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What
Adds direct regression coverage for the demand/linger state machine in
run_announce(rs/moq-net/src/lite/publisher.rs), introduced by #2424 and now onmain. Previously only the lower-level pieces were tested (broadcast::Demandedges, the origin reselect gate, theRouteCostcodec); the announce loop's hysteresis itself (Op::Idle,Op::Linger,COST_LINGER, the fused linger sleep,idle_atcleared onOp::Route) had none. Flagged by CodeRabbit on #2424.Tests only, no behavior change, so this targets
main.How
A minimal in-memory harness:
run_announceruns against a sink session whose send stream captures bytes (decoded back intoAnnounceOk/AnnounceBroadcastmessages via a cursor, so each step asserts exactly the wire messages it caused) and whose recv stream stays pending forever. Tokio time is paused, so the 5s linger is deterministic; understart_pausedthe 1mssettle()is a true quiescence barrier, since auto-advance only fires once the runtime is idle.Six tests:
ANNOUNCE_RESTARTwith the cold cost, then settles.Verification
Every test was mutation-checked so none passes for the wrong reason:
COST_LINGER= 0.min()→.max()idle_atoutgoing_costignores demandTwo of these came out of reviewing the first pass, which had real holes worth calling out:
assert_quiet()would swallow it (tokio::spawnparks the panic in the handle).Harness::assert_idlenow checks theJoinHandlealongside the wire.Cross-package sync
Test-only change in
rs/moq-net; no wire, API, or doc surface touched, so no other rows apply.🤖 Generated with Claude Code
(written by Fable 5)