Skip to content

[Windows] Compile the low-hanging test targets#3663

Open
jakepetroules wants to merge 4 commits into
apple:mainfrom
jakepetroules:windows-tests-compile
Open

[Windows] Compile the low-hanging test targets#3663
jakepetroules wants to merge 4 commits into
apple:mainfrom
jakepetroules:windows-tests-compile

Conversation

@jakepetroules

Copy link
Copy Markdown
Member

Motivation

Follow-up to #3649 (all non-test targets now build on Windows). This gets the bulk of the test targets compiling on Windows so we can start moving toward running them in CI.

Of the 16 test targets, 6 already compiled unchanged. This brings 8 more to a clean compile, leaving only two as dedicated follow-ups:

  • NIOPosixTests — large, many distinct Winsock/POSIX issues; deserves its own PR.
  • NIOFoundationCompatTests — a missing required module 'CNIOPosix' issue to investigate separately.

The changes are compile-only — they don't aim to make the tests pass on Windows yet. Verified by building each target on a Windows ARM64 VM; not yet wired into CI (CI still builds products only, since the two deferred targets would fail --build-tests).

What's here

Three commits:

  1. Make Posix.close available on Windows — it was gated out only because it sat inside the socket-syscalls #if !os(Windows) block (next to shutdown), even though its body already handled Windows. Define sysClose = _close and lift close(descriptor:) out of that block. No behavior change off Windows.
  2. Compile the low-hanging test targets — a gate-out-plus-minimal-shim approach:
    • A tiny #if os(Windows) usleep shim (backed by Sleep), once per affected target, plus a Windows branch for the #error C-library check.
    • Real Windows implementations for the temp-file/pipe test helpers rather than stubs: withPipe_pipe, openTemporaryFile_mktemp_s + _sopen_s, createTemporaryDirectory → a GUID + CreateDirectoryW.
    • Gate out genuinely-unavailable test logic behind #if !os(Windows): System.enumerateInterfaces, ChannelOptions.socket(IPPROTO_IP, IP_TTL), mkfifo-based tests, the POSIX-stat-shaped FileInfoTests, the S_IFSOCK/DT_* conversion tests, and the openat oflag-bit test.
    • Two Windows-only shim tweaks make the NIOFS OpenOptions gap values and Errno.noData @_spi(Testing) public, matching how swift-system exposes the equivalents elsewhere (the tests reach them via an SPI import).
    • The NIOHTTP1Tests and NIOPosixTests copies of TestUtils.swift are intentional duplicates and get identical Windows helper implementations to stay in sync.
  3. Document why SocketOption's integer API is unavailable on Windows — comment-only: WinSDK imports the socket option level/name constants as enumeration cases, not plain integers, so they don't fit the integer SocketOptionLevel/SocketOptionName typealiases.

Notes for reviewers

  • No behavior change off Windows: every change is behind #if os(Windows) / #if !os(Windows); the one shared edit (a test buffer typed CChar instead of CInterop.PlatformChar) is identical on POSIX.
  • The usleep shim is duplicated per target rather than shared: there's no test-only support target these all depend on (the shared deps, NIOCore/NIOTestUtils, are shipping libraries). It can be centralised later if desired.

`Posix.close(descriptor:)` was gated out on Windows only because it sat inside
the `#if !os(Windows)` block of socket syscalls (next to `Posix.shutdown`),
even though its body already handled Windows (reading `errno` via `_get_errno`).

Define the `sysClose` alias as `_close` on Windows (alongside the existing
`_read`/`_write`/etc. aliases) and lift `close(descriptor:)` out of the
`#if !os(Windows)` block so it compiles on all platforms. `shutdown` and the
socket calls remain gated. No behavior change off Windows: `close` was already
compiled there.
Gets 8 more test targets compiling on Windows (NIOTestUtilsTests,
NIOConcurrencyHelpersTests, NIOCoreTests, NIOEmbeddedTests, NIOHTTP1Tests,
NIOFSTests, NIOFSIntegrationTests, NIOFSFoundationCompatTests), joining the 6
that already did. NIOPosixTests and NIOFoundationCompatTests (a `CNIOPosix`
module issue) are left as follow-ups.

The changes are compile-only; they do not aim to make the tests functional yet.
Following a gate-out-plus-minimal-shim approach:

- Add a tiny `#if os(Windows)` `usleep` shim (backed by `Sleep`) once per
  affected test target, and a Windows branch to the `#error` C-library check in
  NIOConcurrencyHelpersTests.
- Implement the temp-file/pipe test helpers on Windows rather than stubbing
  them: `withPipe` via `_pipe`, `openTemporaryFile` via `_mktemp_s` + `_sopen_s`,
  and `createTemporaryDirectory` via a GUID plus `CreateDirectoryW`. `Posix.close`
  is used unconditionally now that it is available on Windows (preceding commit).
- Gate test logic that relies on genuinely-unavailable APIs behind
  `#if !os(Windows)`: `System.enumerateInterfaces`, `ChannelOptions.socket`
  with `IPPROTO_IP`/`IP_TTL`, `mkfifo`-based tests, the POSIX-`stat`-shaped
  `FileInfoTests`, the `S_IFSOCK`/`DT_*` conversion tests, and the `openat`
  oflag-bit test.
- Gate the `Data(contentsOf:maximumSizeAllowed:)` test with the same condition
  the library uses for that initializer.
- In SyscallTests, type the xattr buffer as `CChar` (what the API takes;
  identical to `PlatformChar` off Windows) rather than `CInterop.PlatformChar`.

The `usleep` shim is duplicated once per affected test target rather than shared:
there is no test-only support target these all depend on (the only shared
dependencies, NIOCore and NIOTestUtils, are shipping libraries), and adding one
is out of scope for this compile-only change. It can be centralised later.

The `NIOHTTP1Tests` and `NIOPosixTests` copies of `TestUtils.swift` are
intentional duplicates; both get the same Windows helper implementations to stay
in sync (NIOPosixTests's full compile remains a follow-up).

Two Windows-only library shim tweaks make the NIOFS `OpenOptions` gap values and
`Errno.noData` `@_spi(Testing) public`, matching the accessibility of the
swift-system equivalents on other platforms so the tests' SPI import can reach
them.

No behavior change off Windows: every change is guarded by `#if os(Windows)` /
`#if !os(Windows)`, and the one shared edit (`PlatformChar` -> `CChar`) is
identical on POSIX.
…ndows

`ChannelOptions.Types.SocketOption.init(level:name:)`, `ChannelOptions.socket`,
and the `socket(_:_:)` option accessor are gated `#if !os(Windows)` with no
stated reason. Document it: on Windows, WinSDK imports the socket option
level/name constants (`IPPROTO_IP`, `IP_TTL`, `SO_REUSEADDR`, …) as enumeration
cases rather than plain integers, so they don't fit the integer
`SocketOptionLevel`/`SocketOptionName` typealiases the integer-based API uses
(see `NIOBSDSocket.OptionLevel.ipv6` reading `IPPROTO_IPV6.rawValue`). Windows
callers use the typed `NIOBSDSocket.Option` accessors instead. Comment-only.
Comment thread Sources/NIOCore/ChannelOption.swift
Comment thread Sources/NIOCore/ChannelOption.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants