Skip to content

Commit cf7179f

Browse files
committed
Clarify semantic of waits in connection tests.
1 parent 37a8f1b commit cf7179f

File tree

2 files changed

+35
-32
lines changed

2 files changed

+35
-32
lines changed

tests/asyncio/test_connection.py

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,56 +49,54 @@ async def asyncTearDown(self):
4949

5050
# Test helpers built upon RecordingProtocol and InterceptingConnection.
5151

52-
async def assertFrameSent(self, frame):
53-
"""Check that a single frame was sent."""
54-
# Let the remote side process messages.
52+
async def wait_for_remote_side(self):
53+
"""Wait for the remote side to process messages."""
5554
# Two runs of the event loop are required for answering pings.
5655
await asyncio.sleep(0)
5756
await asyncio.sleep(0)
57+
58+
async def assertFrameSent(self, frame):
59+
"""Check that a single frame was sent."""
60+
await self.wait_for_remote_side()
5861
self.assertEqual(self.remote_connection.protocol.get_frames_rcvd(), [frame])
5962

6063
async def assertFramesSent(self, frames):
6164
"""Check that several frames were sent."""
62-
# Let the remote side process messages.
63-
# Two runs of the event loop are required for answering pings.
64-
await asyncio.sleep(0)
65-
await asyncio.sleep(0)
65+
await self.wait_for_remote_side()
6666
self.assertEqual(self.remote_connection.protocol.get_frames_rcvd(), frames)
6767

6868
async def assertNoFrameSent(self):
6969
"""Check that no frame was sent."""
70-
# Run the event loop twice for consistency with assertFrameSent.
71-
await asyncio.sleep(0)
72-
await asyncio.sleep(0)
70+
await self.wait_for_remote_side()
7371
self.assertEqual(self.remote_connection.protocol.get_frames_rcvd(), [])
7472

7573
@contextlib.asynccontextmanager
7674
async def delay_frames_rcvd(self, delay):
7775
"""Delay frames before they're received by the connection."""
7876
with self.remote_connection.delay_frames_sent(delay):
7977
yield
80-
await asyncio.sleep(MS) # let the remote side process messages
78+
await self.wait_for_remote_side()
8179

8280
@contextlib.asynccontextmanager
8381
async def delay_eof_rcvd(self, delay):
8482
"""Delay EOF before it's received by the connection."""
8583
with self.remote_connection.delay_eof_sent(delay):
8684
yield
87-
await asyncio.sleep(MS) # let the remote side process messages
85+
await self.wait_for_remote_side()
8886

8987
@contextlib.asynccontextmanager
9088
async def drop_frames_rcvd(self):
9189
"""Drop frames before they're received by the connection."""
9290
with self.remote_connection.drop_frames_sent():
9391
yield
94-
await asyncio.sleep(MS) # let the remote side process messages
92+
await self.wait_for_remote_side()
9593

9694
@contextlib.asynccontextmanager
9795
async def drop_eof_rcvd(self):
9896
"""Drop EOF before it's received by the connection."""
9997
with self.remote_connection.drop_eof_sent():
10098
yield
101-
await asyncio.sleep(MS) # let the remote side process messages
99+
await self.wait_for_remote_side()
102100

103101
# Test __aenter__ and __aexit__.
104102

@@ -1009,9 +1007,8 @@ async def test_keepalive_times_out(self, getrandbits):
10091007
async with self.drop_frames_rcvd():
10101008
self.connection.start_keepalive()
10111009
# 4 ms: keepalive() sends a ping frame.
1012-
await asyncio.sleep(4 * MS)
1013-
# Exiting the context manager sleeps for 1 ms.
10141010
# 4.x ms: a pong frame is dropped.
1011+
await asyncio.sleep(5 * MS)
10151012
# 6 ms: no pong frame is received; the connection is closed.
10161013
await asyncio.sleep(2 * MS)
10171014
# 7 ms: check that the connection is closed.
@@ -1026,8 +1023,7 @@ async def test_keepalive_ignores_timeout(self, getrandbits):
10261023
self.connection.start_keepalive()
10271024
# 4 ms: keepalive() sends a ping frame.
10281025
# 4.x ms: a pong frame is dropped.
1029-
await asyncio.sleep(4 * MS)
1030-
# Exiting the context manager sleeps for 1 ms.
1026+
await asyncio.sleep(5 * MS)
10311027
# 6 ms: no pong frame is received; the connection remains open.
10321028
await asyncio.sleep(2 * MS)
10331029
# 7 ms: check that the connection is still open.
@@ -1038,19 +1034,19 @@ async def test_keepalive_terminates_while_sleeping(self):
10381034
self.connection.ping_interval = 3 * MS
10391035
self.connection.start_keepalive()
10401036
await asyncio.sleep(MS)
1037+
self.assertFalse(self.connection.keepalive_task.done())
10411038
await self.connection.close()
10421039
self.assertTrue(self.connection.keepalive_task.done())
10431040

10441041
async def test_keepalive_terminates_while_waiting_for_pong(self):
10451042
"""keepalive task terminates while waiting to receive a pong."""
10461043
self.connection.ping_interval = MS
1047-
self.connection.ping_timeout = 3 * MS
1044+
self.connection.ping_timeout = 4 * MS
10481045
async with self.drop_frames_rcvd():
10491046
self.connection.start_keepalive()
10501047
# 1 ms: keepalive() sends a ping frame.
10511048
# 1.x ms: a pong frame is dropped.
1052-
await asyncio.sleep(MS)
1053-
# Exiting the context manager sleeps for 1 ms.
1049+
await asyncio.sleep(2 * MS)
10541050
# 2 ms: close the connection before ping_timeout elapses.
10551051
await self.connection.close()
10561052
self.assertTrue(self.connection.keepalive_task.done())
@@ -1062,8 +1058,7 @@ async def test_keepalive_reports_errors(self):
10621058
self.connection.start_keepalive()
10631059
# 2 ms: keepalive() sends a ping frame.
10641060
# 2.x ms: a pong frame is dropped.
1065-
await asyncio.sleep(2 * MS)
1066-
# Exiting the context manager sleeps for 1 ms.
1061+
await asyncio.sleep(3 * MS)
10671062
# 3 ms: inject a fault: raise an exception in the pending pong waiter.
10681063
pong_received = next(iter(self.connection.pending_pings.values()))[0]
10691064
with self.assertLogs("websockets", logging.ERROR) as logs:

tests/sync/test_connection.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,43 +44,49 @@ def tearDown(self):
4444

4545
# Test helpers built upon RecordingProtocol and InterceptingConnection.
4646

47+
def wait_for_remote_side(self):
48+
"""Wait for the remote side to process messages."""
49+
# We don't have a way to tell if the remote side is blocked on I/O.
50+
# The sync tests still run faster than the asyncio and trio tests :-)
51+
time.sleep(MS)
52+
4753
def assertFrameSent(self, frame):
4854
"""Check that a single frame was sent."""
49-
time.sleep(MS) # let the remote side process messages
55+
self.wait_for_remote_side()
5056
self.assertEqual(self.remote_connection.protocol.get_frames_rcvd(), [frame])
5157

5258
def assertNoFrameSent(self):
5359
"""Check that no frame was sent."""
54-
time.sleep(MS) # let the remote side process messages
60+
self.wait_for_remote_side()
5561
self.assertEqual(self.remote_connection.protocol.get_frames_rcvd(), [])
5662

5763
@contextlib.contextmanager
5864
def delay_frames_rcvd(self, delay):
5965
"""Delay frames before they're received by the connection."""
6066
with self.remote_connection.delay_frames_sent(delay):
6167
yield
62-
time.sleep(MS) # let the remote side process messages
68+
self.wait_for_remote_side()
6369

6470
@contextlib.contextmanager
6571
def delay_eof_rcvd(self, delay):
6672
"""Delay EOF before it's received by the connection."""
6773
with self.remote_connection.delay_eof_sent(delay):
6874
yield
69-
time.sleep(MS) # let the remote side process messages
75+
self.wait_for_remote_side()
7076

7177
@contextlib.contextmanager
7278
def drop_frames_rcvd(self):
7379
"""Drop frames before they're received by the connection."""
7480
with self.remote_connection.drop_frames_sent():
7581
yield
76-
time.sleep(MS) # let the remote side process messages
82+
self.wait_for_remote_side()
7783

7884
@contextlib.contextmanager
7985
def drop_eof_rcvd(self):
8086
"""Drop EOF before it's received by the connection."""
8187
with self.remote_connection.drop_eof_sent():
8288
yield
83-
time.sleep(MS) # let the remote side process messages
89+
self.wait_for_remote_side()
8490

8591
# Test __enter__ and __exit__.
8692

@@ -736,9 +742,9 @@ def test_keepalive_times_out(self, getrandbits):
736742
with self.drop_frames_rcvd():
737743
self.connection.start_keepalive()
738744
# 4 ms: keepalive() sends a ping frame.
745+
# 4.x ms: a pong frame is dropped.
739746
time.sleep(4 * MS)
740747
# Exiting the context manager sleeps for 1 ms.
741-
# 4.x ms: a pong frame is dropped.
742748
# 6 ms: no pong frame is received; the connection is closed.
743749
time.sleep(2 * MS)
744750
# 7 ms: check that the connection is closed.
@@ -752,9 +758,9 @@ def test_keepalive_ignores_timeout(self, getrandbits):
752758
with self.drop_frames_rcvd():
753759
self.connection.start_keepalive()
754760
# 4 ms: keepalive() sends a ping frame.
761+
# 4.x ms: a pong frame is dropped.
755762
time.sleep(4 * MS)
756763
# Exiting the context manager sleeps for 1 ms.
757-
# 4.x ms: a pong frame is dropped.
758764
# 6 ms: no pong frame is received; the connection remains open.
759765
time.sleep(2 * MS)
760766
# 7 ms: check that the connection is still open.
@@ -765,16 +771,18 @@ def test_keepalive_terminates_while_sleeping(self):
765771
self.connection.ping_interval = 3 * MS
766772
self.connection.start_keepalive()
767773
time.sleep(MS)
774+
self.assertTrue(self.connection.keepalive_thread.is_alive())
768775
self.connection.close()
769776
self.connection.keepalive_thread.join(MS)
770777
self.assertFalse(self.connection.keepalive_thread.is_alive())
771778

772779
def test_keepalive_terminates_when_sending_ping_fails(self):
773780
"""keepalive task terminates when sending a ping fails."""
774-
self.connection.ping_interval = 1 * MS
781+
self.connection.ping_interval = MS
775782
self.connection.start_keepalive()
776783
with self.drop_eof_rcvd(), self.drop_frames_rcvd():
777784
self.connection.close()
785+
# Exiting the context managers sleeps for 2 ms.
778786
self.assertFalse(self.connection.keepalive_thread.is_alive())
779787

780788
def test_keepalive_terminates_while_waiting_for_pong(self):

0 commit comments

Comments
 (0)