From 2daed115cfb701bb7fa27f6abcaaa0e73d7d0c5e Mon Sep 17 00:00:00 2001 From: Natik Gadzhi Date: Wed, 2 Aug 2023 17:27:31 -0700 Subject: [PATCH 1/4] Add unit tests for NWWaitingHandler Motivation: Closes #589. Since we already have a public initializer for NIOTSNetworkEvents.WaitingForConnectivity, we should add unit tests for the handler now that it's straightforward. Modifications: The tests are in their own file `Tests/NWWaitingHandlerTests.swift`. --- .../NWWaitingHandlerTests.swift | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift diff --git a/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift new file mode 100644 index 000000000..ebbb8519d --- /dev/null +++ b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the AsyncHTTPClient open source project +// +// Copyright (c) 2023 Apple Inc. and the AsyncHTTPClient project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if canImport(Network) +@testable import AsyncHTTPClient +import Network +import NIOCore +import NIOTransportServices +import NIOEmbedded +import NIOSSL +import XCTest + +@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) +class NWWaitingHandlerTests: XCTestCase { + + class MockRequester: HTTPConnectionRequester { + var waitingForConnectivityCalled = false + var connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID? = nil + var transientError: NWError? = nil + + func http1ConnectionCreated(_: AsyncHTTPClient.HTTP1Connection) { + } + + func http2ConnectionCreated(_: AsyncHTTPClient.HTTP2Connection, maximumStreams: Int) { + } + + func failedToCreateHTTPConnection(_: AsyncHTTPClient.HTTPConnectionPool.Connection.ID, error: Error) { + } + + func waitingForConnectivity(_ connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID, error: Error) { + self.waitingForConnectivityCalled = true + self.connectionID = connectionID + self.transientError = error as? NWError + } + } + + func testWaitingHandlerInvokesWaitingForConnectivity() { + let requester = MockRequester() + let connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID = 1 + let waitingEventHandler = NWWaitingHandler(requester: requester, connectionID: connectionID) + let embedded = EmbeddedChannel(handlers: [waitingEventHandler]) + + embedded.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.WaitingForConnectivity(transientError: .dns(1))) + + XCTAssertTrue(requester.waitingForConnectivityCalled, "Expected the handler to invoke .waitingForConnectivity on the requester") + XCTAssertEqual(requester.connectionID, connectionID, "Expected the handler to pass connectionID to requester") + XCTAssertEqual(requester.transientError, NWError.dns(1)) + } + + func testWaitingHandlerDoesNotInvokeWaitingForConnectionOnUnrelatedErrors() { + let requester = MockRequester() + let waitingEventHandler = NWWaitingHandler(requester: requester, connectionID: 1) + let embedded = EmbeddedChannel(handlers: [waitingEventHandler]) + embedded.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.BetterPathAvailable()) + + XCTAssertFalse(requester.waitingForConnectivityCalled, "Should not call .waitingForConnectitivy on unrelated events") + } + + func testWaitingHandlerPassesTheEventDownTheContext() { + let requester = MockRequester() + let waitingEventHandler = NWWaitingHandler(requester: requester, connectionID: 1) + let tlsEventsHandler = TLSEventsHandler(deadline: nil) + let embedded = EmbeddedChannel(handlers: [waitingEventHandler, tlsEventsHandler]) + + embedded.pipeline.fireErrorCaught(NIOSSLError.handshakeFailed(BoringSSLError.wantConnect)) + XCTAssertThrowsError(try XCTUnwrap(tlsEventsHandler.tlsEstablishedFuture).wait()) { + XCTAssertEqual($0 as? NIOSSLError, .handshakeFailed(BoringSSLError.wantConnect)) + } + } +} + +#endif + From f3a3ef03f0e825923773d4f5d850e87f5a1707fe Mon Sep 17 00:00:00 2001 From: Natik Gadzhi Date: Sun, 13 Aug 2023 15:00:38 -0700 Subject: [PATCH 2/4] Bump swift-nio-transport-services to 1.13.0 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 1f2f0046f..4d8986e60 100644 --- a/Package.swift +++ b/Package.swift @@ -25,7 +25,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.22.0"), .package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.19.0"), .package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.13.0"), - .package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.11.4"), + .package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.13.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.4.4"), .package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), From 4efea4c2086ffcbb51039b97698019a1f1d10d5f Mon Sep 17 00:00:00 2001 From: Natik Gadzhi Date: Mon, 14 Aug 2023 10:49:54 -0700 Subject: [PATCH 3/4] SwiftFormat@0.48.8 --- .../NWWaitingHandlerTests.swift | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift index ebbb8519d..9a1fa7223 100644 --- a/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift +++ b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift @@ -16,28 +16,24 @@ @testable import AsyncHTTPClient import Network import NIOCore -import NIOTransportServices import NIOEmbedded import NIOSSL +import NIOTransportServices import XCTest @available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) class NWWaitingHandlerTests: XCTestCase { - class MockRequester: HTTPConnectionRequester { var waitingForConnectivityCalled = false - var connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID? = nil - var transientError: NWError? = nil + var connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID? + var transientError: NWError? + + func http1ConnectionCreated(_: AsyncHTTPClient.HTTP1Connection) {} + + func http2ConnectionCreated(_: AsyncHTTPClient.HTTP2Connection, maximumStreams: Int) {} + + func failedToCreateHTTPConnection(_: AsyncHTTPClient.HTTPConnectionPool.Connection.ID, error: Error) {} - func http1ConnectionCreated(_: AsyncHTTPClient.HTTP1Connection) { - } - - func http2ConnectionCreated(_: AsyncHTTPClient.HTTP2Connection, maximumStreams: Int) { - } - - func failedToCreateHTTPConnection(_: AsyncHTTPClient.HTTPConnectionPool.Connection.ID, error: Error) { - } - func waitingForConnectivity(_ connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID, error: Error) { self.waitingForConnectivityCalled = true self.connectionID = connectionID @@ -50,9 +46,9 @@ class NWWaitingHandlerTests: XCTestCase { let connectionID: AsyncHTTPClient.HTTPConnectionPool.Connection.ID = 1 let waitingEventHandler = NWWaitingHandler(requester: requester, connectionID: connectionID) let embedded = EmbeddedChannel(handlers: [waitingEventHandler]) - + embedded.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.WaitingForConnectivity(transientError: .dns(1))) - + XCTAssertTrue(requester.waitingForConnectivityCalled, "Expected the handler to invoke .waitingForConnectivity on the requester") XCTAssertEqual(requester.connectionID, connectionID, "Expected the handler to pass connectionID to requester") XCTAssertEqual(requester.transientError, NWError.dns(1)) @@ -81,4 +77,3 @@ class NWWaitingHandlerTests: XCTestCase { } #endif - From 9fcf553b81088ecd3665b39c574086314bad7921 Mon Sep 17 00:00:00 2001 From: Natik Gadzhi Date: Mon, 14 Aug 2023 10:53:15 -0700 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: David Nadoba --- Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift index 9a1fa7223..967a7da40 100644 --- a/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift +++ b/Tests/AsyncHTTPClientTests/NWWaitingHandlerTests.swift @@ -60,7 +60,7 @@ class NWWaitingHandlerTests: XCTestCase { let embedded = EmbeddedChannel(handlers: [waitingEventHandler]) embedded.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.BetterPathAvailable()) - XCTAssertFalse(requester.waitingForConnectivityCalled, "Should not call .waitingForConnectitivy on unrelated events") + XCTAssertFalse(requester.waitingForConnectivityCalled, "Should not call .waitingForConnectivity on unrelated events") } func testWaitingHandlerPassesTheEventDownTheContext() { @@ -71,7 +71,7 @@ class NWWaitingHandlerTests: XCTestCase { embedded.pipeline.fireErrorCaught(NIOSSLError.handshakeFailed(BoringSSLError.wantConnect)) XCTAssertThrowsError(try XCTUnwrap(tlsEventsHandler.tlsEstablishedFuture).wait()) { - XCTAssertEqual($0 as? NIOSSLError, .handshakeFailed(BoringSSLError.wantConnect)) + XCTAssertEqualTypeAndValue($0, NIOSSLError.handshakeFailed(BoringSSLError.wantConnect)) } } }