|
15 | 15 | @testable import AsyncHTTPClient
|
16 | 16 | import Logging
|
17 | 17 | import NIOCore
|
| 18 | +import NIOHTTP1 |
18 | 19 | import NIOPosix
|
19 | 20 | import XCTest
|
20 | 21 |
|
@@ -390,6 +391,68 @@ class HTTPConnectionPoolTests: XCTestCase {
|
390 | 391 | XCTAssertGreaterThanOrEqual(httpBin.createdConnections, 1)
|
391 | 392 | XCTAssertGreaterThanOrEqual(httpBin.activeConnections, 0)
|
392 | 393 | }
|
| 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 | + } |
393 | 456 | }
|
394 | 457 |
|
395 | 458 | class TestDelegate: HTTPConnectionPoolDelegate {
|
|
0 commit comments