15
15
import XCTest
16
16
import NIO
17
17
import NIOHTTP1
18
+ import CNIONghttp2
18
19
@testable import NIOHTTP2
19
20
20
21
/// A channel handler that passes writes through but fires EOF once the first one hits.
@@ -275,9 +276,8 @@ class SimpleClientServerTests: XCTestCase {
275
276
self . serverChannel. writeAndFlush ( goAwayFrame, promise: nil )
276
277
self . interactInMemory ( self . clientChannel, self . serverChannel)
277
278
278
- // The client should not receive this GOAWAY frame, as it has shut down.
279
- self . clientChannel. assertNoFramesReceived ( )
280
-
279
+ // In some nghttp2 versions the client will receive a GOAWAY, in others
280
+ // it will not. There is no meaningful assertion to apply here.
281
281
// All should be good.
282
282
self . serverChannel. assertNoFramesReceived ( )
283
283
XCTAssertNoThrow ( try self . clientChannel. finish ( ) )
@@ -969,9 +969,8 @@ class SimpleClientServerTests: XCTestCase {
969
969
// The data frame write should have exploded. nghttp2 synthesises an error code for this.
970
970
XCTAssertEqual ( ( writeError as? NIOHTTP2Errors . StreamClosed) ? . streamID, clientStreamID)
971
971
972
- // No other frames should be emitted.
973
- self . clientChannel. assertNoFramesReceived ( )
974
- self . serverChannel. assertNoFramesReceived ( )
972
+ // No other frames should be emitted, but we're ok if they were: depending on performance
973
+ // we may see a WINDOW_UPDATE or two here depending on timings.
975
974
XCTAssertNoThrow ( try self . clientChannel. finish ( ) )
976
975
XCTAssertNoThrow ( try self . serverChannel. finish ( ) )
977
976
}
@@ -1000,7 +999,18 @@ class SimpleClientServerTests: XCTestCase {
1000
999
let respFrame = HTTP2Frame ( streamID: serverStreamID, payload: . headers( responseHeaders) )
1001
1000
var respTrailersFrame = HTTP2Frame ( streamID: serverStreamID, payload: . headers( trailers) )
1002
1001
respTrailersFrame. flags. insert ( . endStream)
1003
- try self . assertFramesRoundTrip ( frames: [ respFrame, respTrailersFrame] , sender: self . serverChannel, receiver: self . clientChannel)
1002
+
1003
+ // v1.11.0 onwards don't send a 0-length DATA frame here, but earlier ones do. We send it explicitly to get
1004
+ // the output to match on all platforms.
1005
+ let expectedFrames : [ HTTP2Frame ]
1006
+ if CNIONghttp2_nghttp2_version_number ( ) < 0x011100 {
1007
+ let emptyDataFrame = HTTP2Frame ( streamID: serverStreamID, payload: . data( . byteBuffer( self . serverChannel. allocator. buffer ( capacity: 0 ) ) ) )
1008
+ expectedFrames = [ respFrame, emptyDataFrame, respTrailersFrame]
1009
+ } else {
1010
+ expectedFrames = [ respFrame, respTrailersFrame]
1011
+ }
1012
+
1013
+ try self . assertFramesRoundTrip ( frames: expectedFrames, sender: self . serverChannel, receiver: self . clientChannel)
1004
1014
1005
1015
XCTAssertNoThrow ( try self . clientChannel. finish ( ) )
1006
1016
XCTAssertNoThrow ( try self . serverChannel. finish ( ) )
@@ -1026,16 +1036,30 @@ class SimpleClientServerTests: XCTestCase {
1026
1036
1027
1037
let serverStreamID = try self . assertFramesRoundTrip ( frames: [ reqFrame, reqBodyFrame] , sender: self . clientChannel, receiver: self . serverChannel) . first!. streamID
1028
1038
1029
- // Now we can send the next trailers.
1030
- XCTAssertNoThrow ( try self . assertFramesRoundTrip ( frames: [ trailerFrame] , sender: self . clientChannel, receiver: self . serverChannel) )
1039
+ // Now we can send the next trailers. Again, old versions of nghttp2 send an empty data frame here too.
1040
+ var expectedFrames : [ HTTP2Frame ]
1041
+ if CNIONghttp2_nghttp2_version_number ( ) < 0x011100 {
1042
+ let emptyDataFrame = HTTP2Frame ( streamID: clientStreamID, payload: . data( . byteBuffer( self . clientChannel. allocator. buffer ( capacity: 0 ) ) ) )
1043
+ expectedFrames = [ emptyDataFrame, trailerFrame]
1044
+ } else {
1045
+ expectedFrames = [ trailerFrame]
1046
+ }
1047
+ XCTAssertNoThrow ( try self . assertFramesRoundTrip ( frames: expectedFrames, sender: self . clientChannel, receiver: self . serverChannel) )
1031
1048
1032
1049
// Let's send a quick response back. This response should also contain trailers.
1033
1050
let responseHeaders = HTTPHeaders ( [ ( " :status " , " 200 " ) , ( " content-length " , " 0 " ) ] )
1034
1051
let respFrame = HTTP2Frame ( streamID: serverStreamID, payload: . headers( responseHeaders) )
1035
1052
var respTrailersFrame = HTTP2Frame ( streamID: serverStreamID, payload: . headers( trailers) )
1036
1053
respTrailersFrame. flags. insert ( . endStream)
1037
1054
XCTAssertNoThrow ( try self . assertFramesRoundTrip ( frames: [ respFrame] , sender: self . serverChannel, receiver: self . clientChannel) )
1038
- XCTAssertNoThrow ( try self . assertFramesRoundTrip ( frames: [ respTrailersFrame] , sender: self . serverChannel, receiver: self . clientChannel) )
1055
+
1056
+ if CNIONghttp2_nghttp2_version_number ( ) < 0x011100 {
1057
+ let emptyDataFrame = HTTP2Frame ( streamID: serverStreamID, payload: . data( . byteBuffer( self . serverChannel. allocator. buffer ( capacity: 0 ) ) ) )
1058
+ expectedFrames = [ emptyDataFrame, respTrailersFrame]
1059
+ } else {
1060
+ expectedFrames = [ respTrailersFrame]
1061
+ }
1062
+ XCTAssertNoThrow ( try self . assertFramesRoundTrip ( frames: expectedFrames, sender: self . serverChannel, receiver: self . clientChannel) )
1039
1063
1040
1064
XCTAssertNoThrow ( try self . clientChannel. finish ( ) )
1041
1065
XCTAssertNoThrow ( try self . serverChannel. finish ( ) )
0 commit comments