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
    No fields configured for issues without a type.

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions