@@ -428,6 +428,29 @@ class SimpleClientServerTests: XCTestCase {
428
428
XCTAssertNil ( try channel. readOutbound ( as: ByteBuffer . self) )
429
429
}
430
430
431
+ func testChannelInactiveThenChannelActiveErrorsButDoesntTrap( ) throws {
432
+ let channel = EmbeddedChannel ( )
433
+ let recorder = ErrorRecorder ( )
434
+ try channel. pipeline. syncOperations. addHandlers (
435
+ [
436
+ NIOHTTP2Handler ( mode: . client) ,
437
+ recorder
438
+ ]
439
+ )
440
+
441
+ XCTAssertEqual ( recorder. errors. count, 0 )
442
+
443
+ // Send channelInactive followed by channelActive. This can happen if a user calls close
444
+ // from within a connect promise.
445
+ channel. pipeline. fireChannelInactive ( )
446
+ XCTAssertEqual ( recorder. errors. count, 0 )
447
+
448
+ channel. pipeline. fireChannelActive ( )
449
+
450
+ XCTAssertEqual ( recorder. errors. count, 1 )
451
+ XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
452
+ }
453
+
431
454
func testImpossibleStateTransitionsThrowErrors( ) throws {
432
455
func setUpChannel( ) throws -> ( EmbeddedChannel , ErrorRecorder ) {
433
456
let channel = EmbeddedChannel ( )
@@ -443,22 +466,14 @@ class SimpleClientServerTests: XCTestCase {
443
466
return ( channel, recorder)
444
467
}
445
468
446
- // First impossible state transition: channelInactive during idle.
447
- // Doesn't transition state, just errors. Becuase we close during this, we hit
448
- // the error twice!
469
+ // First impossible state transition: channelActive on channelActive.
449
470
var ( channel, recorder) = try setUpChannel ( )
450
- channel. pipeline. fireChannelInactive ( )
451
- XCTAssertEqual ( recorder. errors. count, 2 )
452
- XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
453
-
454
- // Second impossible state transition: channelActive on channelActive.
455
- ( channel, recorder) = try setUpChannel ( )
456
471
try channel. pipeline. syncOperations. addHandler ( ActionOnFlushHandler { $0. pipeline. fireChannelActive ( ) } , position: . first)
457
472
channel. pipeline. fireChannelActive ( )
458
473
XCTAssertEqual ( recorder. errors. count, 1 )
459
474
XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
460
475
461
- // Third impossible state transition. Synchronous active/inactive/active. The error causes a close,
476
+ // Second impossible state transition. Synchronous active/inactive/active. The error causes a close,
462
477
// so we error twice!
463
478
( channel, recorder) = try setUpChannel ( )
464
479
try channel. pipeline. syncOperations. addHandler (
@@ -472,17 +487,18 @@ class SimpleClientServerTests: XCTestCase {
472
487
XCTAssertEqual ( recorder. errors. count, 2 )
473
488
XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
474
489
475
- // Fourth impossible state transition: active/inactive/active asynchronously. The error causes a close,
476
- // so we error twice!
490
+ // Third impossible state transition: active/inactive/active asynchronously. This error doesn't cause a
491
+ // close because we don't distinguish it from the case tested in
492
+ // testChannelInactiveThenChannelActiveErrorsButDoesntTrap.
477
493
( channel, recorder) = try setUpChannel ( )
478
494
channel. pipeline. fireChannelActive ( )
479
495
channel. pipeline. fireChannelInactive ( )
480
496
XCTAssertEqual ( recorder. errors. count, 0 )
481
497
channel. pipeline. fireChannelActive ( )
482
- XCTAssertEqual ( recorder. errors. count, 2 )
498
+ XCTAssertEqual ( recorder. errors. count, 1 )
483
499
XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
484
500
485
- // Fifth impossible state transition: active/inactive/inactive synchronously. The error causes a close,
501
+ // Fourth impossible state transition: active/inactive/inactive synchronously. The error causes a close,
486
502
// so we error twice!
487
503
( channel, recorder) = try setUpChannel ( )
488
504
try channel. pipeline. syncOperations. addHandler (
@@ -496,7 +512,7 @@ class SimpleClientServerTests: XCTestCase {
496
512
XCTAssertEqual ( recorder. errors. count, 2 )
497
513
XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
498
514
499
- // Sixth impossible state transition: active/inactive/inactive asynchronously. The error causes a close,
515
+ // Fifth impossible state transition: active/inactive/inactive asynchronously. The error causes a close,
500
516
// so we error twice!
501
517
( channel, recorder) = try setUpChannel ( )
502
518
channel. pipeline. fireChannelActive ( )
@@ -506,7 +522,7 @@ class SimpleClientServerTests: XCTestCase {
506
522
XCTAssertEqual ( recorder. errors. count, 2 )
507
523
XCTAssertTrue ( recorder. errors. allSatisfy { $0 is NIOHTTP2Errors . ActivationError } )
508
524
509
- // Seventh impossible state transition: adding the handler twice. The error causes a close, so we
525
+ // Sixth impossible state transition: adding the handler twice. The error causes a close, so we
510
526
// error twice!
511
527
( channel, recorder) = try setUpChannel ( )
512
528
try channel. connect ( to: SocketAddress ( unixDomainSocketPath: " /tmp/ignored " ) , promise: nil )
0 commit comments