diff --git a/Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Waiter.swift b/Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Waiter.swift new file mode 100644 index 000000000..4220dc4c2 --- /dev/null +++ b/Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Waiter.swift @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the AsyncHTTPClient open source project +// +// Copyright (c) 2021 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 +// +//===----------------------------------------------------------------------===// + +import NIO + +extension HTTPConnectionPool { + struct RequestID: Hashable { + private let objectIdentifier: ObjectIdentifier + + init(_ request: HTTPScheduledRequest) { + self.objectIdentifier = ObjectIdentifier(request) + } + } + + struct Waiter { + var requestID: RequestID { + RequestID(self.request) + } + + var request: HTTPScheduledRequest + + private var eventLoopRequirement: EventLoop? { + switch self.request.eventLoopPreference.preference { + case .delegateAndChannel(on: let eventLoop), + .testOnly_exact(channelOn: let eventLoop, delegateOn: _): + return eventLoop + case .delegate(on: _), + .indifferent: + return nil + } + } + + init(request: HTTPScheduledRequest) { + self.request = request + } + + func canBeRun(on option: EventLoop) -> Bool { + guard let requirement = self.eventLoopRequirement else { + // if no requirement exists we can run on any EventLoop + return true + } + + return requirement === option + } + } +} diff --git a/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests+XCTest.swift b/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests+XCTest.swift new file mode 100644 index 000000000..22ac2329d --- /dev/null +++ b/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the AsyncHTTPClient open source project +// +// Copyright (c) 2018-2019 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 +// +//===----------------------------------------------------------------------===// +// +// HTTPConnectionPool+WaiterTests+XCTest.swift +// +import XCTest + +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension HTTPConnectionPool_WaiterTests { + static var allTests: [(String, (HTTPConnectionPool_WaiterTests) -> () throws -> Void)] { + return [ + ("testCanBeRunIfEventLoopIsSpecified", testCanBeRunIfEventLoopIsSpecified), + ("testCanBeRunIfNoEventLoopIsSpecified", testCanBeRunIfNoEventLoopIsSpecified), + ] + } +} diff --git a/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests.swift b/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests.swift new file mode 100644 index 000000000..c8ee47353 --- /dev/null +++ b/Tests/AsyncHTTPClientTests/HTTPConnectionPool+WaiterTests.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the AsyncHTTPClient open source project +// +// Copyright (c) 2021 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 +// +//===----------------------------------------------------------------------===// + +@testable import AsyncHTTPClient +import Logging +import NIO +import XCTest + +class HTTPConnectionPool_WaiterTests: XCTestCase { + func testCanBeRunIfEventLoopIsSpecified() { + let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) + + let theRightEL = eventLoopGroup.next() + let theFalseEL = eventLoopGroup.next() + + let mockRequest = MockScheduledRequest(eventLoopPreference: .init(.testOnly_exact(channelOn: theRightEL, delegateOn: theFalseEL))) + + let waiter = HTTPConnectionPool.Waiter(request: mockRequest) + + XCTAssertTrue(waiter.canBeRun(on: theRightEL)) + XCTAssertFalse(waiter.canBeRun(on: theFalseEL)) + } + + func testCanBeRunIfNoEventLoopIsSpecified() { + let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) + + let mockRequest = MockScheduledRequest(eventLoopPreference: .indifferent) + let waiter = HTTPConnectionPool.Waiter(request: mockRequest) + + for el in eventLoopGroup.makeIterator() { + XCTAssertTrue(waiter.canBeRun(on: el)) + } + } +} + +private class MockScheduledRequest: HTTPScheduledRequest { + init(eventLoopPreference: HTTPClient.EventLoopPreference) { + self.eventLoopPreference = eventLoopPreference + } + + var logger: Logger { preconditionFailure("Unimplemented") } + var connectionDeadline: NIODeadline { preconditionFailure("Unimplemented") } + let eventLoopPreference: HTTPClient.EventLoopPreference + + func requestWasQueued(_: HTTPRequestScheduler) { + preconditionFailure("Unimplemented") + } + + func fail(_: Error) { + preconditionFailure("Unimplemented") + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 8615a9ca2..a7c7ad1c7 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -36,6 +36,7 @@ import XCTest testCase(HTTPClientSOCKSTests.allTests), testCase(HTTPClientTests.allTests), testCase(HTTPConnectionPool_FactoryTests.allTests), + testCase(HTTPConnectionPool_WaiterTests.allTests), testCase(HTTPRequestStateMachineTests.allTests), testCase(LRUCacheTests.allTests), testCase(RequestBagTests.allTests),