@@ -2324,3 +2324,41 @@ async def handler(request: web.Request) -> web.Response:
2324
2324
# Make 2nd request which will hit the race condition.
2325
2325
async with client .get ("/" ) as resp :
2326
2326
assert resp .status == 200
2327
+
2328
+
2329
+ async def test_keepalive_expires_on_time (aiohttp_client : AiohttpClient ) -> None :
2330
+ """Test that the keepalive handle expires on time."""
2331
+
2332
+ async def handler (request : web .Request ) -> web .Response :
2333
+ body = await request .read ()
2334
+ assert b"" == body
2335
+ return web .Response (body = b"OK" )
2336
+
2337
+ app = web .Application ()
2338
+ app .router .add_route ("GET" , "/" , handler )
2339
+
2340
+ connector = aiohttp .TCPConnector (limit = 1 )
2341
+ client = await aiohttp_client (app , connector = connector )
2342
+
2343
+ loop = asyncio .get_running_loop ()
2344
+ now = loop .time ()
2345
+
2346
+ # Patch loop time so we can control when the keepalive timeout is processed
2347
+ with mock .patch .object (loop , "time" ) as loop_time_mock :
2348
+ loop_time_mock .return_value = now
2349
+ resp1 = await client .get ("/" )
2350
+ await resp1 .read ()
2351
+ request_handler = client .server .handler .connections [0 ]
2352
+
2353
+ # Ensure the keep alive handle is set
2354
+ assert request_handler ._keepalive_handle is not None
2355
+
2356
+ # Set the loop time to exactly the keepalive timeout
2357
+ loop_time_mock .return_value = request_handler ._next_keepalive_close_time
2358
+
2359
+ # sleep twice to ensure the keep alive timeout is processed
2360
+ await asyncio .sleep (0 )
2361
+ await asyncio .sleep (0 )
2362
+
2363
+ # Ensure the keep alive handle expires
2364
+ assert request_handler ._keepalive_handle is None
0 commit comments