@@ -76,12 +76,10 @@ class HTTPRequestStateMachineTests: XCTestCase {
76
76
let part1 = IOData . byteBuffer ( ByteBuffer ( bytes: [ 0 , 1 , 2 , 3 ] ) )
77
77
XCTAssertEqual ( state. requestStreamPartReceived ( part0) , . sendBodyPart( part0) )
78
78
79
- let failAction = state. requestStreamPartReceived ( part1)
80
- guard case . failRequest( let error, . close) = failAction else {
81
- return XCTFail ( " Unexpected action: \( failAction) " )
82
- }
79
+ state. requestStreamPartReceived ( part1) . assertFailRequest ( HTTPClientError . bodyLengthMismatch, . close)
83
80
84
- XCTAssertEqual ( error as? HTTPClientError , . bodyLengthMismatch)
81
+ // if another error happens the new one is ignored
82
+ XCTAssertEqual ( state. errorHappened ( HTTPClientError . remoteConnectionClosed) , . wait)
85
83
}
86
84
87
85
func testPOSTContentLengthIsTooShort( ) {
@@ -92,12 +90,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
92
90
let part0 = IOData . byteBuffer ( ByteBuffer ( bytes: [ 0 , 1 , 2 , 3 ] ) )
93
91
XCTAssertEqual ( state. requestStreamPartReceived ( part0) , . sendBodyPart( part0) )
94
92
95
- let failAction = state. requestStreamFinished ( )
96
- guard case . failRequest( let error, . close) = failAction else {
97
- return XCTFail ( " Unexpected action: \( failAction) " )
98
- }
99
-
100
- XCTAssertEqual ( error as? HTTPClientError , . bodyLengthMismatch)
93
+ state. requestStreamFinished ( ) . assertFailRequest ( HTTPClientError . bodyLengthMismatch, . close)
101
94
}
102
95
103
96
func testRequestBodyStreamIsCancelledIfServerRespondsWith301( ) {
@@ -206,7 +199,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
206
199
207
200
let part1 = IOData . byteBuffer ( ByteBuffer ( bytes: 4 ... 7 ) )
208
201
XCTAssertEqual ( state. requestStreamPartReceived ( part1) , . sendBodyPart( part1) )
209
- XCTAssertEqual ( state. requestStreamFinished ( ) , . failRequest ( HTTPClientError . bodyLengthMismatch, . close) )
202
+ state. requestStreamFinished ( ) . assertFailRequest ( HTTPClientError . bodyLengthMismatch, . close)
210
203
XCTAssertEqual ( state. channelInactive ( ) , . wait)
211
204
}
212
205
@@ -224,7 +217,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
224
217
225
218
let part1 = IOData . byteBuffer ( ByteBuffer ( bytes: 4 ... 7 ) )
226
219
XCTAssertEqual ( state. requestStreamPartReceived ( part1) , . sendBodyPart( part1) )
227
- XCTAssertEqual ( state. requestStreamFinished ( ) , . failRequest ( HTTPClientError . bodyLengthMismatch, . close) )
220
+ state. requestStreamFinished ( ) . assertFailRequest ( HTTPClientError . bodyLengthMismatch, . close)
228
221
XCTAssertEqual ( state. channelRead ( . end( nil ) ) , . wait)
229
222
}
230
223
@@ -249,7 +242,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
249
242
let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
250
243
let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
251
244
XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . wait)
252
- XCTAssertEqual ( state. channelInactive ( ) , . failRequest ( HTTPClientError . remoteConnectionClosed, . none) )
245
+ state. channelInactive ( ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . none)
253
246
}
254
247
255
248
func testResponseReadingWithBackpressure( ) {
@@ -339,15 +332,15 @@ class HTTPRequestStateMachineTests: XCTestCase {
339
332
340
333
func testCancellingARequestInStateInitializedKeepsTheConnectionAlive( ) {
341
334
var state = HTTPRequestStateMachine ( isChannelWritable: false )
342
- XCTAssertEqual ( state. requestCancelled ( ) , . failRequest ( HTTPClientError . cancelled, . none) )
335
+ state. requestCancelled ( ) . assertFailRequest ( HTTPClientError . cancelled, . none)
343
336
}
344
337
345
338
func testCancellingARequestBeforeBeingSendKeepsTheConnectionAlive( ) {
346
339
var state = HTTPRequestStateMachine ( isChannelWritable: false )
347
340
let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
348
341
let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
349
342
XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . wait)
350
- XCTAssertEqual ( state. requestCancelled ( ) , . failRequest ( HTTPClientError . cancelled, . none) )
343
+ state. requestCancelled ( ) . assertFailRequest ( HTTPClientError . cancelled, . none)
351
344
}
352
345
353
346
func testConnectionBecomesWritableBeforeFirstRequest( ) {
@@ -373,15 +366,15 @@ class HTTPRequestStateMachineTests: XCTestCase {
373
366
let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
374
367
let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
375
368
XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . sendRequestHead( requestHead, startBody: false ) )
376
- XCTAssertEqual ( state. requestCancelled ( ) , . failRequest ( HTTPClientError . cancelled, . close) )
369
+ state. requestCancelled ( ) . assertFailRequest ( HTTPClientError . cancelled, . close)
377
370
}
378
371
379
372
func testRemoteSuddenlyClosesTheConnection( ) {
380
373
var state = HTTPRequestStateMachine ( isChannelWritable: true )
381
374
let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " , headers: . init( [ ( " content-length " , " 4 " ) ] ) )
382
375
let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 4 ) )
383
376
XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . sendRequestHead( requestHead, startBody: true ) )
384
- XCTAssertEqual ( state. requestCancelled ( ) , . failRequest ( HTTPClientError . remoteConnectionClosed , . close) )
377
+ state. requestCancelled ( ) . assertFailRequest ( HTTPClientError . cancelled , . close)
385
378
XCTAssertEqual ( state. requestStreamPartReceived ( . byteBuffer( . init( bytes: 1 ... 3 ) ) ) , . wait)
386
379
}
387
380
@@ -395,7 +388,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
395
388
XCTAssertEqual ( state. channelRead ( . head( responseHead) ) , . forwardResponseHead( responseHead, pauseRequestBodyStream: false ) )
396
389
let part0 = ByteBuffer ( bytes: 0 ... 3 )
397
390
XCTAssertEqual ( state. channelRead ( . body( part0) ) , . wait)
398
- XCTAssertEqual ( state. idleReadTimeoutTriggered ( ) , . failRequest ( HTTPClientError . readTimeout, . close) )
391
+ state. idleReadTimeoutTriggered ( ) . assertFailRequest ( HTTPClientError . readTimeout, . close)
399
392
XCTAssertEqual ( state. channelRead ( . body( ByteBuffer ( bytes: 4 ... 7 ) ) ) , . wait)
400
393
XCTAssertEqual ( state. channelRead ( . body( ByteBuffer ( bytes: 8 ... 11 ) ) ) , . wait)
401
394
XCTAssertEqual ( state. demandMoreResponseBodyParts ( ) , . wait)
@@ -448,7 +441,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
448
441
let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
449
442
XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . sendRequestHead( requestHead, startBody: false ) )
450
443
451
- XCTAssertEqual ( state. errorHappened ( HTTPParserError . invalidChunkSize) , . failRequest ( HTTPParserError . invalidChunkSize, . close) )
444
+ state. errorHappened ( HTTPParserError . invalidChunkSize) . assertFailRequest ( HTTPParserError . invalidChunkSize, . close)
452
445
XCTAssertEqual ( state. requestCancelled ( ) , . wait, " A cancellation that happens to late is ignored " )
453
446
}
454
447
@@ -502,7 +495,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
502
495
XCTAssertEqual ( state. read ( ) , . read)
503
496
XCTAssertEqual ( state. channelReadComplete ( ) , . wait)
504
497
XCTAssertEqual ( state. channelRead ( . body( body) ) , . wait)
505
- XCTAssertEqual ( state. channelRead ( . end( nil ) ) , . failRequest ( HTTPClientError . remoteConnectionClosed, . close) )
498
+ state. channelRead ( . end( nil ) ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . close)
506
499
XCTAssertEqual ( state. channelInactive ( ) , . wait)
507
500
}
508
501
@@ -517,11 +510,32 @@ class HTTPRequestStateMachineTests: XCTestCase {
517
510
XCTAssertEqual ( state. channelRead ( . head( responseHead) ) , . forwardResponseHead( responseHead, pauseRequestBodyStream: false ) )
518
511
XCTAssertEqual ( state. demandMoreResponseBodyParts ( ) , . wait)
519
512
XCTAssertEqual ( state. channelRead ( . body( body) ) , . wait)
520
- XCTAssertEqual ( state. errorHappened ( NIOSSLError . uncleanShutdown) , . failRequest ( NIOSSLError . uncleanShutdown, . close) )
513
+ state. errorHappened ( NIOSSLError . uncleanShutdown) . assertFailRequest ( NIOSSLError . uncleanShutdown, . close)
521
514
XCTAssertEqual ( state. channelRead ( . end( nil ) ) , . wait)
522
515
XCTAssertEqual ( state. channelInactive ( ) , . wait)
523
516
}
524
517
518
+ func testNIOSSLErrorUncleanShutdownShouldBeTreatedAsRemoteConnectionCloseWhileInWaitingForHeadState( ) {
519
+ var state = HTTPRequestStateMachine ( isChannelWritable: true )
520
+ let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
521
+ let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
522
+ XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . sendRequestHead( requestHead, startBody: false ) )
523
+
524
+ XCTAssertEqual ( state. errorHappened ( NIOSSLError . uncleanShutdown) , . wait)
525
+ state. channelInactive ( ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . none)
526
+ }
527
+
528
+ func testArbitraryErrorShouldBeTreatedAsARequestFailureWhileInWaitingForHeadState( ) {
529
+ struct ArbitraryError : Error , Equatable { }
530
+ var state = HTTPRequestStateMachine ( isChannelWritable: true )
531
+ let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
532
+ let metadata = RequestFramingMetadata ( connectionClose: false , body: . fixedSize( 0 ) )
533
+ XCTAssertEqual ( state. startRequest ( head: requestHead, metadata: metadata) , . sendRequestHead( requestHead, startBody: false ) )
534
+
535
+ state. errorHappened ( ArbitraryError ( ) ) . assertFailRequest ( ArbitraryError ( ) , . close)
536
+ XCTAssertEqual ( state. channelInactive ( ) , . wait)
537
+ }
538
+
525
539
func testFailHTTP1RequestWithContentLengthWithNIOSSLErrorUncleanShutdownButIgnoreIt( ) {
526
540
var state = HTTPRequestStateMachine ( isChannelWritable: true )
527
541
let requestHead = HTTPRequestHead ( version: . http1_1, method: . GET, uri: " / " )
@@ -536,7 +550,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
536
550
XCTAssertEqual ( state. channelRead ( . body( body) ) , . wait)
537
551
XCTAssertEqual ( state. channelReadComplete ( ) , . forwardResponseBodyParts( [ body] ) )
538
552
XCTAssertEqual ( state. errorHappened ( NIOSSLError . uncleanShutdown) , . wait)
539
- XCTAssertEqual ( state. errorHappened ( HTTPParserError . invalidEOFState) , . failRequest ( HTTPParserError . invalidEOFState, . close) )
553
+ state. errorHappened ( HTTPParserError . invalidEOFState) . assertFailRequest ( HTTPParserError . invalidEOFState, . close)
540
554
XCTAssertEqual ( state. channelInactive ( ) , . wait)
541
555
}
542
556
@@ -558,7 +572,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
558
572
559
573
XCTAssertEqual ( state. channelRead ( . body( ByteBuffer ( string: " baz lightyear " ) ) ) , . wait)
560
574
XCTAssertEqual ( state. channelReadComplete ( ) , . wait)
561
- XCTAssertEqual ( state. channelInactive ( ) , . failRequest ( HTTPClientError . remoteConnectionClosed, . none) )
575
+ state. channelInactive ( ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . none)
562
576
}
563
577
564
578
func testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForRead( ) {
@@ -579,7 +593,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
579
593
580
594
XCTAssertEqual ( state. channelRead ( . body( ByteBuffer ( string: " baz lightyear " ) ) ) , . wait)
581
595
XCTAssertEqual ( state. channelReadComplete ( ) , . wait)
582
- XCTAssertEqual ( state. channelInactive ( ) , . failRequest ( HTTPClientError . remoteConnectionClosed, . none) )
596
+ state. channelInactive ( ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . none)
583
597
}
584
598
585
599
func testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForReadAndDemand( ) {
@@ -599,7 +613,7 @@ class HTTPRequestStateMachineTests: XCTestCase {
599
613
600
614
XCTAssertEqual ( state. channelRead ( . body( ByteBuffer ( string: " baz lightyear " ) ) ) , . wait)
601
615
XCTAssertEqual ( state. channelReadComplete ( ) , . wait)
602
- XCTAssertEqual ( state. channelInactive ( ) , . failRequest ( HTTPClientError . remoteConnectionClosed, . none) )
616
+ state. channelInactive ( ) . assertFailRequest ( HTTPClientError . remoteConnectionClosed, . none)
603
617
}
604
618
605
619
func testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForReadAndDemandMultipleTimes( ) {
@@ -676,3 +690,22 @@ extension HTTPRequestStateMachine.Action: Equatable {
676
690
}
677
691
}
678
692
}
693
+
694
+ extension HTTPRequestStateMachine . Action {
695
+ fileprivate func assertFailRequest< Error> (
696
+ _ expectedError: Error ,
697
+ _ expectedFinalStreamAction: HTTPRequestStateMachine . Action . FinalStreamAction ,
698
+ file: StaticString = #file,
699
+ line: UInt = #line
700
+ ) where Error: Swift . Error & Equatable {
701
+ guard case . failRequest( let actualError, let actualFinalStreamAction) = self else {
702
+ return XCTFail ( " expected .failRequest( \( expectedError) , \( expectedFinalStreamAction) ) but got \( self ) " , file: file, line: line)
703
+ }
704
+ if let actualError = actualError as? Error {
705
+ XCTAssertEqual ( actualError, expectedError, file: file, line: line)
706
+ } else {
707
+ XCTFail ( " \( actualError) is not equal to \( expectedError) " , file: file, line: line)
708
+ }
709
+ XCTAssertEqual ( actualFinalStreamAction, expectedFinalStreamAction, file: file, line: line)
710
+ }
711
+ }
0 commit comments