test(websockets): unit tests for ReaderControl + writer coalescing (closes #757)#762
Conversation
…loses #757) Adds 4 unit tests inside the existing `crates/fbuild-daemon/src/handlers/websockets.rs` test module: * `reader_control_drain_reports_drop_count` — exercises the `ReaderControl::Drain` round-trip through a toy reader that mirrors the production reader's `tokio::select! { biased; ... }` loop. Proves the oneshot reply IS a real count <= events sent. * `reader_control_get_depth_reports_broadcast_length` — same for `ReaderControl::GetDepth`. * `writer_coalesces_adjacent_data_into_one_frame` — exercises the writer-batching contract: 5 adjacent `Data` messages coalesce into 1 `Data` with 5 lines and the latest `current_index`. * `writer_flushes_data_before_non_data_event` — exercises ordering: `Data, Data, PortDisconnected, Data` produces `Data{[a,b]}, PortDisconnected, Data{[c]}` — never reorders non-Data events behind the pending batch. The reader/writer/inbound task bodies in `handle_serial_ws()` are spawned inline and capture local closures, so we exercise the **primitives** they rely on (ReaderControl select branch + Data-coalescing state machine) in isolation rather than reaching into the spawn topology directly. A full axum WebSocket harness integration test is deferred to a follow-up sub-PR because it needs a real hyper server stood up to drive end-to-end frames. Also picks up a minor `Cargo.lock` drift (version bump 2.2.31 -> 2.3.0 that #753 missed in the lockfile). Build: `soldr cargo build -p fbuild-daemon --tests` clean. Tests: `soldr cargo test -p fbuild-daemon --lib handlers::websockets` 6 passed (2 existing + 4 new). Fmt: `soldr cargo fmt -p fbuild-daemon --check` clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 10 minutes and 19 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Closes #757. Sub-PR of meta #755.
Summary
Adds 4 unit tests inside the existing
crates/fbuild-daemon/src/handlers/websockets.rstest module covering the post-#750 / #761 reader/writer/inbound split contracts.Tests added
reader_control_drain_reports_drop_count— exercisesReaderControl::Drainround-trip through a toy reader that mirrors the production reader'stokio::select! { biased; ... }loop. Proves the oneshot reply IS a real count <= events sent.reader_control_get_depth_reports_broadcast_length— same forReaderControl::GetDepth.writer_coalesces_adjacent_data_into_one_frame— exercises the writer-batching contract: 5 adjacentDatamessages coalesce into 1Datawith 5 lines and the latestcurrent_index.writer_flushes_data_before_non_data_event— exercises ordering:Data, Data, PortDisconnected, DataproducesData{[a,b]}, PortDisconnected, Data{[c]}— never reorders non-Data events behind the pending batch.Scope rationale
The reader / writer / inbound task bodies in
handle_serial_ws()are spawned inline and capture local closures, so we exercise the primitives they rely on (ReaderControl select branch + Data-coalescing state machine) in isolation rather than reaching into the spawn topology directly.A full axum WebSocket harness integration test is deferred to a follow-up sub-PR because it needs a real hyper server stood up to drive end-to-end frames — substantially more scaffolding than these primitive-level checks need, and out of scope for the "regression-guard the contracts" goal stated in #757.
Drive-by
Picks up a minor
Cargo.lockdrift: version bump 2.2.31 -> 2.3.0 that PR #753 missed in the lockfile.Test plan
soldr cargo build -p fbuild-daemon --tests— cleansoldr cargo test -p fbuild-daemon --lib handlers::websockets— 6 passed (2 existing + 4 new)soldr cargo fmt -p fbuild-daemon --check— clean🤖 Generated with Claude Code