@@ -1193,4 +1193,67 @@ class SimpleClientServerTests: XCTestCase {
11931193 XCTAssertNoThrow ( try self . clientChannel. finish ( ) )
11941194 XCTAssertNoThrow ( try self . serverChannel. finish ( ) )
11951195 }
1196+
1197+ func testStreamErrorOnSelfDependentPriorityFrames( ) throws {
1198+ // Begin by getting the connection up.
1199+ try self . basicHTTP2Connection ( )
1200+
1201+ // Send a PRIORITY frame that has a self-dependency. Note that we aren't policing these outbound:
1202+ // as we can't detect cycles generally without maintaining a bunch of state, we simply don't. That
1203+ // allows us to emit this.
1204+ let frame = HTTP2Frame ( streamID: 1 , payload: . priority( . init( exclusive: false , dependency: 1 , weight: 32 ) ) )
1205+ self . clientChannel. writeAndFlush ( frame, promise: nil )
1206+
1207+ // We treat this as a connection error.
1208+ guard let frameData = try assertNoThrowWithValue ( self . clientChannel. readOutbound ( as: ByteBuffer . self) ) else {
1209+ XCTFail ( " Did not receive frame " )
1210+ return
1211+ }
1212+ XCTAssertThrowsError ( try self . serverChannel. writeInbound ( frameData) ) { error in
1213+ XCTAssertEqual ( error as? NIOHTTP2Errors . PriorityCycle , NIOHTTP2Errors . PriorityCycle ( streamID: 1 ) )
1214+ }
1215+
1216+ guard let responseFrame = try assertNoThrowWithValue ( self . serverChannel. readOutbound ( as: ByteBuffer . self) ) else {
1217+ XCTFail ( " Did not receive response frame " )
1218+ return
1219+ }
1220+ XCTAssertNoThrow ( try self . clientChannel. writeInbound ( responseFrame) )
1221+
1222+ try self . clientChannel. assertReceivedFrame ( ) . assertGoAwayFrame ( lastStreamID: . maxID, errorCode: UInt32 ( http2ErrorCode: . protocolError) , opaqueData: nil )
1223+
1224+ XCTAssertNoThrow ( XCTAssertTrue ( try self . clientChannel. finish ( ) . isClean) )
1225+ _ = try ? self . serverChannel. finish ( )
1226+ }
1227+
1228+ func testStreamErrorOnSelfDependentHeadersFrames( ) throws {
1229+ // Begin by getting the connection up.
1230+ try self . basicHTTP2Connection ( )
1231+
1232+ // Send a HEADERS frame that has a self-dependency. Note that we aren't policing these outbound:
1233+ // as we can't detect cycles generally without maintaining a bunch of state, we simply don't. That
1234+ // allows us to emit this.
1235+ let headers = HPACKHeaders ( [ ( " :path " , " / " ) , ( " :method " , " POST " ) , ( " :scheme " , " https " ) , ( " :authority " , " localhost " ) ] )
1236+ let frame = HTTP2Frame ( streamID: 1 , payload: . headers( . init( headers: headers, priorityData: . init( exclusive: true , dependency: 1 , weight: 64 ) ) ) )
1237+ self . clientChannel. writeAndFlush ( frame, promise: nil )
1238+
1239+ // We treat this as a connection error.
1240+ guard let frameData = try assertNoThrowWithValue ( self . clientChannel. readOutbound ( as: ByteBuffer . self) ) else {
1241+ XCTFail ( " Did not receive frame " )
1242+ return
1243+ }
1244+ XCTAssertThrowsError ( try self . serverChannel. writeInbound ( frameData) ) { error in
1245+ XCTAssertEqual ( error as? NIOHTTP2Errors . PriorityCycle , NIOHTTP2Errors . PriorityCycle ( streamID: 1 ) )
1246+ }
1247+
1248+ guard let responseFrame = try assertNoThrowWithValue ( self . serverChannel. readOutbound ( as: ByteBuffer . self) ) else {
1249+ XCTFail ( " Did not receive response frame " )
1250+ return
1251+ }
1252+ XCTAssertNoThrow ( try self . clientChannel. writeInbound ( responseFrame) )
1253+
1254+ try self . clientChannel. assertReceivedFrame ( ) . assertGoAwayFrame ( lastStreamID: . maxID, errorCode: UInt32 ( http2ErrorCode: . protocolError) , opaqueData: nil )
1255+
1256+ XCTAssertNoThrow ( XCTAssertTrue ( try self . clientChannel. finish ( ) . isClean) )
1257+ _ = try ? self . serverChannel. finish ( )
1258+ }
11961259}
0 commit comments