* test(pilot): in-process simulation of mid-tunnel disconnects
The PR #979 hardening added per-stream idle timers, drain handling,
paused-request maps, and a tcpAwaitingDrain set on the bridge. None
of those cleanup paths had an end-to-end test driving them through a
real disconnect. A future refactor that inverts the order of
clearIdleTimer + streams.delete (or that misses one of the aux maps)
would leak per-tunnel memory in a way unit tests cannot catch.
Spin up a real http.Server with attachUpgrade and a real ws.WebSocket
client (same self-contained pattern as
pilot-tunnel-integration.test.ts). Four cases:
- HTTP request mid-flight: open a real loopback HTTP request, wait
for the bridge to forward http_req to the agent, terminate the
agent WS, assert the loopback request resolves with 502 (the
teardownStream path) and the manager marks the node Offline.
- TCP stream with bytes outstanding: openTcpStream from the bridge,
ack open from the test agent, write some bytes, terminate the
tunnel, assert the TcpStream emits 'close' and the bridge is
gone from the manager.
- Reconnect with the long-lived token after a clean close does NOT
bump tunnels_replaced (no live tunnel to replace).
- Reconnect WHILE the prior tunnel is still live DOES bump
tunnels_replaced. Inverse case proves the counter wiring is
correct in both directions.
Self-contained: no shared helper modules, no dependencies on other
in-flight pilot test files. Can land independently of PRs #982,
#983, or #985.
* test(pilot): address PR E code-review on disconnect tests
Two small findings:
- Defensive: attach a no-op 'error' listener on the TcpStream in
test #2 after the 'open' event has fired. teardownStream only
emits 'error' for unaccepted streams today, so the listener is
not exercised; the listener exists so a future refactor that
delays accepted=true past 'open' cannot crash the worker on an
unhandled 'error' event.
- Removed a stale cross-file reference in the header comment that
pointed at pilot-tunnel-integration.test.ts; that file lives in
a separate in-flight branch and does not exist on main.
No behavior change. All 4 disconnect tests pass.
* chore(test): drop unused PROTOCOL_VERSION import
The import was leftover from an earlier draft and ESLint flagged it
as no-unused-vars (error level for symbols not prefixed with _),
failing the lint job in CI.