Add tests

This commit is contained in:
Gus Cairo 2025-04-14 14:18:35 +01:00
parent 08a31ceb2f
commit c90c6432fd
2 changed files with 40 additions and 24 deletions

View File

@ -18,7 +18,7 @@ import XCTest
import Network import Network
import NIOCore import NIOCore
import NIOEmbedded import NIOEmbedded
import NIOTransportServices @testable import NIOTransportServices
import NIOConcurrencyHelpers import NIOConcurrencyHelpers
import Foundation import Foundation
@ -372,34 +372,40 @@ final class NIOTSBootstrapTests: XCTestCase {
XCTAssertEqual(try connectionChannel.getOption(NIOTSChannelOptions.multipathServiceType).wait(), .handover) XCTAssertEqual(try connectionChannel.getOption(NIOTSChannelOptions.multipathServiceType).wait(), .handover)
} }
func testNWParametersConfigurator() throws { func testNWParametersConfigurator() async throws {
let group = NIOTSEventLoopGroup() let group = NIOTSEventLoopGroup()
defer {
try! group.syncShutdownGracefully()
}
let configuratorListenerCounter = NIOLockedValueBox(0) let configuratorListenerCounter = NIOLockedValueBox(0)
let configuratorConnectionCounter = NIOLockedValueBox(0) let configuratorConnectionCounter = NIOLockedValueBox(0)
let listenerChannel = try NIOTSListenerBootstrap(group: group) let listenerChannel = try await NIOTSListenerBootstrap(group: group)
.configureNWParameters { _ in .configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 } configuratorListenerCounter.withLockedValue { $0 += 1 }
} }
.bind(host: "localhost", port: 0) .bind(host: "localhost", port: 0)
.wait() .get()
let connectionChannel: Channel = try NIOTSConnectionBootstrap(group: group) let connectionChannel: Channel = try await NIOTSConnectionBootstrap(group: group)
.configureNWParameters { _ in .configureNWParameters { _ in
configuratorConnectionCounter.withLockedValue { $0 += 1 } configuratorConnectionCounter.withLockedValue { $0 += 1 }
} }
.connect(to: listenerChannel.localAddress!) .connect(to: listenerChannel.localAddress!)
.wait() .get()
try listenerChannel.close().wait() // Need to wait for the connection channel to be activated. We cannot wait for the connect
try connectionChannel.close().wait() // 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))
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 }) XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
try await group.shutdownGracefully()
} }
} }

View File

@ -16,7 +16,7 @@
import XCTest import XCTest
import Network import Network
import NIOCore import NIOCore
import NIOTransportServices @testable import NIOTransportServices
import Foundation import Foundation
import NIOConcurrencyHelpers import NIOConcurrencyHelpers
@ -233,34 +233,44 @@ final class NIOTSDatagramConnectionChannelTests: XCTestCase {
XCTAssertNoThrow(try connection.close().wait()) XCTAssertNoThrow(try connection.close().wait())
} }
func testNWParametersConfigurator() throws { func testNWParametersConfigurator() async throws {
let group = NIOTSEventLoopGroup() let group = NIOTSEventLoopGroup()
defer {
try! group.syncShutdownGracefully()
}
let configuratorListenerCounter = NIOLockedValueBox(0) let configuratorListenerCounter = NIOLockedValueBox(0)
let configuratorConnectionCounter = NIOLockedValueBox(0) let configuratorConnectionCounter = NIOLockedValueBox(0)
let listenerChannel = try NIOTSDatagramListenerBootstrap(group: group) let listenerChannel = try await NIOTSDatagramListenerBootstrap(group: group)
// .childChannelInitializer { connectionChannel in
// print((connectionChannel as! NIOTSDatagramChannel).connectPromise)
// return connectionChannel.eventLoop.makeSucceededFuture(())
// }
.configureNWParameters { _ in .configureNWParameters { _ in
configuratorListenerCounter.withLockedValue { $0 += 1 } configuratorListenerCounter.withLockedValue { $0 += 1 }
} }
.bind(host: "localhost", port: 0) .bind(host: "localhost", port: 0)
.wait() .get()
let connectionChannel: Channel = try NIOTSDatagramBootstrap(group: group) let connectionChannel: Channel = try await NIOTSDatagramBootstrap(group: group)
.configureNWParameters { _ in .configureNWParameters { _ in
configuratorConnectionCounter.withLockedValue { $0 += 1 } configuratorConnectionCounter.withLockedValue { $0 += 1 }
} }
.connect(to: listenerChannel.localAddress!) .connect(to: listenerChannel.localAddress!)
.wait() .get()
try listenerChannel.close().wait() // Need to write something so the server can activate the connection channel: this is UDP,
try connectionChannel.close().wait() // 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 }) try await Task.sleep(for: .milliseconds(100))
try await listenerChannel.close().get()
try await connectionChannel.close().get()
XCTAssertEqual(2, configuratorListenerCounter.withLockedValue { $0 })
XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 }) XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
try await group.shutdownGracefully()
} }
func testCanExtractTheConnection() throws { func testCanExtractTheConnection() throws {