【发布时间】:2022-01-23 13:10:24
【问题描述】:
我有一个可与 UI 组件配合使用的 XCTest。我尝试使用 SwiftNIO 在 xctext 函数中打开一个服务器套接字。
我采用了 echo 服务器示例 from here。为了进行肮脏的测试,我简化并删除了带有硬编码值的参数。
import XCTest
import NIOCore
import NIOPosix
private final class EchoHandler: ChannelInboundHandler {
public typealias InboundIn = ByteBuffer
public typealias OutboundOut = ByteBuffer
public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
// As we are not really interested getting notified on success or failure we just pass nil as promise to
// reduce allocations.
context.write(data, promise: nil)
}
// Flush it out. This can make use of gathering writes if multiple buffers are pending
public func channelReadComplete(context: ChannelHandlerContext) {
context.flush()
}
public func errorCaught(context: ChannelHandlerContext, error: Error) {
print("error: ", error)
// As we are not really interested getting notified on success or failure we just pass nil as promise to
// reduce allocations.
context.close(promise: nil)
}
}
class MyXCTests: XCTestCase {
var app: XCUIApplication!
override func setUpWithError() throws {
continueAfterFailure = false
app = XCUIApplication()
// Catch system alerts such as "allow connecting to Wi-fi network"
addUIInterruptionMonitor(withDescription: "System Dialog") { (alert) -> Bool in
alert.buttons["Join"].tap()
return true
}
}
override func tearDownWithError() throws {
}
func testXYZ() throws {
app.launch()
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
let bootstrap = ServerBootstrap(group: group)
// Specify backlog and enable SO_REUSEADDR for the server itself
.serverChannelOption(ChannelOptions.backlog, value: 256)
.serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
// Set the handlers that are appled to the accepted Channels
.childChannelInitializer { channel in
// Ensure we don't read faster than we can write by adding the BackPressureHandler into the pipeline.
channel.pipeline.addHandler(BackPressureHandler()).flatMap { v in
channel.pipeline.addHandler(EchoHandler())
}
}
// Enable SO_REUSEADDR for the accepted Channels
.childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.childChannelOption(ChannelOptions.maxMessagesPerRead, value: 16)
.childChannelOption(ChannelOptions.recvAllocator, value: AdaptiveRecvByteBufferAllocator())
defer {
try! group.syncShutdownGracefully()
}
let channel = try { () -> Channel in
return try bootstrap.bind(host: "0.0.0.0", port: 1234).wait()
}()
print("============= Server started and listening on \(channel.localAddress!)")
// then some XCTest code which works here was cut from this snippet
}
测试运行正确,它也打印
============= Server started and listening on [IPv4]0.0.0.0/0.0.0.0:1234
但实际上 EchoClient from here 不起作用
swift run NIOEchoClient localhost 1234 1785
[0/0] Build complete!
Please enter line to send to the server
dfsdfd
Swift/ErrorType.swift:200: Fatal error: Error raised at top level: NIOPosix.NIOConnectionError(host: "localhost", port: 1234, dnsAError: nil, dnsAAAAError: nil, connectionErrors: [NIOPosix.SingleConnectionFailure(target: [IPv6]localhost/::1:1234, error: connection reset (error set): Connection refused (errno: 61)), NIOPosix.SingleConnectionFailure(target: [IPv4]localhost/127.0.0.1:1234, error: connection reset (error set): Connection refused (errno: 61))])
[1] 28213 trace trap swift run NIOEchoClient localhost 1234
监听套接字也无法使用
sudo lsof -PiTCP -sTCP:LISTEN
我也在尝试 UITestEntitlements 将 com.apple.security.app-sandbox 设置为 false。
有没有办法允许来自 XCTest 的服务器套接字?
最初我试图嵌入一个 Swift-GRPC 端点,以允许循环控制器中的硬件进行更细粒度的控制。目的是使用命令行 xcodebuild 启动 XCTest,这反过来又启动了一个长时间运行的测试,但不是用 Swift 编写的测试代码,而是在测试过程之外通过一个 grpc 端点。
由于 grpc 端点不起作用,我将问题归结为上述问题。
任何人有提示,如何解决这个问题,或者提示为什么永远无法在 XCTest 应用程序中打开服务器套接字,请不要犹豫,在这里回复。
【问题讨论】:
标签: ios swift xctest swift-nio