fcl-web: fpcunit tests for the websocket client lifetime handling (depends on !1565)

fpcunit tests for the websocket client, as announced in #41913 (closed).

Depends on !1565 (merged). This branch is based on its commit fb10d17495; the only new commit is 665d5e93dd, which adds files under packages/fcl-web/tests and nothing else. The tests use additions of !1565 (merged) (e.g. EWSReadError) and do not compile against main without it. Once !1565 (merged) is merged, only that one commit remains in this MR.

What is added:

  • a separate console runner testwebsocketclient.lpr (+ .lpi), deliberately not merged into testfpweb: these tests start threads and sockets, and a problem there should not take the other fcl-web tests down with it;
  • tcwsclienthelpers.pp (loopback servers, instrumented transport, probe classes) and five test units, tcwsclient{basic,pump,peer,callbacks,free}.pp, 44 tests.

They port the standalone regression harness from the fpc-devel thread (37 scenarios plus the pump-first and interrupt-race cases; originally written by me, extended by Roger Olsson) to fpcunit. Every scenario is covered; four were split into two tests where they checked independent things. Because fpcunit runs everything in one process, a few things differ from the harness:

  • a per-test watchdog (30 s) ends the process with exit code 99 and a HUNG: line naming the test, instead of letting a run hang;
  • the test servers bind 127.0.0.1:0 and join their accept and connection threads before they are freed (TWebSocketServer.StopServer itself does not wait for its accept thread), so nothing from one test can run into the next;
  • callbacks under test are held until the operation that must overlap them (Free, reconnect, disconnect) has provably started;
  • readiness is polled against deadlines instead of fixed sleeps;
  • TLS tests are reported as ignored when no OpenSSL library can be loaded.

One case is weaker than its name in the harness suggested: the race between a completing read and Terminate cannot be forced from outside the unit, so the test is named for what it checks (TestPayloadDuringTerminateLeavesConsistentState).

The probe classes keep the memory of destroyed connections and clients on purpose (FreeInstance override), so that a use after destruction is counted instead of crashing; the helpers unit says so in its header.

Validation, on this machine, 2026-09-21, fresh output directory per build:

  • aarch64-win64, FPC 3.3.1 compiler of unmodified main 8604d19b11 with the !1565 (merged) websocket sources via -Fu (in fcl-web/src/websocket, fcl-net, fcl-base and openssl, 8604d19b11 is identical to the !1565 (merged) base 1364760964): five runs, 44 run, 0 errors, 0 failures, 3 ignored (no OpenSSL here), about 15 s each.
  • aarch64-linux (WSL Ubuntu 24.04, OpenSSL 3.0.13), FPC 3.3.1 whose fcl-web, fcl-net and openssl sources are identical to main 8604d19b11 (the compiler itself carries unrelated local changes): five runs, 44 run, 0 errors, 0 failures, 0 ignored, about 16 s each.
  • Windows and Linux runs partly ran at the same time on the same machine.
  • Not shown: that the tests fail without !1565 (merged); they do not compile there.

Build, from an empty directory:

fpc -MObjFPC -Sh -O1 -gl -Fu<fpc>/packages/fcl-web/src/websocket -Fu<fpc>/packages/fcl-web/tests -FE. -FU. <fpc>/packages/fcl-web/tests/testwebsocketclient.lpr
./testwebsocketclient --all --format=plain

Evidence (build logs, all runs, scripts): websocket-mr1565-fpcunit-20260921-logs.zip, SHA-256 278f729917fc6d13109950562b22954a50c867a3918b9c0ac7b6d47e7d99601a

I have no commit rights; this is a proposal.

Merge request reports

Loading
Loading