From aa66da80fa1ea29d728ee093757f4fe5db89dca7 Mon Sep 17 00:00:00 2001 From: David Nadoba Date: Fri, 10 Feb 2023 15:13:21 +0100 Subject: [PATCH] Fix request head continuation misuse (#666) * Fix request head continuation misuse Fixes #664 * remove unused function * format & generate linux tests --- .../AsyncAwait/Transaction+StateMachine.swift | 4 +- .../TransactionTests+XCTest.swift | 1 + .../TransactionTests.swift | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift b/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift index 8700d6b..008f1f8 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift @@ -207,7 +207,9 @@ extension Transaction { self.state = .executing(context, .requestHeadSent, .waitingForResponseHead) return .none case .deadlineExceededWhileQueued(let continuation): - return .cancelAndFail(executor, continuation, with: HTTPClientError.deadlineExceeded) + let error = HTTPClientError.deadlineExceeded + self.state = .finished(error: error, nil) + return .cancelAndFail(executor, continuation, with: error) case .finished(error: .some, .none): return .cancel(executor) diff --git a/Tests/AsyncHTTPClientTests/TransactionTests+XCTest.swift b/Tests/AsyncHTTPClientTests/TransactionTests+XCTest.swift index 1902606..de63914 100644 --- a/Tests/AsyncHTTPClientTests/TransactionTests+XCTest.swift +++ b/Tests/AsyncHTTPClientTests/TransactionTests+XCTest.swift @@ -26,6 +26,7 @@ extension TransactionTests { static var allTests: [(String, (TransactionTests) -> () throws -> Void)] { return [ ("testCancelAsyncRequest", testCancelAsyncRequest), + ("testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask", testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask), ("testResponseStreamingWorks", testResponseStreamingWorks), ("testIgnoringResponseBodyWorks", testIgnoringResponseBodyWorks), ("testWriteBackpressureWorks", testWriteBackpressureWorks), diff --git a/Tests/AsyncHTTPClientTests/TransactionTests.swift b/Tests/AsyncHTTPClientTests/TransactionTests.swift index 7aee8c6..1ef0bfe 100644 --- a/Tests/AsyncHTTPClientTests/TransactionTests.swift +++ b/Tests/AsyncHTTPClientTests/TransactionTests.swift @@ -59,6 +59,55 @@ final class TransactionTests: XCTestCase { } } + func testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask() { + guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return } + XCTAsyncTest { + let embeddedEventLoop = EmbeddedEventLoop() + defer { XCTAssertNoThrow(try embeddedEventLoop.syncShutdownGracefully()) } + + var request = HTTPClientRequest(url: "https://localhost/") + request.method = .GET + var maybePreparedRequest: PreparedRequest? + XCTAssertNoThrow(maybePreparedRequest = try PreparedRequest(request)) + guard let preparedRequest = maybePreparedRequest else { + return XCTFail("Expected to have a request here.") + } + let (transaction, responseTask) = await Transaction.makeWithResultTask( + request: preparedRequest, + preferredEventLoop: embeddedEventLoop + ) + + let queuer = MockTaskQueuer() + transaction.requestWasQueued(queuer) + + transaction.deadlineExceeded() + + struct Executor: HTTPRequestExecutor { + func writeRequestBodyPart(_: NIOCore.IOData, request: AsyncHTTPClient.HTTPExecutableRequest, promise: NIOCore.EventLoopPromise?) { + XCTFail() + } + + func finishRequestBodyStream(_ task: AsyncHTTPClient.HTTPExecutableRequest, promise: NIOCore.EventLoopPromise?) { + XCTFail() + } + + func demandResponseBodyStream(_: AsyncHTTPClient.HTTPExecutableRequest) { + XCTFail() + } + + func cancelRequest(_ task: AsyncHTTPClient.HTTPExecutableRequest) { + task.fail(HTTPClientError.cancelled) + } + } + + transaction.willExecuteRequest(Executor()) + + await XCTAssertThrowsError(try await responseTask.value) { error in + XCTAssertEqualTypeAndValue(error, HTTPClientError.deadlineExceeded) + } + } + } + func testResponseStreamingWorks() { guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return } XCTAsyncTest {