@@ -261,4 +261,69 @@ class HTTPConnectionPool_HTTP2StateMachineTests: XCTestCase {
261
261
XCTAssertEqual ( closeAction. connection, . cleanupConnections( . init( ) , isShutdown: . yes( unclean: true ) ) )
262
262
XCTAssertEqual ( closeAction. request, . none)
263
263
}
264
+
265
+ func testHTTP1ToHTTP2MigrationAndShutdownIfFirstConnectionIsHTTP1( ) {
266
+ let elg = EmbeddedEventLoopGroup ( loops: 4 )
267
+ let el1 = elg. next ( )
268
+
269
+ let idGenerator = HTTPConnectionPool . Connection. ID. Generator ( )
270
+ var http1State = HTTPConnectionPool . HTTP1StateMachine ( idGenerator: idGenerator, maximumConcurrentConnections: 8 )
271
+
272
+ let mockRequest1 = MockHTTPRequest ( eventLoop: el1)
273
+ let request1 = HTTPConnectionPool . Request ( mockRequest1)
274
+ let mockRequest2 = MockHTTPRequest ( eventLoop: el1)
275
+ let request2 = HTTPConnectionPool . Request ( mockRequest2)
276
+
277
+ let executeAction1 = http1State. executeRequest ( request1)
278
+ XCTAssertEqual ( executeAction1. request, . scheduleRequestTimeout( for: request1, on: el1) )
279
+ guard case . createConnection( let conn1ID, _) = executeAction1. connection else {
280
+ return XCTFail ( " unexpected connection action \( executeAction1. connection) " )
281
+ }
282
+ let executeAction2 = http1State. executeRequest ( request2)
283
+ XCTAssertEqual ( executeAction2. request, . scheduleRequestTimeout( for: request2, on: el1) )
284
+ guard case . createConnection( let conn2ID, _) = executeAction2. connection else {
285
+ return XCTFail ( " unexpected connection action \( executeAction2. connection) " )
286
+ }
287
+
288
+ // first connection is a HTTP1 connection
289
+ let conn1 : HTTPConnectionPool . Connection = . __testOnly_connection( id: conn1ID, eventLoop: el1)
290
+ let conn1Action = http1State. newHTTP1ConnectionEstablished ( conn1)
291
+ XCTAssertEqual ( conn1Action. connection, . none)
292
+ XCTAssertEqual ( conn1Action. request, . executeRequest( request1, conn1, cancelTimeout: true ) )
293
+
294
+
295
+ // second connection is a HTTP2 connection and we need to migrate
296
+ let conn2 : HTTPConnectionPool . Connection = . __testOnly_connection( id: conn2ID, eventLoop: el1)
297
+ var http2State = HTTPConnectionPool . HTTP2StateMaschine ( idGenerator: idGenerator)
298
+
299
+ let migrationAction = http2State. migrateConnectionsFromHTTP1 (
300
+ connections: http1State. connections,
301
+ requests: http1State. requests
302
+ )
303
+ XCTAssertEqual ( migrationAction, . none)
304
+
305
+ let http2ConnectAction = http2State. newHTTP2ConnectionEstablished ( conn2, maxConcurrentStreams: 100 )
306
+ XCTAssertEqual ( http2ConnectAction. connection, . none)
307
+ guard case . executeRequestsAndCancelTimeouts( [ request2] , conn2) = http2ConnectAction. request else {
308
+ return XCTFail ( " Unexpected request action \( http2ConnectAction. request) " )
309
+ }
310
+
311
+ // second request is done first
312
+ let closeAction = http2State. http2ConnectionStreamClosed ( conn2ID)
313
+ XCTAssertEqual ( closeAction. request, . none)
314
+ XCTAssertEqual ( closeAction. connection, . scheduleTimeoutTimer( conn2ID, on: el1) )
315
+
316
+
317
+ let shutdownAction = http2State. shutdown ( )
318
+ XCTAssertEqual ( shutdownAction. request, . none)
319
+ XCTAssertEqual ( shutdownAction. connection, . cleanupConnections( . init(
320
+ close: [ conn2] ,
321
+ cancel: [ ] ,
322
+ connectBackoff: [ ]
323
+ ) , isShutdown: . no) )
324
+
325
+ let releaseAction = http2State. http1ConnectionReleased ( conn1ID)
326
+ XCTAssertEqual ( releaseAction. request, . none)
327
+ XCTAssertEqual ( releaseAction. connection, . closeConnection( conn1, isShutdown: . yes( unclean: true ) ) )
328
+ }
264
329
}
0 commit comments