swift-nio-transport-services/Tests/NIOTransportServicesTests/NIOTSSocketOptionsOnChannel...

225 lines
7.8 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
#if canImport(Network)
import XCTest
import NIOCore
import Network
@testable import NIOTransportServices
extension Channel {
private func getSocketOption(_ option: ChannelOptions.Types.SocketOption) -> EventLoopFuture<SocketOptionValue> {
self.getOption(option)
}
private func setSocketOption(
_ option: ChannelOptions.Types.SocketOption,
to value: SocketOptionValue
) -> EventLoopFuture<Void> {
self.setOption(option, value: value)
}
/// Asserts that a given socket option has a default value, that its value can be changed to a new value, and that it can then be
/// switched back.
fileprivate func assertOptionRoundTrips(
option: ChannelOptions.Types.SocketOption,
initialValue: SocketOptionValue,
testAlternativeValue: SocketOptionValue
) -> EventLoopFuture<Void> {
self.getSocketOption(option).flatMap { actualInitialValue in
XCTAssertEqual(actualInitialValue, initialValue)
return self.setSocketOption(option, to: testAlternativeValue)
}.flatMap {
self.getSocketOption(option)
}.flatMap { actualNewValue in
XCTAssertEqual(actualNewValue, testAlternativeValue)
return self.setSocketOption(option, to: initialValue)
}.flatMap {
self.getSocketOption(option)
}.map { returnedToValue in
XCTAssertEqual(returnedToValue, initialValue)
}
}
}
@available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 6, *)
class NIOTSSocketOptionsOnChannelTests: XCTestCase {
private var group: NIOTSEventLoopGroup!
override func setUp() {
self.group = NIOTSEventLoopGroup()
}
override func tearDown() {
XCTAssertNoThrow(try self.group.syncShutdownGracefully())
}
func assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption,
initialValue: SocketOptionValue,
testAlternativeValue: SocketOptionValue
) throws {
let listener = try NIOTSListenerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait()
defer {
XCTAssertNoThrow(try listener.close().wait())
}
let connector = try NIOTSConnectionBootstrap(group: group).connect(to: listener.localAddress!).wait()
defer {
XCTAssertNoThrow(try connector.close().wait())
}
XCTAssertNoThrow(
try listener.assertOptionRoundTrips(
option: option,
initialValue: initialValue,
testAlternativeValue: testAlternativeValue
).wait()
)
XCTAssertNoThrow(
try connector.assertOptionRoundTrips(
option: option,
initialValue: initialValue,
testAlternativeValue: testAlternativeValue
).wait()
)
}
func testNODELAY() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_NODELAY),
initialValue: 1,
testAlternativeValue: 0
)
}
func testNOPUSH() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_NOPUSH),
initialValue: 0,
testAlternativeValue: 1
)
}
func testNOOPT() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_NOOPT),
initialValue: 0,
testAlternativeValue: 1
)
}
func testKEEPCNT() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_KEEPCNT),
initialValue: 0,
testAlternativeValue: 5
)
}
func testKEEPALIVE() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_KEEPALIVE),
initialValue: 0,
testAlternativeValue: 5
)
}
func testKEEPINTVL() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_KEEPINTVL),
initialValue: 0,
testAlternativeValue: 5
)
}
func testMAXSEG() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_MAXSEG),
initialValue: 0,
testAlternativeValue: 5
)
}
func testCONNECTIONTIMEOUT() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_CONNECTIONTIMEOUT),
initialValue: 0,
testAlternativeValue: 5
)
}
func testRXT_CONNDROPTIME() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_RXT_CONNDROPTIME),
initialValue: 0,
testAlternativeValue: 5
)
}
func testRXT_FINDROP() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_RXT_FINDROP),
initialValue: 0,
testAlternativeValue: 1
)
}
func testSENDMOREACKS() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: IPPROTO_TCP, name: TCP_SENDMOREACKS),
initialValue: 0,
testAlternativeValue: 1
)
}
func testSO_KEEPALIVE() throws {
try self.assertChannelOptionAfterCreation(
option: ChannelOptions.Types.SocketOption(level: SOL_SOCKET, name: SO_KEEPALIVE),
initialValue: 0,
testAlternativeValue: 1
)
}
func testMultipleSocketOptions() throws {
let listener = try NIOTSListenerBootstrap(group: group)
.serverChannelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
.serverChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
.bind(host: "127.0.0.1", port: 0).wait()
defer {
XCTAssertNoThrow(try listener.close().wait())
}
let connector = try NIOTSConnectionBootstrap(group: group)
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
.channelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
.connect(to: listener.localAddress!).wait()
defer {
XCTAssertNoThrow(try connector.close().wait())
}
XCTAssertNoThrow(
XCTAssertEqual(1, try listener.getOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR)).wait())
)
XCTAssertNoThrow(
XCTAssertEqual(1, try listener.getOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY)).wait())
)
XCTAssertNoThrow(
XCTAssertEqual(1, try connector.getOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR)).wait())
)
XCTAssertNoThrow(
XCTAssertEqual(1, try connector.getOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY)).wait())
)
}
}
#endif