Compare commits

..

12 Commits

Author SHA1 Message Date
Gus Cairo 047d270acf
Merge d597722cca into 3d21b85af4 2025-04-14 13:29:26 +00:00
Gus Cairo d597722cca Replace sleep in tests with waiter channel handler 2025-04-14 14:28:52 +01:00
Gus Cairo c90c6432fd Add tests 2025-04-14 14:28:52 +01:00
Gus Cairo 08a31ceb2f Call param configurator when wrapping an existing NWConnection 2025-04-14 14:28:52 +01:00
Gus Cairo 9e6e4ed7ab Turn vars into lets 2025-04-14 14:28:52 +01:00
Gus Cairo 7a8dcde582 Add tests 2025-04-14 14:28:52 +01:00
Gus Cairo b37cc8bd40 Add missing call to configurator to NIOTSManagedListenerChannel 2025-04-14 14:28:52 +01:00
Gus Cairo d61bf6d098 Add missing configurator method to the NIOTSListenerBootstrap 2025-04-14 14:28:52 +01:00
Gus Cairo f129546483 Add missed initialization of the configurator to StateManagedListenerChannel 2025-04-14 14:28:52 +01:00
Gus Cairo fca19c5367 Undo NWParameters as inout in configurator closure
NWParameters is a class, so we don't need it to be inout when passing it to the configurator closure
2025-04-14 14:28:52 +01:00
Gus Cairo 1f354a871f Add NWParameters configurator to bootstraps 2025-04-14 14:28:52 +01:00
Rick Newton-Rogers 3d21b85af4
Enable Swift 6.1 jobs in CI (#232)
Motivation:

Swift 6.1 has been released, we should add it to our CI coverage.

Modifications:

Add additional Swift 6.1 jobs where appropriate in main.yml,
pull_request.yml

Result:

Improved test coverage.
2025-04-14 10:52:43 +01:00
7 changed files with 83 additions and 25 deletions

View File

@ -14,6 +14,7 @@ jobs:
linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error"
linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error"
linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_6_1_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"

View File

@ -17,6 +17,7 @@ jobs:
linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error"
linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error"
linux_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_6_1_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"

View File

@ -140,7 +140,7 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
internal var allowLocalEndpointReuse = false
internal var multipathServiceType: NWParameters.MultipathServiceType = .disabled
private let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
internal let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
var parameters: NWParameters {
let parameters = NWParameters(dtls: self.tlsOptions, udp: self.udpOptions)

View File

@ -164,7 +164,7 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
/// An `EventLoopPromise` that will be succeeded or failed when a connection attempt succeeds or fails.
internal var connectPromise: EventLoopPromise<Void>?
private let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
internal let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
internal var parameters: NWParameters {
let parameters = NWParameters(tls: self.tlsOptions, tcp: self.tcpOptions)

View File

@ -83,6 +83,8 @@ internal protocol StateManagedNWConnectionChannel: StateManagedChannel where Act
var multipathServiceType: NWParameters.MultipathServiceType { get }
var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)? { get }
func setChannelSpecificOption0<Option: ChannelOption>(option: Option, value: Option.Value) throws
func getChannelSpecificOption0<Option: ChannelOption>(option: Option) throws -> Option.Value
@ -242,6 +244,7 @@ extension StateManagedNWConnectionChannel {
connection.betterPathUpdateHandler = self.betterPathHandler
connection.viabilityUpdateHandler = self.viabilityUpdateHandler
connection.pathUpdateHandler = self.pathChangedHandler(newPath:)
self.nwParametersConfigurator?(connection.parameters)
connection.start(queue: self.connectionQueue)
}

View File

@ -18,7 +18,7 @@ import XCTest
import Network
import NIOCore
import NIOEmbedded
import NIOTransportServices
@testable import NIOTransportServices
import NIOConcurrencyHelpers
import Foundation
@ -372,34 +372,58 @@ final class NIOTSBootstrapTests: XCTestCase {
XCTAssertEqual(try connectionChannel.getOption(NIOTSChannelOptions.multipathServiceType).wait(), .handover)
}
func testNWParametersConfigurator() throws {
let group = NIOTSEventLoopGroup()
defer {
try! group.syncShutdownGracefully()
func testNWParametersConfigurator() async throws {
final class WaitForConnectionHandler: ChannelInboundHandler, Sendable {
typealias InboundIn = Never
let connectionPromise: EventLoopPromise<Void>
init(connectionPromise: EventLoopPromise<Void>) {
self.connectionPromise = connectionPromise
}
func channelActive(context: ChannelHandlerContext) {
self.connectionPromise.succeed()
}
}
let group = NIOTSEventLoopGroup(loopCount: 1)
let configuratorListenerCounter = NIOLockedValueBox(0)
let configuratorConnectionCounter = NIOLockedValueBox(0)
let waitForConnectionHandler = WaitForConnectionHandler(
connectionPromise: group.next().makePromise()
)
let listenerChannel = try NIOTSListenerBootstrap(group: group)
let listenerChannel = try await NIOTSListenerBootstrap(group: group)
.childChannelInitializer { connectionChannel in
connectionChannel.eventLoop.makeCompletedFuture {
try connectionChannel.pipeline.syncOperations.addHandler(waitForConnectionHandler)
}
}
.configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 }
}
.bind(host: "localhost", port: 0)
.wait()
.get()
let connectionChannel: Channel = try NIOTSConnectionBootstrap(group: group)
let connectionChannel: Channel = try await NIOTSConnectionBootstrap(group: group)
.configureNWParameters { _ in
configuratorConnectionCounter.withLockedValue { $0 += 1 }
}
.connect(to: listenerChannel.localAddress!)
.wait()
.get()
try listenerChannel.close().wait()
try connectionChannel.close().wait()
// Wait for the server to activate the connection channel to the client.
try await waitForConnectionHandler.connectionPromise.futureResult.get()
XCTAssertEqual(1, configuratorListenerCounter.withLockedValue { $0 })
try await listenerChannel.close().get()
try await connectionChannel.close().get()
XCTAssertEqual(2, configuratorListenerCounter.withLockedValue { $0 })
XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
try await group.shutdownGracefully()
}
}

View File

@ -233,34 +233,63 @@ final class NIOTSDatagramConnectionChannelTests: XCTestCase {
XCTAssertNoThrow(try connection.close().wait())
}
func testNWParametersConfigurator() throws {
let group = NIOTSEventLoopGroup()
defer {
try! group.syncShutdownGracefully()
func testNWParametersConfigurator() async throws {
final class WaitForConnectionHandler: ChannelInboundHandler, Sendable {
typealias InboundIn = Never
let connectionPromise: EventLoopPromise<Void>
init(connectionPromise: EventLoopPromise<Void>) {
self.connectionPromise = connectionPromise
}
func channelActive(context: ChannelHandlerContext) {
self.connectionPromise.succeed()
}
}
let group = NIOTSEventLoopGroup(loopCount: 1)
let configuratorListenerCounter = NIOLockedValueBox(0)
let configuratorConnectionCounter = NIOLockedValueBox(0)
let waitForConnectionHandler = WaitForConnectionHandler(
connectionPromise: group.next().makePromise()
)
let listenerChannel = try NIOTSDatagramListenerBootstrap(group: group)
let listenerChannel = try await NIOTSDatagramListenerBootstrap(group: group)
.childChannelInitializer { connectionChannel in
connectionChannel.eventLoop.makeCompletedFuture {
try connectionChannel.pipeline.syncOperations.addHandler(waitForConnectionHandler)
}
}
.configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 }
}
.bind(host: "localhost", port: 0)
.wait()
.get()
let connectionChannel: Channel = try NIOTSDatagramBootstrap(group: group)
let connectionChannel: Channel = try await NIOTSDatagramBootstrap(group: group)
.configureNWParameters { _ in
configuratorConnectionCounter.withLockedValue { $0 += 1 }
}
.connect(to: listenerChannel.localAddress!)
.wait()
.get()
try listenerChannel.close().wait()
try connectionChannel.close().wait()
// Need to write something so the server can activate the connection channel: this is UDP,
// so there is no handshaking that happens and thus the server cannot know that the
// connection has been established and the channel can be activated.
try await connectionChannel.writeAndFlush(ByteBuffer(bytes: [42]))
XCTAssertEqual(1, configuratorListenerCounter.withLockedValue { $0 })
// Wait for the server to activate the connection channel to the client.
try await waitForConnectionHandler.connectionPromise.futureResult.get()
try await listenerChannel.close().get()
try await connectionChannel.close().get()
XCTAssertEqual(2, configuratorListenerCounter.withLockedValue { $0 })
XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
try await group.shutdownGracefully()
}
func testCanExtractTheConnection() throws {