@@ -890,12 +890,25 @@ async def test_pong_explicit_binary(self):
890
890
891
891
@patch ("random.getrandbits" )
892
892
async def test_keepalive (self , getrandbits ):
893
- """keepalive sends pings."""
893
+ """keepalive sends pings at ping_interval and measures latency ."""
894
894
self .connection .ping_interval = 2 * MS
895
895
getrandbits .return_value = 1918987876
896
896
self .connection .start_keepalive ()
897
+ self .assertEqual (self .connection .latency , 0 )
898
+ # 2 ms: keepalive() sends a ping frame.
899
+ # 2.x ms: a pong frame is received.
897
900
await asyncio .sleep (3 * MS )
901
+ # 3 ms: check that the ping frame was sent.
898
902
await self .assertFrameSent (Frame (Opcode .PING , b"rand" ))
903
+ self .assertGreater (self .connection .latency , 0 )
904
+ self .assertLess (self .connection .latency , MS )
905
+
906
+ async def test_disable_keepalive (self ):
907
+ """keepalive is disabled when ping_interval is None."""
908
+ self .connection .ping_interval = None
909
+ self .connection .start_keepalive ()
910
+ await asyncio .sleep (3 * MS )
911
+ await self .assertNoFrameSent ()
899
912
900
913
@patch ("random.getrandbits" )
901
914
async def test_keepalive_times_out (self , getrandbits ):
@@ -905,13 +918,14 @@ async def test_keepalive_times_out(self, getrandbits):
905
918
async with self .drop_frames_rcvd ():
906
919
getrandbits .return_value = 1918987876
907
920
self .connection .start_keepalive ()
921
+ # 4 ms: keepalive() sends a ping frame.
908
922
await asyncio .sleep (4 * MS )
909
923
# Exiting the context manager sleeps for MS.
910
- await self . assertFrameSent ( Frame ( Opcode . PING , b"rand" ))
911
- await asyncio . sleep ( MS )
912
- await self . assertFrameSent (
913
- Frame ( Opcode . CLOSE , b" \x03 \xf3 keepalive ping timeout" )
914
- )
924
+ # 4.x ms: a pong frame is dropped.
925
+ # 6 ms: no pong frame is received; the connection is closed.
926
+ await asyncio . sleep ( 2 * MS )
927
+ # 7 ms: check that the connection is closed.
928
+ self . assertEqual ( self . connection . state , State . CLOSED )
915
929
916
930
@patch ("random.getrandbits" )
917
931
async def test_keepalive_ignores_timeout (self , getrandbits ):
@@ -921,18 +935,14 @@ async def test_keepalive_ignores_timeout(self, getrandbits):
921
935
async with self .drop_frames_rcvd ():
922
936
getrandbits .return_value = 1918987876
923
937
self .connection .start_keepalive ()
938
+ # 4 ms: keepalive() sends a ping frame.
924
939
await asyncio .sleep (4 * MS )
925
940
# Exiting the context manager sleeps for MS.
926
- await self .assertFrameSent (Frame (Opcode .PING , b"rand" ))
927
- await asyncio .sleep (MS )
928
- await self .assertNoFrameSent ()
929
-
930
- async def test_disable_keepalive (self ):
931
- """keepalive is disabled when ping_interval is None."""
932
- self .connection .ping_interval = None
933
- self .connection .start_keepalive ()
934
- await asyncio .sleep (3 * MS )
935
- await self .assertNoFrameSent ()
941
+ # 4.x ms: a pong frame is dropped.
942
+ # 6 ms: no pong frame is received; the connection remains open.
943
+ await asyncio .sleep (2 * MS )
944
+ # 7 ms: check that the connection is still open.
945
+ self .assertEqual (self .connection .state , State .OPEN )
936
946
937
947
async def test_keepalive_terminates_while_sleeping (self ):
938
948
"""keepalive task terminates while waiting to send a ping."""
@@ -945,21 +955,27 @@ async def test_keepalive_terminates_while_sleeping(self):
945
955
async def test_keepalive_terminates_while_waiting_for_pong (self ):
946
956
"""keepalive task terminates while waiting to receive a pong."""
947
957
self .connection .ping_interval = 2 * MS
958
+ self .connection .ping_timeout = 2 * MS
948
959
async with self .drop_frames_rcvd ():
949
960
self .connection .start_keepalive ()
961
+ # 2 ms: keepalive() sends a ping frame.
950
962
await asyncio .sleep (2 * MS )
951
963
# Exiting the context manager sleeps for MS.
964
+ # 2.x ms: a pong frame is dropped.
965
+ # 3 ms: close the connection before ping_timeout elapses.
952
966
await self .connection .close ()
953
967
self .assertTrue (self .connection .keepalive_task .done ())
954
968
955
969
async def test_keepalive_reports_errors (self ):
956
970
"""keepalive reports unexpected errors in logs."""
957
971
self .connection .ping_interval = 2 * MS
958
- # Inject a fault by raising an exception in a pending pong waiter.
959
972
async with self .drop_frames_rcvd ():
960
973
self .connection .start_keepalive ()
974
+ # 2 ms: keepalive() sends a ping frame.
961
975
await asyncio .sleep (2 * MS )
962
976
# Exiting the context manager sleeps for MS.
977
+ # 2.x ms: a pong frame is dropped.
978
+ # 3 ms: inject a fault: raise an exception in the pending pong waiter.
963
979
pong_waiter = next (iter (self .connection .pong_waiters .values ()))[0 ]
964
980
with self .assertLogs ("websockets" , logging .ERROR ) as logs :
965
981
pong_waiter .set_exception (Exception ("BOOM" ))
0 commit comments