Skip to content

Run threaded api-test SFTP/SCP tests on Windows#1058

Draft
yosuke-wolfssl wants to merge 6 commits into
wolfSSL:masterfrom
yosuke-wolfssl:fix/winTest
Draft

Run threaded api-test SFTP/SCP tests on Windows#1058
yosuke-wolfssl wants to merge 6 commits into
wolfSSL:masterfrom
yosuke-wolfssl:fix/winTest

Conversation

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor

Summary

Runs the 11 threaded echoserver+client tests in api-test (real SFTP/SCP
transport and rekey over a socket) on Windows for the first time, giving genuine
SFTP/SCP integration coverage under MSVC AddressSanitizer. Previously these tests
were stubbed out on Windows because the test harness's readiness handshake was
POSIX-only.

This is a follow-up to the windows-check.yml fix that made Windows CI actually
compile WOLFSSH_SSHD/SFTP/SCP/CERTS/X509 and run api-test + unit-test
under ASan. That restored compile and unit-level coverage; this PR adds the
integration coverage that was still missing.

Background / root cause

The threaded tests follow this shape:

InitTcpReady(&ready);
ThreadStart(echoserver_test, &ser, &serThread);  /* server thread */
WaitTcpReady(&ready);                             /* block until listening */
scp_client_connect(&ctx, &ssh, ready.port, cmd); /* connect to handed-back port */

The readiness handshake (block the client until the server is listening, then
hand back the bound port) was implemented only for POSIX threads. On MSVC
_POSIX_THREADS is undefined, so WaitTcpReady returned immediately and
SignalTcpReady never set ready->port — the client raced ahead and connected
to port 0, tripping AssertNotNull(ctx). Win32 threads themselves already worked
(ThreadStart uses _beginthreadex); only the readiness primitive was missing.

What changed

1. Win32 readiness primitive (wolfssh/test.h, examples/echoserver/echoserver.c)

Added a Win32 branch to the readiness primitive, mirroring the POSIX semantics:

  • tcp_ready gains a CRITICAL_SECTION + a manual-reset event HANDLE.
  • InitTcpReady / FreeTcpReady / WaitTcpReady and SignalTcpReady get
    #elif defined(USE_WINDOWS_API) branches.
  • WaitTcpReady uses a bounded 30s wait instead of an indefinite one: the signal
    fires right after listen(), so the real wait is sub-second, and a server that
    dies before signaling fails the test fast instead of hanging CI. On timeout the
    port stays 0 and the existing AssertNotNull(ctx) trips.
  • FreeTcpReady nulls the event handle after closing it so cleanup is idempotent.

All Win32 code is strictly additive (#elif USE_WINDOWS_API); the POSIX and
single-threaded branches are untouched, so non-Windows builds are unaffected.

2. Re-enable the stubbed tests (tests/api.c)

Dropped !defined(USE_WINDOWS_API) from the SFTP and SCP-rekey block guards so
the real test bodies compile and run on Windows. Also paired every InitTcpReady
with FreeTcpReady (api-test previously had 6 inits and 0 frees, unlike
testsuite.c/kex.c/sftp.c), releasing the new Windows event handle and
critical section as well as the pre-existing POSIX mutex/cond.

Tests that now run on Windows:

  • SFTP: SendReadPacket, PartialSend, ReKey, ReKey_NonBlock, Confinement,
    SetDefaultPath
  • SCP: ReKey, ReKey_NonBlock, ReKey_ToServer, ReKey_ToServer_NonBlock

3. Ephemeral port on Windows (wolfssh/test.h, tests/api.c, examples/echoserver/echoserver.c)

The tests passed -p 0 (OS-assigned ephemeral port) only on POSIX; on Windows
the server fell back to the fixed wolfSshPort because tcp_listen could not
read the bound port back. Reusing one fixed port across the serial networked
tests is the worst case for TIME_WAIT rebind on Windows, which (correctly) does
not set SO_REUSEADDR.

Let Windows use an ephemeral port like POSIX already does, so each test binds a
fresh port and never contends with a prior connection lingering in TIME_WAIT:

  • test.h: drop the USE_WINDOWS_API exclusion from the getsockname port
    readback (getsockname/ntohs/socklen_t are all available on Winsock).
  • tests/api.c: pass -p 0 on all platforms.
  • echoserver.c: reject -p 0 only for the standalone main driver, not the
    NO_MAIN_DRIVER test harness, so the Windows api-test server accepts an
    ephemeral port.

Testing

  • Non-Windows regression (macOS): the Win32 code is #elif USE_WINDOWS_API,
    so POSIX preprocessed output is unchanged. Rebuilt api-test + testsuite and
    ran under ASan+UBSan (-fsanitize=address,undefined -fno-omit-frame-pointer) —
    exit 0, no AddressSanitizer errors. (One pre-existing UBSan note at
    test.h:478, a gethostbyname misaligned char* load, is unrelated to this
    change.)
  • Windows: exercised by the windows-check.yml asan-tests job — the only
    place _WIN32 + features + threads + ASan combine. The 11 tests should now run
    green under MSVC ASan.

Scope / risk

  • Touches shared test infrastructure (test.h, echoserver.c) used by every
    example/test program, so the change is strictly additive
    (#elif USE_WINDOWS_API) with the POSIX/single-threaded branches unchanged.
  • Net effect on non-Windows: none.
  • Net effect on Windows: 11 networked tests go from stub to live SFTP/SCP
    transport + rekey coverage under AddressSanitizer.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Jun 24, 2026
Copilot AI review requested due to automatic review settings June 24, 2026 04:12
@yosuke-wolfssl yosuke-wolfssl marked this pull request as draft June 24, 2026 04:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@yosuke-wolfssl yosuke-wolfssl changed the title Fix/win test Run threaded api-test SFTP/SCP tests on Windows Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants