Skip to content

Commit 562b6a0

Browse files
committed
[HTTPConnectionPool] Add HTTP/1.1 stress test
1 parent 50611a5 commit 562b6a0

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

Tests/AsyncHTTPClientTests/HTTPConnectionPoolTests+XCTest.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extension HTTPConnectionPoolTests {
3232
("testConnectionCreationIsRetriedUntilPoolIsShutdown", testConnectionCreationIsRetriedUntilPoolIsShutdown),
3333
("testConnectionCreationIsRetriedUntilRequestIsCancelled", testConnectionCreationIsRetriedUntilRequestIsCancelled),
3434
("testConnectionShutdownIsCalledOnActiveConnections", testConnectionShutdownIsCalledOnActiveConnections),
35+
("testConnectionPoolStressResistanceHTTP1", testConnectionPoolStressResistanceHTTP1),
3536
]
3637
}
3738
}

Tests/AsyncHTTPClientTests/HTTPConnectionPoolTests.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
@testable import AsyncHTTPClient
1616
import Logging
1717
import NIOCore
18+
import NIOHTTP1
1819
import NIOPosix
1920
import XCTest
2021

@@ -390,6 +391,68 @@ class HTTPConnectionPoolTests: XCTestCase {
390391
XCTAssertGreaterThanOrEqual(httpBin.createdConnections, 1)
391392
XCTAssertGreaterThanOrEqual(httpBin.activeConnections, 0)
392393
}
394+
395+
func testConnectionPoolStressResistanceHTTP1() {
396+
let numberOfRequestsPerThread = 1000
397+
let numberOfParallelWorkers = 8
398+
399+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 8)
400+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
401+
402+
let httpBin = HTTPBin()
403+
defer { XCTAssertNoThrow(try httpBin.shutdown()) }
404+
405+
let logger = Logger(label: "Test")
406+
let request = try! HTTPClient.Request(url: "http://localhost:\(httpBin.port)")
407+
let poolDelegate = TestDelegate(eventLoop: eventLoopGroup.next())
408+
409+
let pool = HTTPConnectionPool(
410+
eventLoopGroup: eventLoopGroup,
411+
sslContextCache: .init(),
412+
tlsConfiguration: nil,
413+
clientConfiguration: .init(),
414+
key: .init(request),
415+
delegate: poolDelegate,
416+
idGenerator: .init(),
417+
backgroundActivityLogger: logger
418+
)
419+
420+
let dispatchGroup = DispatchGroup()
421+
for workerID in 0..<numberOfParallelWorkers {
422+
DispatchQueue(label: "\(#file):\(#line):worker-\(workerID)").async(group: dispatchGroup) {
423+
func makeRequest() {
424+
let url = "http://localhost:\(httpBin.port)"
425+
var maybeRequest: HTTPClient.Request?
426+
var maybeRequestBag: RequestBag<ResponseAccumulator>?
427+
428+
XCTAssertNoThrow(maybeRequest = try HTTPClient.Request(url: url))
429+
XCTAssertNoThrow(maybeRequestBag = try RequestBag(
430+
request: XCTUnwrap(maybeRequest),
431+
eventLoopPreference: .indifferent,
432+
task: .init(eventLoop: eventLoopGroup.next(), logger: logger),
433+
redirectHandler: nil,
434+
connectionDeadline: .now() + .seconds(5),
435+
requestOptions: .forTests(),
436+
delegate: ResponseAccumulator(request: XCTUnwrap(maybeRequest))
437+
))
438+
439+
guard let requestBag = maybeRequestBag else { return XCTFail("Expected to get a request") }
440+
pool.executeRequest(requestBag)
441+
442+
XCTAssertNoThrow(try requestBag.task.futureResult.wait())
443+
}
444+
445+
for _ in 0..<numberOfRequestsPerThread {
446+
makeRequest()
447+
}
448+
}
449+
}
450+
451+
let timeout = DispatchTime.now() + .seconds(180)
452+
XCTAssertEqual(dispatchGroup.wait(timeout: timeout), .success)
453+
pool.shutdown()
454+
XCTAssertNoThrow(try poolDelegate.future.wait())
455+
}
393456
}
394457

395458
class TestDelegate: HTTPConnectionPoolDelegate {

0 commit comments

Comments
 (0)