@@ -153,7 +153,7 @@ class HTTPConnectionPool_HTTP1StateMachineTests: XCTestCase {
153153 return XCTFail ( " Unexpected request action: \( action. request) " )
154154 }
155155 XCTAssert ( requestToFail. __testOnly_wrapped_request ( ) === mockRequest) // XCTAssertIdentical not available on Linux
156- XCTAssertEqual ( requestError as? HTTPClientError , . getConnectionFromPoolTimeout )
156+ XCTAssertEqual ( requestError as? HTTPClientError , . connectTimeout )
157157 XCTAssertEqual ( failRequest. connection, . none)
158158
159159 // 4. retry connection, but no more queued requests.
@@ -626,4 +626,110 @@ class HTTPConnectionPool_HTTP1StateMachineTests: XCTestCase {
626626
627627 XCTAssertEqual ( state. connectionCreationBackoffDone ( connectionID) , . none)
628628 }
629+
630+ func testRequestThatTimesOutIsFailedWithLastConnectionCreationError( ) {
631+ let elg = EmbeddedEventLoopGroup ( loops: 1 )
632+ defer { XCTAssertNoThrow ( try elg. syncShutdownGracefully ( ) ) }
633+
634+ var state = HTTPConnectionPool . StateMachine (
635+ eventLoopGroup: elg,
636+ idGenerator: . init( ) ,
637+ maximumConcurrentHTTP1Connections: 6
638+ )
639+
640+ let mockRequest = MockHTTPRequest ( eventLoop: elg. next ( ) , requiresEventLoopForChannel: false )
641+ let request = HTTPConnectionPool . Request ( mockRequest)
642+
643+ let executeAction = state. executeRequest ( request)
644+ guard case . createConnection( let connectionID, on: let connEL) = executeAction. connection else {
645+ return XCTFail ( " Expected to create a connection " )
646+ }
647+
648+ XCTAssertEqual ( executeAction. request, . scheduleRequestTimeout( for: request, on: mockRequest. eventLoop) )
649+
650+ let failAction = state. failedToCreateNewConnection ( HTTPClientError . httpProxyHandshakeTimeout, connectionID: connectionID)
651+ guard case . scheduleBackoffTimer( connectionID, backoff: _, on: let timerEL) = failAction. connection else {
652+ return XCTFail ( " Expected to create a backoff timer " )
653+ }
654+ XCTAssert ( timerEL === connEL)
655+ XCTAssertEqual ( failAction. request, . none)
656+
657+ let timeoutAction = state. timeoutRequest ( request. id)
658+ XCTAssertEqual ( timeoutAction. request, . failRequest( request, HTTPClientError . httpProxyHandshakeTimeout, cancelTimeout: false ) )
659+ XCTAssertEqual ( timeoutAction. connection, . none)
660+ }
661+
662+ func testRequestThatTimesOutBeforeAConnectionIsEstablishedIsFailedWithConnectTimeoutError( ) {
663+ let eventLoop = EmbeddedEventLoop ( )
664+ defer { XCTAssertNoThrow ( try eventLoop. syncShutdownGracefully ( ) ) }
665+
666+ var state = HTTPConnectionPool . StateMachine (
667+ eventLoopGroup: eventLoop,
668+ idGenerator: . init( ) ,
669+ maximumConcurrentHTTP1Connections: 6
670+ )
671+
672+ let mockRequest = MockHTTPRequest ( eventLoop: eventLoop. next ( ) , requiresEventLoopForChannel: false )
673+ let request = HTTPConnectionPool . Request ( mockRequest)
674+
675+ let executeAction = state. executeRequest ( request)
676+ guard case . createConnection( _, on: _) = executeAction. connection else {
677+ return XCTFail ( " Expected to create a connection " )
678+ }
679+ XCTAssertEqual ( executeAction. request, . scheduleRequestTimeout( for: request, on: mockRequest. eventLoop) )
680+
681+ let timeoutAction = state. timeoutRequest ( request. id)
682+ XCTAssertEqual ( timeoutAction. request, . failRequest( request, HTTPClientError . connectTimeout, cancelTimeout: false ) )
683+ XCTAssertEqual ( timeoutAction. connection, . none)
684+ }
685+
686+ func testRequestThatTimesOutAfterAConnectionWasEstablishedSuccessfullyTimesOutWithGenericError( ) {
687+ let elg = EmbeddedEventLoopGroup ( loops: 1 )
688+ defer { XCTAssertNoThrow ( try elg. syncShutdownGracefully ( ) ) }
689+
690+ var state = HTTPConnectionPool . StateMachine (
691+ eventLoopGroup: elg,
692+ idGenerator: . init( ) ,
693+ maximumConcurrentHTTP1Connections: 6
694+ )
695+
696+ let mockRequest1 = MockHTTPRequest ( eventLoop: elg. next ( ) , requiresEventLoopForChannel: false )
697+ let request1 = HTTPConnectionPool . Request ( mockRequest1)
698+
699+ let executeAction1 = state. executeRequest ( request1)
700+ guard case . createConnection( let connectionID1, on: let connEL1) = executeAction1. connection else {
701+ return XCTFail ( " Expected to create a connection " )
702+ }
703+ XCTAssert ( mockRequest1. eventLoop === connEL1)
704+
705+ XCTAssertEqual ( executeAction1. request, . scheduleRequestTimeout( for: request1, on: mockRequest1. eventLoop) )
706+
707+ let mockRequest2 = MockHTTPRequest ( eventLoop: elg. next ( ) , requiresEventLoopForChannel: false )
708+ let request2 = HTTPConnectionPool . Request ( mockRequest2)
709+
710+ let executeAction2 = state. executeRequest ( request2)
711+ guard case . createConnection( let connectionID2, on: let connEL2) = executeAction2. connection else {
712+ return XCTFail ( " Expected to create a connection " )
713+ }
714+ XCTAssert ( mockRequest2. eventLoop === connEL2)
715+
716+ XCTAssertEqual ( executeAction2. request, . scheduleRequestTimeout( for: request2, on: connEL1) )
717+
718+ let failAction = state. failedToCreateNewConnection ( HTTPClientError . httpProxyHandshakeTimeout, connectionID: connectionID1)
719+ guard case . scheduleBackoffTimer( connectionID1, backoff: _, on: let timerEL) = failAction. connection else {
720+ return XCTFail ( " Expected to create a backoff timer " )
721+ }
722+ XCTAssert ( timerEL === connEL2)
723+ XCTAssertEqual ( failAction. request, . none)
724+
725+ let conn2 = HTTPConnectionPool . Connection. __testOnly_connection ( id: connectionID2, eventLoop: connEL2)
726+ let createdAction = state. newHTTP1ConnectionCreated ( conn2)
727+
728+ XCTAssertEqual ( createdAction. request, . executeRequest( request1, conn2, cancelTimeout: true ) )
729+ XCTAssertEqual ( createdAction. connection, . none)
730+
731+ let timeoutAction = state. timeoutRequest ( request2. id)
732+ XCTAssertEqual ( timeoutAction. request, . failRequest( request2, HTTPClientError . getConnectionFromPoolTimeout, cancelTimeout: false ) )
733+ XCTAssertEqual ( timeoutAction. connection, . none)
734+ }
629735}
0 commit comments