From 61f1220bd7a81be95f8ad305673896d3cf440752 Mon Sep 17 00:00:00 2001 From: Zhennan Zhou Date: Sat, 27 Jan 2024 23:54:04 -0800 Subject: [PATCH] fix various formatting issue --- .../LCLPing/ICMP/ICMPChannelHandlers.swift | 47 +- Sources/LCLPing/TestUtils/Rewritable.swift | 7 +- .../HTTPIntegrationTests.swift | 656 +++++++++--------- 3 files changed, 354 insertions(+), 356 deletions(-) diff --git a/Sources/LCLPing/ICMP/ICMPChannelHandlers.swift b/Sources/LCLPing/ICMP/ICMPChannelHandlers.swift index 0115539..39deae6 100644 --- a/Sources/LCLPing/ICMP/ICMPChannelHandlers.swift +++ b/Sources/LCLPing/ICMP/ICMPChannelHandlers.swift @@ -87,7 +87,7 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { self.timerScheduler.schedule(delay: self.configuration.timeout, key: sequenceNum) { [weak self, context] in if let self = self, !self.seqToResponse.keys.contains(sequenceNum) { - print("[ICMPDuplexer][\(#function)]: packet #\(sequenceNum) timed out") + logger.debug("[ICMPDuplexer][\(#function)]: packet #\(sequenceNum) timed out") self.responseSeqNumSet.insert(sequenceNum) context.eventLoop.execute { context.fireChannelRead(self.wrapInboundOut(.timeout(sequenceNum))) @@ -95,19 +95,19 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { } } } - print("[ICMPDuplexer][\(#function)]: schedule timer for # \(sequenceNum) for \(self.configuration.timeout) second") + logger.debug("[ICMPDuplexer][\(#function)]: schedule timer for # \(sequenceNum) for \(self.configuration.timeout) second") } private func closeWhenComplete(context: ChannelHandlerContext) { if self.seqToRequest.count == self.configuration.count && self.responseSeqNumSet.count == self.configuration.count { - print("[ICMPDuplexer]: Ping finished. Closing all channels") + logger.debug("[ICMPDuplexer]: Ping finished. Closing all channels") context.close(mode: .all, promise: nil) } } func channelRead(context: ChannelHandlerContext, data: NIOAny) { guard self.state.isOperational else { - print("[ICMPDuplexer][\(#function)]: drop data: \(data) because channel is not in operational state") + logger.debug("[ICMPDuplexer][\(#function)]: drop data: \(data) because channel is not in operational state") return } @@ -117,11 +117,11 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { let code = icmpResponse.code let sequenceNum = icmpResponse.sequenceNum let identifier = icmpResponse.idenifier - print("[ICMPDuplexer][\(#function)]: received icmp response with type: \(type), code: \(code), sequence number: \(sequenceNum), identifier: \(identifier)") + logger.debug("[ICMPDuplexer][\(#function)]: received icmp response with type: \(type), code: \(code), sequence number: \(sequenceNum), identifier: \(identifier)") if self.responseSeqNumSet.contains(sequenceNum) { let pingResponse: PingResponse = self.seqToResponse[sequenceNum] == nil ? .timeout(sequenceNum) : .duplicated(sequenceNum) - print("[ICMPDuplexer][\(#function)]: response for #\(sequenceNum) is \(self.seqToResponse[sequenceNum] == nil ? "timeout" : "duplicate")") + logger.debug("[ICMPDuplexer][\(#function)]: response for #\(sequenceNum) is \(self.seqToResponse[sequenceNum] == nil ? "timeout" : "duplicate")") context.fireChannelRead(self.wrapInboundOut(pingResponse)) closeWhenComplete(context: context) return @@ -281,13 +281,13 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { func channelActive(context: ChannelHandlerContext) { switch self.state { case .operational: - print("[ICMPDuplexer][\(#function)]: Channel already active") + logger.debug("[ICMPDuplexer][\(#function)]: Channel already active") break case .error: logger.error("[ICMPDuplexer][\(#function)]: in an incorrect state: \(state)") assertionFailure("[\(#function)]: in an incorrect state: \(state)") case .inactive: - print("[ICMPDuplexer][\(#function)]: Channel active") + logger.debug("[ICMPDuplexer][\(#function)]: Channel active") context.fireChannelActive() self.state = .operational } @@ -301,7 +301,7 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { self.seqToRequest.removeAll() self.seqToResponse.removeAll() self.timerScheduler.reset() - print("[ICMPDuplexer][\(#function)]: Channel inactive") + logger.debug("[ICMPDuplexer][\(#function)]: Channel inactive") case .error: break case .inactive: @@ -312,7 +312,7 @@ internal final class ICMPDuplexer: ChannelDuplexHandler { func errorCaught(context: ChannelHandlerContext, error: Error) { guard self.state.isOperational else { - print("[ICMPDuplexer]: already in error state. ignore error \(error)") + logger.debug("[ICMPDuplexer]: already in error state. ignore error \(error)") return } self.state = .error @@ -347,13 +347,13 @@ internal final class IPDecoder: ChannelInboundHandler { func channelActive(context: ChannelHandlerContext) { switch self.state { case .operational: - print("[IPDecoder][\(#function)]: Channel already active") + logger.debug("[IPDecoder][\(#function)]: Channel already active") break case .error: logger.error("[IPDecoder][\(#function)] in an incorrect state: \(state)") assertionFailure("[IPDecoder][\(#function)] in an incorrect state: \(state)") case .inactive: - print("[IPDecoder][\(#function)]: Channel active") + logger.debug("[IPDecoder][\(#function)]: Channel active") context.fireChannelActive() self.state = .operational } @@ -362,26 +362,25 @@ internal final class IPDecoder: ChannelInboundHandler { func channelInactive(context: ChannelHandlerContext) { switch self.state { case .operational: - print("[IPDecoder][\(#function)]: Channel inactive") + logger.debug("[IPDecoder][\(#function)]: Channel inactive") context.fireChannelInactive() self.state = .inactive case .error: break case .inactive: - print("[IPDecoder][\(#function)]: received inactive signal when channel is already in inactive state.") + logger.debug("[IPDecoder][\(#function)]: received inactive signal when channel is already in inactive state.") assertionFailure("[IPDecoder][\(#function)]: received inactive signal when channel is already in inactive state.") } } func channelRead(context: ChannelHandlerContext, data: NIOAny) { guard self.state.isOperational else { - print("[IPDecoder][\(#function)]: drop data: \(data) because channel is not in operational state") + logger.debug("[IPDecoder][\(#function)]: drop data: \(data) because channel is not in operational state") return } let addressedBuffer = self.unwrapInboundIn(data) var buffer = addressedBuffer.data - print(buffer.readableBytesView) #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) let ipv4Header: IPv4Header do { @@ -392,7 +391,7 @@ internal final class IPDecoder: ChannelInboundHandler { } let version = ipv4Header.versionAndHeaderLength & 0xF0 if version != 0x40 { - print("received version: \(version)") + logger.debug("received version: \(version)") context.fireErrorCaught(PingError.invalidIPVersion) return } @@ -410,7 +409,7 @@ internal final class IPDecoder: ChannelInboundHandler { func errorCaught(context: ChannelHandlerContext, error: Error) { guard self.state.isOperational else { - print("[IPDecoder]: already in error state. ignore error \(error)") + logger.debug("[IPDecoder]: already in error state. ignore error \(error)") return } @@ -443,13 +442,13 @@ internal final class ICMPDecoder: ChannelInboundHandler { func channelActive(context: ChannelHandlerContext) { switch self.state { case .operational: - print("[ICMPDecoder][\(#function)]: Channel already active") + logger.debug("[ICMPDecoder][\(#function)]: Channel already active") break case .error: logger.error("[ICMPDecoder][\(#function)] in an incorrect state: \(state)") assertionFailure("[\(#function)] in an incorrect state: \(state)") case .inactive: - print("[ICMPDecoder][\(#function)]: Channel active") + logger.debug("[ICMPDecoder][\(#function)]: Channel active") context.fireChannelActive() self.state = .operational } @@ -458,7 +457,7 @@ internal final class ICMPDecoder: ChannelInboundHandler { func channelInactive(context: ChannelHandlerContext) { switch self.state { case .operational: - print("[ICMPDecoder][\(#function)]: Channel inactive") + logger.debug("[ICMPDecoder][\(#function)]: Channel inactive") context.fireChannelInactive() self.state = .inactive case .error: @@ -471,7 +470,7 @@ internal final class ICMPDecoder: ChannelInboundHandler { func channelRead(context: ChannelHandlerContext, data: NIOAny) { guard self.state.isOperational else { - print("[ICMPDecoder]: drop data: \(data) because channel is not in operational state") + logger.debug("[ICMPDecoder]: drop data: \(data) because channel is not in operational state") return } @@ -484,12 +483,12 @@ internal final class ICMPDecoder: ChannelInboundHandler { return } context.fireChannelRead(self.wrapInboundOut(icmpResponseHeader)) - print("[ICMPDecoder][\(#function)] finish decoding icmp header: \(icmpResponseHeader)") + logger.debug("[ICMPDecoder][\(#function)] finish decoding icmp header: \(icmpResponseHeader)") } func errorCaught(context: ChannelHandlerContext, error: Error) { guard self.state.isOperational else { - print("[ICMPDecoder]: already in error state. ignore error \(error)") + logger.debug("[ICMPDecoder]: already in error state. ignore error \(error)") return } diff --git a/Sources/LCLPing/TestUtils/Rewritable.swift b/Sources/LCLPing/TestUtils/Rewritable.swift index 847cfbe..f5c1996 100644 --- a/Sources/LCLPing/TestUtils/Rewritable.swift +++ b/Sources/LCLPing/TestUtils/Rewritable.swift @@ -58,7 +58,7 @@ extension AddressedEnvelope: Rewritable where DataType == ByteBuffer { func rewrite(newValues: [PartialKeyPath> : AnyObject]) -> NIOCore.AddressedEnvelope { return AddressedEnvelope( remoteAddress: newValues[\.remoteAddress] as? SocketAddress ?? self.remoteAddress, - data: data.rewrite(newValues: newValues[\AddressedEnvelope.data] as? [RewriteData] ?? [RewriteData(index: 0, byte: 0x55)]) + data: data.rewrite(newValues: newValues[\AddressedEnvelope.data] as? [RewriteData] ?? []) ) } } @@ -66,17 +66,16 @@ extension AddressedEnvelope: Rewritable where DataType == ByteBuffer { extension ByteBuffer { func rewrite(newValues: ByteBuffer) -> NIOCore.ByteBuffer { - print("[ByteBuffer Rewrite]: received new value: \(newValues.readableBytesView)") return ByteBuffer(buffer: newValues) } func rewrite(newValues: [RewriteData]) -> ByteBuffer { - print("[ByteBuffer Rewrite]: received new value: \(newValues)") + logger.debug("[ByteBuffer Rewrite]: received new value: \(newValues)") var newBuffer = ByteBuffer(buffer: self) for newValue in newValues { newBuffer.setBytes(newValue.byte.data, at: newValue.index) } - print("ByteBuffer Rewrite: rewritten as \(newBuffer.readableBytesView)") + logger.debug("ByteBuffer Rewrite: rewritten as \(newBuffer.readableBytesView)") return newBuffer } } diff --git a/Tests/IntegrationTests/HTTPIntegrationTests.swift b/Tests/IntegrationTests/HTTPIntegrationTests.swift index 1be07c6..d6b4ae0 100644 --- a/Tests/IntegrationTests/HTTPIntegrationTests.swift +++ b/Tests/IntegrationTests/HTTPIntegrationTests.swift @@ -17,354 +17,354 @@ import NIOCore #if INTEGRATION_TEST && (os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || swift(>=5.7)) final class HTTPIntegrationTests: XCTestCase { - private func runTest( - networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected, - pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) - ) async throws -> (PingState, PingSummary?) { - switch pingConfig.type { - case .http(let httpOptions): - var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) - try await httpPing.start(with: pingConfig) - return (httpPing.pingStatus, httpPing.summary) - default: - XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") - } - return (PingState.error, nil) - } - - func testfullyConnectedNetwork() async throws { - let (pingStatus, pingSummary) = try await runTest() - switch pingStatus { - case .finished: - XCTAssertEqual(pingSummary?.totalCount, 10) - XCTAssertEqual(pingSummary?.details.isEmpty, false) - XCTAssertEqual(pingSummary?.duplicates.count, 0) - XCTAssertEqual(pingSummary?.timeout.count, 0) - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + private func runTest( + networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected, + pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) + ) async throws -> (PingState, PingSummary?) { + switch pingConfig.type { + case .http(let httpOptions): + var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) + try await httpPing.start(with: pingConfig) + return (httpPing.pingStatus, httpPing.summary) + default: + XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") + } + return (PingState.error, nil) + } - func testFullyDisconnectedNetwork() async throws { - let fullyDisconnected = TrafficControllerChannelHandler.NetworkLinkConfiguration.fullyDisconnected - let (pingStatus, pingSummary) = try await runTest(networkLinkConfig: fullyDisconnected) - switch pingStatus { - case .finished: - for i in 0..<10 { - XCTAssertEqual(pingSummary?.timeout.contains(UInt16(i)), true) - } - XCTAssertEqual(pingSummary?.totalCount, 10) - XCTAssertEqual(pingSummary?.details.isEmpty, true) - XCTAssertEqual(pingSummary?.duplicates.count, 0) - XCTAssertEqual(pingSummary?.timeout.count, 10) - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testfullyConnectedNetwork() async throws { + let (pingStatus, pingSummary) = try await runTest() + switch pingStatus { + case .finished: + XCTAssertEqual(pingSummary?.totalCount, 10) + XCTAssertEqual(pingSummary?.details.isEmpty, false) + XCTAssertEqual(pingSummary?.duplicates.count, 0) + XCTAssertEqual(pingSummary?.timeout.count, 0) + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testInvalidIPURL() async throws { - let expectedError = PingError.invalidIPv4URL - do { - let pingConfig = LCLPing.PingConfiguration(type: .http(.init()), endpoint: .ipv4("ww.invalid-url.^&*", 8080)) - let _ = try await runTest(pingConfig: pingConfig) - XCTFail("Expect throwing PingError.invalidIPv4URL") - } catch { - XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) - } - } + func testFullyDisconnectedNetwork() async throws { + let fullyDisconnected = TrafficControllerChannelHandler.NetworkLinkConfiguration.fullyDisconnected + let (pingStatus, pingSummary) = try await runTest(networkLinkConfig: fullyDisconnected) + switch pingStatus { + case .finished: + for i in 0..<10 { + XCTAssertEqual(pingSummary?.timeout.contains(UInt16(i)), true) + } + XCTAssertEqual(pingSummary?.totalCount, 10) + XCTAssertEqual(pingSummary?.details.isEmpty, true) + XCTAssertEqual(pingSummary?.duplicates.count, 0) + XCTAssertEqual(pingSummary?.timeout.count, 10) + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMissingHostInURL() async throws { - let expectedError = PingError.httpMissingHost - do { - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("127.0.0.1", 8080)) - let _ = try await runTest(pingConfig: pingConfig) - XCTFail("Expect throwing PingError.httpMissingHost") - } catch { - XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) - } - } + func testInvalidIPURL() async throws { + let expectedError = PingError.invalidIPv4URL + do { + let pingConfig = LCLPing.PingConfiguration(type: .http(.init()), endpoint: .ipv4("ww.invalid-url.^&*", 8080)) + let _ = try await runTest(pingConfig: pingConfig) + XCTFail("Expect throwing PingError.invalidIPv4URL") + } catch { + XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) + } + } - func testMissingHTTPSchemaInURL() async throws { - let expectedError = PingError.httpMissingSchema - do { - let pingConfig = LCLPing.PingConfiguration(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("someOtherSchema://127.0.0.1", 8080)) - let _ = try await runTest(pingConfig: pingConfig) - XCTFail("Expect throwing PingError.httpMissingSchema") - } catch { - XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) - } - } + func testMissingHostInURL() async throws { + let expectedError = PingError.httpMissingHost + do { + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("127.0.0.1", 8080)) + let _ = try await runTest(pingConfig: pingConfig) + XCTFail("Expect throwing PingError.httpMissingHost") + } catch { + XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) + } + } - func testUnknownHost() async throws { - let expectedError = PingError.sendPingFailed(IOError(errnoCode: 61, reason: "connection reset (error set)")) - let pingConfig = LCLPing.PingConfiguration(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 9090)) - do { - let _ = try await runTest(pingConfig: pingConfig) - XCTFail("Expect throwing ") - } catch { - print("error: \(error)") - XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) - } - } + func testMissingHTTPSchemaInURL() async throws { + let expectedError = PingError.httpMissingSchema + do { + let pingConfig = LCLPing.PingConfiguration(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("someOtherSchema://127.0.0.1", 8080)) + let _ = try await runTest(pingConfig: pingConfig) + XCTFail("Expect throwing PingError.httpMissingSchema") + } catch { + XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) + } + } - func testMinorInOutPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.1, outPacketLoss: 0.1) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testUnknownHost() async throws { + let expectedError = PingError.sendPingFailed(IOError(errnoCode: 61, reason: "connection reset (error set)")) + let pingConfig = LCLPing.PingConfiguration(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 9090)) + do { + let _ = try await runTest(pingConfig: pingConfig) + XCTFail("Expect throwing ") + } catch { + print("error: \(error)") + XCTAssertEqual(expectedError.localizedDescription, error.localizedDescription) + } + } - func testCorrectStatusCode() async throws { - for param in [(statusCode: 200, ok: true), (statusCode: 201, ok: true), (statusCode: 301, ok: false), (statusCode: 404, ok: false), (statusCode: 410, ok: false), (statusCode: 500, ok: false), (statusCode: 505, ok: false)] { - var httpOptions = LCLPing.PingConfiguration.HTTPOptions() - let desiredHeaders = [ - "Status-Code": String(param.statusCode) - ] - httpOptions.httpHeaders = desiredHeaders - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1", 8080), count: 3) - let expectedSequenceNumbers: Set = [0, 1, 2] - let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) - switch pingStatus { - case .finished: - XCTAssertEqual(pingSummary?.totalCount, 3) - if param.ok { - XCTAssertEqual(pingSummary?.details.count, 3) - pingSummary?.details.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - } - } else { - XCTAssertEqual(pingSummary?.errors.count, 3) - switch param.statusCode { - case 300...399: - pingSummary?.errors.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - XCTAssertEqual(element.reason, PingError.httpRedirect.localizedDescription) - } - case 400...499: - pingSummary?.errors.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - XCTAssertEqual(element.reason, PingError.httpClientError.localizedDescription) - } - case 500...599: - pingSummary?.errors.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - XCTAssertEqual(element.reason, PingError.httpServerError.localizedDescription) - } - default: - XCTFail("HTTP Test failed with unknown status code \(param.statusCode)") - } - } + func testMinorInOutPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.1, outPacketLoss: 0.1) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } - } + func testCorrectStatusCode() async throws { + for param in [(statusCode: 200, ok: true), (statusCode: 201, ok: true), (statusCode: 301, ok: false), (statusCode: 404, ok: false), (statusCode: 410, ok: false), (statusCode: 500, ok: false), (statusCode: 505, ok: false)] { + var httpOptions = LCLPing.PingConfiguration.HTTPOptions() + let desiredHeaders = [ + "Status-Code": String(param.statusCode) + ] + httpOptions.httpHeaders = desiredHeaders + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1", 8080), count: 3) + let expectedSequenceNumbers: Set = [0, 1, 2] + let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) + switch pingStatus { + case .finished: + XCTAssertEqual(pingSummary?.totalCount, 3) + if param.ok { + XCTAssertEqual(pingSummary?.details.count, 3) + pingSummary?.details.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + } + } else { + XCTAssertEqual(pingSummary?.errors.count, 3) + switch param.statusCode { + case 300...399: + pingSummary?.errors.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + XCTAssertEqual(element.reason, PingError.httpRedirect.localizedDescription) + } + case 400...499: + pingSummary?.errors.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + XCTAssertEqual(element.reason, PingError.httpClientError.localizedDescription) + } + case 500...599: + pingSummary?.errors.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + XCTAssertEqual(element.reason, PingError.httpServerError.localizedDescription) + } + default: + XCTFail("HTTP Test failed with unknown status code \(param.statusCode)") + } + } - func testBasicServerTiming() async throws { - var httpOptions = LCLPing.PingConfiguration.HTTPOptions() - let desiredHeaders = [ - "Status-Code": "200", - "Use-Empty-Server-Timing": "False", - "Number-Of-Metrics": "1" - ] - httpOptions.useServerTiming = true - httpOptions.httpHeaders = desiredHeaders - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) - let expectedSequenceNumbers: Set = [0, 1, 2] - let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) - switch pingStatus { - case .finished: - XCTAssertEqual(pingSummary?.totalCount, 3) - XCTAssertEqual(pingSummary?.details.count, 3) - pingSummary?.details.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - } - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } + } - func testEmptyServerTimingField() async throws { - var httpOptions = LCLPing.PingConfiguration.HTTPOptions() - let desiredHeaders = [ - "Status-Code": "200", - "Use-Empty-Server-Timing": "True", - "Number-Of-Metrics": "1" - ] - httpOptions.useServerTiming = true - httpOptions.httpHeaders = desiredHeaders - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) - let expectedSequenceNumbers: Set = [0, 1, 2] - let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) - switch pingStatus { - case .finished: - XCTAssertEqual(pingSummary?.totalCount, 3) - XCTAssertEqual(pingSummary?.details.count, 3) - pingSummary?.details.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - } - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testBasicServerTiming() async throws { + var httpOptions = LCLPing.PingConfiguration.HTTPOptions() + let desiredHeaders = [ + "Status-Code": "200", + "Use-Empty-Server-Timing": "False", + "Number-Of-Metrics": "1" + ] + httpOptions.useServerTiming = true + httpOptions.httpHeaders = desiredHeaders + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) + let expectedSequenceNumbers: Set = [0, 1, 2] + let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) + switch pingStatus { + case .finished: + XCTAssertEqual(pingSummary?.totalCount, 3) + XCTAssertEqual(pingSummary?.details.count, 3) + pingSummary?.details.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + } + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMultipleServerTimingFields() async throws { - var httpOptions = LCLPing.PingConfiguration.HTTPOptions() - let desiredHeaders = [ - "Status-Code": "200", - "Use-Empty-Server-Timing": "True", - "Number-Of-Metrics": "4" - ] - httpOptions.useServerTiming = true - httpOptions.httpHeaders = desiredHeaders - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) - let expectedSequenceNumbers: Set = [0, 1, 2] - let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) - switch pingStatus { - case .finished: - XCTAssertEqual(pingSummary?.totalCount, 3) - XCTAssertEqual(pingSummary?.details.count, 3) - pingSummary?.details.forEach { element in - XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) - } - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testEmptyServerTimingField() async throws { + var httpOptions = LCLPing.PingConfiguration.HTTPOptions() + let desiredHeaders = [ + "Status-Code": "200", + "Use-Empty-Server-Timing": "True", + "Number-Of-Metrics": "1" + ] + httpOptions.useServerTiming = true + httpOptions.httpHeaders = desiredHeaders + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) + let expectedSequenceNumbers: Set = [0, 1, 2] + let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) + switch pingStatus { + case .finished: + XCTAssertEqual(pingSummary?.totalCount, 3) + XCTAssertEqual(pingSummary?.details.count, 3) + pingSummary?.details.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + } + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testCancelBeforeTestStarts() async throws { - let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) - switch pingConfig.type { - case .http(let httpOptions): - var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) - httpPing.stop() - try await httpPing.start(with: pingConfig) - switch httpPing.pingStatus { - case .stopped: - XCTAssertNil(httpPing.summary) - default: - XCTFail("Invalid HTTP Ping state. Should be .stopped, but is \(httpPing.pingStatus)") - } - default: - XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") - } - } - - @MainActor - func testCancelDuringTest() async throws { - for waitSecond in [2, 4, 5, 6, 7, 9] { - let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) - switch pingConfig.type { - case .http(let httpOptions): - var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) + func testMultipleServerTimingFields() async throws { + var httpOptions = LCLPing.PingConfiguration.HTTPOptions() + let desiredHeaders = [ + "Status-Code": "200", + "Use-Empty-Server-Timing": "True", + "Number-Of-Metrics": "4" + ] + httpOptions.useServerTiming = true + httpOptions.httpHeaders = desiredHeaders + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(httpOptions), endpoint: .ipv4("http://127.0.0.1/server-timing", 8080), count: 3) + let expectedSequenceNumbers: Set = [0, 1, 2] + let (pingStatus, pingSummary) = try await runTest(pingConfig: pingConfig) + switch pingStatus { + case .finished: + XCTAssertEqual(pingSummary?.totalCount, 3) + XCTAssertEqual(pingSummary?.details.count, 3) + pingSummary?.details.forEach { element in + XCTAssertEqual(expectedSequenceNumbers.contains(element.seqNum), true) + } + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - Task { - try await Task.sleep(nanoseconds: UInt64(waitSecond) * 1_000_000_000) - httpPing.stop() - } + func testCancelBeforeTestStarts() async throws { + let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) + switch pingConfig.type { + case .http(let httpOptions): + var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) + httpPing.stop() + try await httpPing.start(with: pingConfig) + switch httpPing.pingStatus { + case .stopped: + XCTAssertNil(httpPing.summary) + default: + XCTFail("Invalid HTTP Ping state. Should be .stopped, but is \(httpPing.pingStatus)") + } + default: + XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") + } + } - try await httpPing.start(with: pingConfig) + @MainActor + func testCancelDuringTest() async throws { + for waitSecond in [2, 4, 5, 6, 7, 9] { + let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080)) + switch pingConfig.type { + case .http(let httpOptions): + var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) - switch httpPing.pingStatus { - case .stopped: - XCTAssertNotNil(httpPing.summary?.totalCount) - XCTAssertLessThanOrEqual(httpPing.summary!.totalCount, waitSecond + 1) - XCTAssertEqual(httpPing.summary?.details.isEmpty, false) - XCTAssertEqual(httpPing.summary?.duplicates.count, 0) - XCTAssertEqual(httpPing.summary?.timeout.count, 0) - default: - XCTFail("Invalid HTTP Ping state. Should be .finished, but is \(httpPing.pingStatus)") - } - default: - XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") - } - } - } - - func testCancelAfterTestFinishes() async throws { - let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected - let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080), count: 3) - switch pingConfig.type { - case .http(let httpOptions): - var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) - try await httpPing.start(with: pingConfig) - httpPing.stop() - switch httpPing.pingStatus { - case .finished: - XCTAssertEqual(httpPing.summary?.totalCount, 3) - XCTAssertEqual(httpPing.summary?.details.isEmpty, false) - XCTAssertEqual(httpPing.summary?.duplicates.count, 0) - XCTAssertEqual(httpPing.summary?.timeout.count, 0) - default: - XCTFail("Invalid HTTP Ping state. Should be .finished, but is \(httpPing.pingStatus)") - } - default: - XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") - } - } + Task { + try await Task.sleep(nanoseconds: UInt64(waitSecond) * 1_000_000_000) + httpPing.stop() + } + + try await httpPing.start(with: pingConfig) + + switch httpPing.pingStatus { + case .stopped: + XCTAssertNotNil(httpPing.summary?.totalCount) + XCTAssertLessThanOrEqual(httpPing.summary!.totalCount, waitSecond + 1) + XCTAssertEqual(httpPing.summary?.details.isEmpty, false) + XCTAssertEqual(httpPing.summary?.duplicates.count, 0) + XCTAssertEqual(httpPing.summary?.timeout.count, 0) + default: + XCTFail("Invalid HTTP Ping state. Should be .finished, but is \(httpPing.pingStatus)") + } + default: + XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") + } + } + } + + func testCancelAfterTestFinishes() async throws { + let networkLinkConfig: TrafficControllerChannelHandler.NetworkLinkConfiguration = .fullyConnected + let pingConfig: LCLPing.PingConfiguration = .init(type: .http(LCLPing.PingConfiguration.HTTPOptions()), endpoint: .ipv4("http://127.0.0.1", 8080), count: 3) + switch pingConfig.type { + case .http(let httpOptions): + var httpPing = HTTPPing(httpOptions: httpOptions, networkLinkConfig: networkLinkConfig) + try await httpPing.start(with: pingConfig) + httpPing.stop() + switch httpPing.pingStatus { + case .finished: + XCTAssertEqual(httpPing.summary?.totalCount, 3) + XCTAssertEqual(httpPing.summary?.details.isEmpty, false) + XCTAssertEqual(httpPing.summary?.duplicates.count, 0) + XCTAssertEqual(httpPing.summary?.timeout.count, 0) + default: + XCTFail("Invalid HTTP Ping state. Should be .finished, but is \(httpPing.pingStatus)") + } + default: + XCTFail("Invalid PingConfig. Need HTTP, but received \(pingConfig.type)") + } + } - // FIXME: re-enable the following test after https://github.com/apple/swift-nio/issues/2612 is fixed + // FIXME: re-enable the following test after https://github.com/apple/swift-nio/issues/2612 is fixed - func testMediumInOutPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.4, outPacketLoss: 0.4) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testMediumInOutPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.4, outPacketLoss: 0.4) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMinorInPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.2) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testMinorInPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.2) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMinorOutPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(outPacketLoss: 0.2) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testMinorOutPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(outPacketLoss: 0.2) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMediumInPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.5) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testMediumInPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(inPacketLoss: 0.5) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } - func testMediumOutPacketDrop() async throws { - let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(outPacketLoss: 0.5) - let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) - switch pingStatus { - case .finished: - () - default: - XCTFail("HTTP Test failed with status \(pingStatus)") - } - } + func testMediumOutPacketDrop() async throws { + let networkLink = TrafficControllerChannelHandler.NetworkLinkConfiguration(outPacketLoss: 0.5) + let (pingStatus, _) = try await runTest(networkLinkConfig: networkLink) + switch pingStatus { + case .finished: + () + default: + XCTFail("HTTP Test failed with status \(pingStatus)") + } + } } #endif