fpwebsocketclient shutdown tests
================================

Two standalone programs used to evaluate the "websocket safe shutdown"
patch against FPC trunk 695611fdb3. No external dependencies beyond FPC
itself; OpenSSL is optional (TLS scenarios are skipped without it).


wsshutdowntest.pas
------------------
Loopback harness. Drives FPC's own TWebSocketServer against
TWebsocketClient, so the real HTTP upgrade handshake runs.

Scenarios:

  1  upgrade handshake and echo
  2  repeated Execute/Terminate keeps the connection usable
  3  peer close notifies the owner and clears Active (exactly once)
  4  Terminate on an idle healthy connection, still usable afterwards
  5  TLS upgrade, echo and peer close
  6  partial frame stall over plain TCP
  7  partial frame stall over TLS
  8  Terminate called from the OnDisconnect callback
  9  healthy client sharing a pump with a stalled one

Scenarios 6 and 7 stage a peer that completes the upgrade, sends two bytes
of a frame header announcing a five byte payload, and then stays silent
without reading. That is the only situation in which the reader is in a
genuinely blocking read rather than a bounded select. Both peers park
instead of returning; if the peer keeps reading it will notice the FIN
that a client-side SHUT_RDWR produces and close, which releases the reader
for the wrong reason and makes the scenario pass spuriously.

The scenarios assert that the reader is actually inside a transport read
before terminating. TWSConnection.CheckIncoming is not virtual, but
GetTransport is, so the harness installs a delegating IWSTransport that
counts entries and exits of the blocking reads. (IWSTransport is declared
under {$INTERFACES CORBA}, so that wrapper is owned and freed explicitly,
not reference counted.)

Each scenario runs in its own process with an external timeout, because a
hanging call cannot report its own failure. A scenario that does not
finish is killed and reported as HUNG; the rest still run.

Usage:

  ./wsshutdowntest                 run all scenarios
  ./wsshutdowntest --scenario N    run one scenario in this process
  ./wsshutdowntest --pump-first    free the pump before an active client
                                   (expected to crash - it demonstrates
                                   the missing Notification override)

Exit code: number of scenarios that failed, hung or crashed.


shutdownwake.pas
----------------
Isolates one question with raw sockets, no websocket code involved: does
fpShutdown(SHUT_RDWR) release a thread already blocked in recv?

The reader publishes a flag as its last action before recv; the main
thread waits for that flag, waits a further settle interval, and verifies
the call has not already completed. Three rounds. If the shutdown does not
release the read, closesocket is tried next and that result is reported
too.

Exit code: 0 released in every scored round, 1 not released, 2 setup
failed or no round produced a valid measurement.


Building
--------
Point -Fu at the websocket sources of the tree you want to test, so the
same test binary can be built against a patched and an unpatched tree:

  fpc -Mobjfpc -Sh -O- -gl \
      -FE<outdir> -FU<outdir> \
      -Fu<fpc>/packages/fcl-web/src/websocket \
      wsshutdowntest.pas

  fpc -Mobjfpc -Sh -O- -gl -FE<outdir> -FU<outdir> shutdownwake.pas

On Windows the TLS scenarios need OpenSSL DLLs next to the executable or
on PATH. On aarch64-win64 FPC looks for libssl-3-arm64.dll and
libcrypto-3-arm64.dll specifically; without them those scenarios report
themselves as skipped rather than failing.


Results obtained with these programs
------------------------------------
Trunk 695611fdb3, two trees differing only by the patch:

                  linux unpatched  linux patched  win unpatched  win patched
  passed                3               7              3             5
  failed                3               2              2             0
  hung                  3               0              4             4

aarch64-linux is Ubuntu 24.04 with OpenSSL 3.0.13; aarch64-win64 uses the
ARM64 OpenSSL 3 DLLs. The two failures remaining with the patch on linux
are scenarios 8 and 9, which exist to demonstrate defects.

shutdownwake, same machines:

  linux: released after 0-2 ms, recv returns 0, 3 of 3 rounds
  win64: NOT released within 3000 ms, 3 of 3 rounds, fpShutdown returning 0
         closesocket then released it after 0 ms (recv=-1, WSAENOTSOCK)
