@@ -890,12 +890,25 @@ async def test_pong_explicit_binary(self):
890890
891891 @patch ("random.getrandbits" )
892892 async def test_keepalive (self , getrandbits ):
893- """keepalive sends pings."""
893+ """keepalive sends pings at ping_interval and measures latency ."""
894894 self .connection .ping_interval = 2 * MS
895895 getrandbits .return_value = 1918987876
896896 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.
897900 await asyncio .sleep (3 * MS )
901+ # 3 ms: check that the ping frame was sent.
898902 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 ()
899912
900913 @patch ("random.getrandbits" )
901914 async def test_keepalive_times_out (self , getrandbits ):
@@ -905,13 +918,14 @@ async def test_keepalive_times_out(self, getrandbits):
905918 async with self .drop_frames_rcvd ():
906919 getrandbits .return_value = 1918987876
907920 self .connection .start_keepalive ()
921+ # 4 ms: keepalive() sends a ping frame.
908922 await asyncio .sleep (4 * MS )
909923 # 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 )
915929
916930 @patch ("random.getrandbits" )
917931 async def test_keepalive_ignores_timeout (self , getrandbits ):
@@ -921,18 +935,14 @@ async def test_keepalive_ignores_timeout(self, getrandbits):
921935 async with self .drop_frames_rcvd ():
922936 getrandbits .return_value = 1918987876
923937 self .connection .start_keepalive ()
938+ # 4 ms: keepalive() sends a ping frame.
924939 await asyncio .sleep (4 * MS )
925940 # 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 )
936946
937947 async def test_keepalive_terminates_while_sleeping (self ):
938948 """keepalive task terminates while waiting to send a ping."""
@@ -945,21 +955,27 @@ async def test_keepalive_terminates_while_sleeping(self):
945955 async def test_keepalive_terminates_while_waiting_for_pong (self ):
946956 """keepalive task terminates while waiting to receive a pong."""
947957 self .connection .ping_interval = 2 * MS
958+ self .connection .ping_timeout = 2 * MS
948959 async with self .drop_frames_rcvd ():
949960 self .connection .start_keepalive ()
961+ # 2 ms: keepalive() sends a ping frame.
950962 await asyncio .sleep (2 * MS )
951963 # 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.
952966 await self .connection .close ()
953967 self .assertTrue (self .connection .keepalive_task .done ())
954968
955969 async def test_keepalive_reports_errors (self ):
956970 """keepalive reports unexpected errors in logs."""
957971 self .connection .ping_interval = 2 * MS
958- # Inject a fault by raising an exception in a pending pong waiter.
959972 async with self .drop_frames_rcvd ():
960973 self .connection .start_keepalive ()
974+ # 2 ms: keepalive() sends a ping frame.
961975 await asyncio .sleep (2 * MS )
962976 # 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.
963979 pong_waiter = next (iter (self .connection .pong_waiters .values ()))[0 ]
964980 with self .assertLogs ("websockets" , logging .ERROR ) as logs :
965981 pong_waiter .set_exception (Exception ("BOOM" ))
0 commit comments