Skip to content

test(serial): unit + integration tests for handle_serial_ws task split #757

Description

@zackees

Sub-issue of #755 (post-#750 follow-up meta).

Scope

crates/fbuild-daemon/src/handlers/websockets.rs::handle_serial_ws() was refactored in #750 from a single tokio::select! loop into three concurrent tasks (reader / writer / inbound). The split has no test coverage — landed on hardware validation only.

What needs covering

Unit tests (in-process, mock channels)

  1. Reader contract: given a stream of SerialStreamEvents on the broadcast channel, the reader pushes one SerialServerMessage::Data per Data event into the out-mpsc, and forwards non-Data events 1:1.
  2. Writer batching: when N Data messages are already queued in the out-mpsc before the writer wakes up, the writer coalesces them into a single Data { lines: [...], current_index: ... } WS frame.
  3. Writer event-ordering: when a non-Data message arrives mid-batch, the writer flushes the pending Data batch FIRST, then ships the non-Data event, then continues batching new Data.
  4. Writer exit propagation: when the WS sink returns an error, the writer exits cleanly without panicking; the reader and inbound tasks notice (out-mpsc producers dropped → next send fails or recv returns None).
  5. RecvError::Lagged at the reader: the broadcast receiver lag path emits a tracing::warn! and continues; doesn't kill the reader task.

Integration tests (real daemon, real WS client)

  1. Burst smoke: spawn an in-process daemon, point a mock serial source at it that emits 320 lines in one rx.send burst, attach a WS client, assert all 320 lines arrive (no Lagged warnings, no drops). This is the exact reproducer for perf(serial): per-line WebSocket messages drop lines under sustained TX bursts #749.
  2. Slow socket: artificially delay the WS sink (e.g. wrap it in a tokio::time::sleep(10ms) layer); confirm the reader keeps draining the broadcast channel and the writer ships bigger batches as the queue grows. Asserts the producer/consumer decoupling.
  3. Mixed traffic: interleave Data events with PortDisconnected / PortReattached events; assert FIFO ordering at the client.

Suggested file layout

  • crates/fbuild-daemon/src/handlers/websockets.rs — keep production code clean; add #[cfg(test)] mod tests { ... } at bottom for unit tests that can drive the reader/writer functions in isolation (this means extracting them into testable free functions — a useful refactor in its own right).
  • crates/fbuild-daemon/tests/serial_ws_burst.rs — integration tests spinning up a real daemon and WS client.

Acceptance criteria

Cross-links

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions