Replace sleep in tests with waiter channel handler

This commit is contained in:
Gus Cairo 2025-04-14 14:28:41 +01:00
parent c90c6432fd
commit d597722cca
2 changed files with 51 additions and 14 deletions

View File

@ -373,12 +373,34 @@ final class NIOTSBootstrapTests: XCTestCase {
}
func testNWParametersConfigurator() async throws {
let group = NIOTSEventLoopGroup()
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 await NIOTSListenerBootstrap(group: group)
.childChannelInitializer { connectionChannel in
connectionChannel.eventLoop.makeCompletedFuture {
try connectionChannel.pipeline.syncOperations.addHandler(waitForConnectionHandler)
}
}
.configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 }
}
@ -392,12 +414,8 @@ final class NIOTSBootstrapTests: XCTestCase {
.connect(to: listenerChannel.localAddress!)
.get()
// Need to wait for the connection channel to be activated. We cannot wait for the connect
// promise (`StateManagedNWConnectionChannel/connectPromise`) from here, because it is
// nulled out as soon as it's completed, and the listener channel doesn't wait on it either.
// If we don't wait, we can race with the connection channel's parameter configurator
// closure being run, and the assertion below would fail.
try await Task.sleep(for: .milliseconds(100))
// 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()

View File

@ -16,7 +16,7 @@
import XCTest
import Network
import NIOCore
@testable import NIOTransportServices
import NIOTransportServices
import Foundation
import NIOConcurrencyHelpers
@ -234,16 +234,34 @@ final class NIOTSDatagramConnectionChannelTests: XCTestCase {
}
func testNWParametersConfigurator() async throws {
let group = NIOTSEventLoopGroup()
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 await NIOTSDatagramListenerBootstrap(group: group)
// .childChannelInitializer { connectionChannel in
// print((connectionChannel as! NIOTSDatagramChannel).connectPromise)
// return connectionChannel.eventLoop.makeSucceededFuture(())
// }
.childChannelInitializer { connectionChannel in
connectionChannel.eventLoop.makeCompletedFuture {
try connectionChannel.pipeline.syncOperations.addHandler(waitForConnectionHandler)
}
}
.configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 }
}
@ -262,7 +280,8 @@ final class NIOTSDatagramConnectionChannelTests: XCTestCase {
// connection has been established and the channel can be activated.
try await connectionChannel.writeAndFlush(ByteBuffer(bytes: [42]))
try await Task.sleep(for: .milliseconds(100))
// 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()