@@ -1192,7 +1192,11 @@ async def test_abnormal_closure_when_server_does_not_receive(
1192
1192
"""Test abnormal closure when the server closes and a message is pending."""
1193
1193
1194
1194
async def handler (request : web .Request ) -> web .WebSocketResponse :
1195
- ws = web .WebSocketResponse ()
1195
+ # Setting close timeout to 0, otherwise the server waits for a
1196
+ # close response for 10 seconds by default.
1197
+ # This would make the client's autoclose in resp.receive() to succeed,
1198
+ # closing the connection cleanly from both sides.
1199
+ ws = web .WebSocketResponse (timeout = 0 )
1196
1200
await ws .prepare (request )
1197
1201
await ws .close ()
1198
1202
return ws
@@ -1206,3 +1210,70 @@ async def handler(request: web.Request) -> web.WebSocketResponse:
1206
1210
msg = await resp .receive ()
1207
1211
assert msg .type is aiohttp .WSMsgType .CLOSE
1208
1212
assert resp .close_code == WSCloseCode .ABNORMAL_CLOSURE
1213
+
1214
+
1215
+ async def test_abnormal_closure_when_client_does_not_close (
1216
+ aiohttp_client : AiohttpClient ,
1217
+ ) -> None :
1218
+ """Test abnormal closure when the server closes and the client doesn't respond."""
1219
+ close_code : Optional [WSCloseCode ] = None
1220
+
1221
+ async def handler (request : web .Request ) -> web .WebSocketResponse :
1222
+ # Setting a short close timeout
1223
+ ws = web .WebSocketResponse (timeout = 0.1 )
1224
+ await ws .prepare (request )
1225
+ await ws .close ()
1226
+
1227
+ nonlocal close_code
1228
+ assert ws .close_code is not None
1229
+ close_code = WSCloseCode (ws .close_code )
1230
+
1231
+ return ws
1232
+
1233
+ app = web .Application ()
1234
+ app .router .add_route ("GET" , "/" , handler )
1235
+ client = await aiohttp_client (app )
1236
+ async with client .ws_connect ("/" , autoclose = False ):
1237
+ await asyncio .sleep (0.2 )
1238
+ await client .server .close ()
1239
+ assert close_code == WSCloseCode .ABNORMAL_CLOSURE
1240
+
1241
+
1242
+ async def test_normal_closure_while_client_sends_msg (
1243
+ aiohttp_client : AiohttpClient ,
1244
+ ) -> None :
1245
+ """Test abnormal closure when the server closes and the client doesn't respond."""
1246
+ close_code : Optional [WSCloseCode ] = None
1247
+ got_close_code = asyncio .Event ()
1248
+
1249
+ async def handler (request : web .Request ) -> web .WebSocketResponse :
1250
+ # Setting a short close timeout
1251
+ ws = web .WebSocketResponse (timeout = 0.2 )
1252
+ await ws .prepare (request )
1253
+ await ws .close ()
1254
+
1255
+ nonlocal close_code
1256
+ assert ws .close_code is not None
1257
+ close_code = WSCloseCode (ws .close_code )
1258
+ got_close_code .set ()
1259
+
1260
+ return ws
1261
+
1262
+ app = web .Application ()
1263
+ app .router .add_route ("GET" , "/" , handler )
1264
+ client = await aiohttp_client (app )
1265
+ async with client .ws_connect ("/" , autoclose = False ) as ws :
1266
+ # send text and close message during server close timeout
1267
+ await asyncio .sleep (0.1 )
1268
+ await ws .send_str ("Hello" )
1269
+ await ws .close ()
1270
+ # wait for close code to be received by server
1271
+ await asyncio .wait (
1272
+ [
1273
+ asyncio .create_task (asyncio .sleep (0.5 )),
1274
+ asyncio .create_task (got_close_code .wait ()),
1275
+ ],
1276
+ return_when = asyncio .FIRST_COMPLETED ,
1277
+ )
1278
+ await client .server .close ()
1279
+ assert close_code == WSCloseCode .OK
0 commit comments