diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 746bf12..7a1ee3b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,6 +20,12 @@ jobs: linux_6_0_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" linux_nightly_next_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" linux_nightly_main_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" + windows_6_0_enabled: true + windows_nightly_6_1_enabled: true + windows_nightly_main_enabled: true + windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" macos-tests: name: macOS tests diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b8751fb..9226e21 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -24,6 +24,12 @@ jobs: linux_6_0_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" linux_nightly_next_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" linux_nightly_main_arguments_override: "-Xswiftc -strict-concurrency=complete --explicit-target-dependency-import-check error" + windows_6_0_enabled: true + windows_nightly_6_1_enabled: true + windows_nightly_main_enabled: true + windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" cxx-interop: name: Cxx interop diff --git a/Package.swift b/Package.swift index 7bcd778..04a0b7c 100644 --- a/Package.swift +++ b/Package.swift @@ -34,7 +34,7 @@ let package = Package( platforms: [.macOS(.v10_15), .macCatalyst(.v13), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)], products: [.library(name: "OpenAPIURLSession", targets: ["OpenAPIURLSession"])], dependencies: [ - .package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.8.2"), .package(url: "https://github.com/apple/swift-http-types", from: "1.0.0"), .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), ], @@ -50,14 +50,21 @@ let package = Package( ), .testTarget( name: "OpenAPIURLSessionTests", - dependencies: ["OpenAPIURLSession", .product(name: "NIOTestUtils", package: "swift-nio")], + dependencies: ["OpenAPIURLSession"], swiftSettings: swiftSettings ), ] ) +#if !os(Windows) // NIO not yet supported on Windows // Test-only dependencies. package.dependencies += [.package(url: "https://github.com/apple/swift-nio", from: "2.62.0")] +package.targets.forEach { target in + if target.name == "OpenAPIURLSessionTests" { + target.dependencies += [.product(name: "NIOTestUtils", package: "swift-nio")] + } +} +#endif // --- STANDARD CROSS-REPO SETTINGS DO NOT EDIT --- // for target in package.targets { diff --git a/README.md b/README.md index 4f43166..3f268c1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Use the transport with client code generated by [Swift OpenAPI Generator](https: ## Supported platforms and minimum versions -| macOS | Linux | iOS | tvOS | watchOS | visionOS | +| macOS | Linux, Windows | iOS | tvOS | watchOS | visionOS | | :-: | :-: | :-: | :-: | :-: | :-: | | ✅ 10.15+ | ✅ | ✅ 13+ | ✅ 13+ | ✅ 6+ | ✅ 1+ | diff --git a/Sources/OpenAPIURLSession/BufferedStream/Lock.swift b/Sources/OpenAPIURLSession/BufferedStream/Lock.swift index b6e82e2..077ce9f 100644 --- a/Sources/OpenAPIURLSession/BufferedStream/Lock.swift +++ b/Sources/OpenAPIURLSession/BufferedStream/Lock.swift @@ -30,10 +30,17 @@ import Darwin #elseif canImport(Glibc) import Glibc +#elseif os(Windows) +import WinSDK #endif +#if os(Windows) +@usableFromInline +typealias LockPrimitive = SRWLOCK +#else @usableFromInline typealias LockPrimitive = pthread_mutex_t +#endif @usableFromInline enum LockOperations {} @@ -43,35 +50,51 @@ extension LockOperations { static func create(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() + #if os(Windows) + InitializeSRWLock(mutex) + #else var attr = pthread_mutexattr_t() pthread_mutexattr_init(&attr) let err = pthread_mutex_init(mutex, &attr) precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") + #endif } @inlinable static func destroy(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() + #if os(Windows) + // SRWLOCK does not need to be freed + #else let err = pthread_mutex_destroy(mutex) precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") + #endif } @inlinable static func lock(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() + #if os(Windows) + AcquireSRWLockExclusive(mutex) + #else let err = pthread_mutex_lock(mutex) precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") + #endif } @inlinable static func unlock(_ mutex: UnsafeMutablePointer) { mutex.assertValidAlignment() + #if os(Windows) + ReleaseSRWLockExclusive(mutex) + #else let err = pthread_mutex_unlock(mutex) precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") + #endif } } diff --git a/Tests/OpenAPIURLSessionTests/NIOAsyncHTTP1TestServer.swift b/Tests/OpenAPIURLSessionTests/NIOAsyncHTTP1TestServer.swift index 20fb663..aad5f3d 100644 --- a/Tests/OpenAPIURLSessionTests/NIOAsyncHTTP1TestServer.swift +++ b/Tests/OpenAPIURLSessionTests/NIOAsyncHTTP1TestServer.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// +#if !os(Windows) // NIO not yet supported on Windows import NIOCore import NIOPosix import NIOHTTP1 @@ -93,3 +94,4 @@ extension AsyncTestHTTP1Server { } } +#endif diff --git a/Tests/OpenAPIURLSessionTests/TaskCancellationTests.swift b/Tests/OpenAPIURLSessionTests/TaskCancellationTests.swift index a5f4c86..73762c6 100644 --- a/Tests/OpenAPIURLSessionTests/TaskCancellationTests.swift +++ b/Tests/OpenAPIURLSessionTests/TaskCancellationTests.swift @@ -16,6 +16,7 @@ import Foundation import HTTPTypes import NIO +import NIOHTTP1 import OpenAPIRuntime import XCTest @testable import OpenAPIURLSession diff --git a/Tests/OpenAPIURLSessionTests/URLSessionTransportTests.swift b/Tests/OpenAPIURLSessionTests/URLSessionTransportTests.swift index 32ce86b..ffacd53 100644 --- a/Tests/OpenAPIURLSessionTests/URLSessionTransportTests.swift +++ b/Tests/OpenAPIURLSessionTests/URLSessionTransportTests.swift @@ -16,8 +16,10 @@ import Foundation import FoundationNetworking #endif import HTTPTypes +#if !os(Windows) // NIO not yet supported on Windows import NIO import NIOHTTP1 +#endif import OpenAPIRuntime import XCTest @testable import OpenAPIURLSession @@ -59,6 +61,7 @@ class URLSessionTransportConverterTests: XCTestCase { } } +#if !os(Windows) // NIO not yet supported on Windows // swift-format-ignore: AllPublicDeclarationsHaveDocumentation class URLSessionTransportBufferedTests: XCTestCase { var transport: URLSessionTransport! @@ -133,22 +136,6 @@ class URLSessionTransportStreamingTests: XCTestCase { #endif } -class URLSessionTransportPlatformSupportTests: XCTestCase { - func testDefaultsToStreamingIfSupported() { - if URLSessionTransport.Configuration.Implementation.platformSupportsStreaming { - guard case .streaming = URLSessionTransport.Configuration.Implementation.platformDefault else { - XCTFail() - return - } - } else { - guard case .buffering = URLSessionTransport.Configuration.Implementation.platformDefault else { - XCTFail() - return - } - } - } -} - func testHTTPRedirect( transport: any ClientTransport, requestBodyIterationBehavior: IterationBehavior, @@ -315,6 +302,23 @@ func testHTTPBasicPost(transport: any ClientTransport) async throws { group.cancelAll() } } +#endif + +class URLSessionTransportPlatformSupportTests: XCTestCase { + func testDefaultsToStreamingIfSupported() { + if URLSessionTransport.Configuration.Implementation.platformSupportsStreaming { + guard case .streaming = URLSessionTransport.Configuration.Implementation.platformDefault else { + XCTFail() + return + } + } else { + guard case .buffering = URLSessionTransport.Configuration.Implementation.platformDefault else { + XCTFail() + return + } + } + } +} class URLSessionTransportDebugLoggingTests: XCTestCase { func testDebugLoggingEnabled() {