@@ -2680,13 +2680,12 @@ class HTTPClientTests: XCTestCase {
2680
2680
class CloseHandler : ChannelInboundHandler {
2681
2681
typealias InboundIn = Any
2682
2682
2683
- func channelActive ( context: ChannelHandlerContext ) {
2683
+ func channelRead ( context: ChannelHandlerContext , data : NIOAny ) {
2684
2684
context. close ( promise: nil )
2685
2685
}
2686
2686
}
2687
2687
2688
2688
let server = try ServerBootstrap ( group: self . serverGroup)
2689
- . childChannelOption ( ChannelOptions . autoRead, value: false )
2690
2689
. childChannelInitializer { channel in
2691
2690
channel. pipeline. addHandler ( CloseHandler ( ) )
2692
2691
}
@@ -2697,17 +2696,73 @@ class HTTPClientTests: XCTestCase {
2697
2696
XCTAssertNoThrow ( try server. close ( ) . wait ( ) )
2698
2697
}
2699
2698
2700
- let request = try Request ( url: " https://localhost: \( server. localAddress!. port!) " , method: . GET)
2701
- let task = self . defaultClient. execute ( request: request, delegate: TestHTTPDelegate ( ) )
2699
+ // We set the connect timeout down very low here because on NIOTS this manifests as a connect
2700
+ // timeout.
2701
+ let config = HTTPClient . Configuration ( timeout: HTTPClient . Configuration. Timeout ( connect: . milliseconds( 100 ) , read: nil ) )
2702
+ let client = HTTPClient ( eventLoopGroupProvider: . shared( self . clientGroup) , configuration: config)
2703
+ defer {
2704
+ XCTAssertNoThrow ( try client. syncShutdown ( ) )
2705
+ }
2706
+
2707
+ let request = try Request ( url: " https://127.0.0.1: \( server. localAddress!. port!) " , method: . GET)
2708
+ let task = client. execute ( request: request, delegate: TestHTTPDelegate ( ) )
2709
+
2710
+ XCTAssertThrowsError ( try task. wait ( ) ) { error in
2711
+ #if os(Linux)
2712
+ XCTAssertEqual ( error as? NIOSSLError , NIOSSLError . uncleanShutdown)
2713
+ #else
2714
+ if isTestingNIOTS ( ) {
2715
+ XCTAssertEqual ( error as? ChannelError , . connectTimeout( . milliseconds( 100 ) ) )
2716
+ } else {
2717
+ XCTAssertEqual ( ( error as? IOError ) . map { $0. errnoCode } , ECONNRESET)
2718
+ }
2719
+ #endif
2720
+ }
2721
+ }
2722
+
2723
+ func testSSLHandshakeErrorPropagationDelayedClose( ) throws {
2724
+ // This is as the test above, but the close handler delays its close action by a few hundred ms.
2725
+ // This will tend to catch the pipeline at different weird stages, and flush out different bugs.
2726
+ class CloseHandler : ChannelInboundHandler {
2727
+ typealias InboundIn = Any
2728
+
2729
+ func channelRead( context: ChannelHandlerContext , data: NIOAny ) {
2730
+ context. eventLoop. scheduleTask ( in: . milliseconds( 100 ) ) {
2731
+ context. close ( promise: nil )
2732
+ }
2733
+ }
2734
+ }
2735
+
2736
+ let server = try ServerBootstrap ( group: self . serverGroup)
2737
+ . childChannelInitializer { channel in
2738
+ channel. pipeline. addHandler ( CloseHandler ( ) )
2739
+ }
2740
+ . bind ( host: " 127.0.0.1 " , port: 0 )
2741
+ . wait ( )
2742
+
2743
+ defer {
2744
+ XCTAssertNoThrow ( try server. close ( ) . wait ( ) )
2745
+ }
2746
+
2747
+ // We set the connect timeout down very low here because on NIOTS this manifests as a connect
2748
+ // timeout.
2749
+ let config = HTTPClient . Configuration ( timeout: HTTPClient . Configuration. Timeout ( connect: . milliseconds( 200 ) , read: nil ) )
2750
+ let client = HTTPClient ( eventLoopGroupProvider: . shared( self . clientGroup) , configuration: config)
2751
+ defer {
2752
+ XCTAssertNoThrow ( try client. syncShutdown ( ) )
2753
+ }
2754
+
2755
+ let request = try Request ( url: " https://127.0.0.1: \( server. localAddress!. port!) " , method: . GET)
2756
+ let task = client. execute ( request: request, delegate: TestHTTPDelegate ( ) )
2702
2757
2703
2758
XCTAssertThrowsError ( try task. wait ( ) ) { error in
2704
2759
#if os(Linux)
2705
2760
XCTAssertEqual ( error as? NIOSSLError , NIOSSLError . uncleanShutdown)
2706
2761
#else
2707
2762
if isTestingNIOTS ( ) {
2708
- XCTAssertEqual ( ( error as? AsyncHTTPClient . HTTPClient . NWTLSError ) . map { $0 . status } , errSSLClosedNoNotify )
2763
+ XCTAssertEqual ( error as? ChannelError , . connectTimeout ( . milliseconds ( 200 ) ) )
2709
2764
} else {
2710
- XCTAssertEqual ( ( error as? IOError ) . map { $0. errnoCode } , 54 )
2765
+ XCTAssertEqual ( ( error as? IOError ) . map { $0. errnoCode } , ECONNRESET )
2711
2766
}
2712
2767
#endif
2713
2768
}
0 commit comments