110 lines
3.5 KiB
Swift
110 lines
3.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftNIO open source project
|
|
//
|
|
// Copyright (c) 2019 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
|
|
// swift-tools-version:4.0
|
|
//
|
|
// swift-tools-version:4.0
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if canImport(Network)
|
|
import XCTest
|
|
import Network
|
|
import NIO
|
|
import NIOTransportServices
|
|
import NIOConcurrencyHelpers
|
|
import Foundation
|
|
|
|
@available(OSX 10.14, iOS 12.0, tvOS 12.0, *)
|
|
final class NIOTSBootstrapTests: XCTestCase {
|
|
var groupBag: [NIOTSEventLoopGroup]? = nil // protected by `self.lock`
|
|
let lock = Lock()
|
|
|
|
override func setUp() {
|
|
self.lock.withLock {
|
|
XCTAssertNil(self.groupBag)
|
|
self.groupBag = []
|
|
}
|
|
}
|
|
|
|
override func tearDown() {
|
|
XCTAssertNoThrow(try self.lock.withLock {
|
|
guard let groupBag = self.groupBag else {
|
|
XCTFail()
|
|
return
|
|
}
|
|
XCTAssertNoThrow(try groupBag.forEach {
|
|
XCTAssertNoThrow(try $0.syncShutdownGracefully())
|
|
})
|
|
self.groupBag = nil
|
|
})
|
|
}
|
|
|
|
func freshEventLoop() -> EventLoop {
|
|
let group: NIOTSEventLoopGroup = .init(loopCount: 1, defaultQoS: .default)
|
|
self.lock.withLock {
|
|
self.groupBag!.append(group)
|
|
}
|
|
return group.next()
|
|
}
|
|
|
|
func testBootstrapsTolerateFuturesFromDifferentEventLoopsReturnedInInitializers() throws {
|
|
let childChannelDone = self.freshEventLoop().makePromise(of: Void.self)
|
|
let serverChannelDone = self.freshEventLoop().makePromise(of: Void.self)
|
|
let serverChannel = try assertNoThrowWithValue(NIOTSListenerBootstrap(group: self.freshEventLoop())
|
|
.childChannelInitializer { channel in
|
|
channel.eventLoop.preconditionInEventLoop()
|
|
defer {
|
|
childChannelDone.succeed(())
|
|
}
|
|
return self.freshEventLoop().makeSucceededFuture(())
|
|
}
|
|
.serverChannelInitializer { channel in
|
|
channel.eventLoop.preconditionInEventLoop()
|
|
defer {
|
|
serverChannelDone.succeed(())
|
|
}
|
|
return self.freshEventLoop().makeSucceededFuture(())
|
|
}
|
|
.bind(host: "127.0.0.1", port: 0)
|
|
.wait())
|
|
defer {
|
|
XCTAssertNoThrow(try serverChannel.close().wait())
|
|
}
|
|
|
|
let client = try assertNoThrowWithValue(NIOTSConnectionBootstrap(group: self.freshEventLoop())
|
|
.channelInitializer { channel in
|
|
channel.eventLoop.preconditionInEventLoop()
|
|
return self.freshEventLoop().makeSucceededFuture(())
|
|
}
|
|
.connect(to: serverChannel.localAddress!)
|
|
.wait())
|
|
defer {
|
|
XCTAssertNoThrow(try client.syncCloseAcceptingAlreadyClosed())
|
|
}
|
|
XCTAssertNoThrow(try childChannelDone.futureResult.wait())
|
|
XCTAssertNoThrow(try serverChannelDone.futureResult.wait())
|
|
}
|
|
}
|
|
|
|
extension Channel {
|
|
func syncCloseAcceptingAlreadyClosed() throws {
|
|
do {
|
|
try self.close().wait()
|
|
} catch ChannelError.alreadyClosed {
|
|
/* we're happy with this one */
|
|
} catch let e {
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|