Skip to content

Commit e4dc122

Browse files
committed
gh-110088, gh-109878: Fix test_asyncio timeouts (#110092)
Fix test_asyncio timeouts: don't measure the maximum duration, a test should not measure a CI performance. Only measure the minimum duration when a task has a timeout or delay. Add CLOCK_RES to test_asyncio.utils. (cherry picked from commit db0a258)
1 parent 69a9f47 commit e4dc122

File tree

7 files changed

+19
-54
lines changed

7 files changed

+19
-54
lines changed

Lib/test/test_asyncio/test_base_events.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def cb():
273273
self.loop.stop()
274274

275275
self.loop._process_events = mock.Mock()
276-
delay = 0.1
276+
delay = 0.100
277277

278278
when = self.loop.time() + delay
279279
self.loop.call_at(when, cb)
@@ -282,10 +282,7 @@ def cb():
282282
dt = self.loop.time() - t0
283283

284284
# 50 ms: maximum granularity of the event loop
285-
self.assertGreaterEqual(dt, delay - 0.050, dt)
286-
# tolerate a difference of +800 ms because some Python buildbots
287-
# are really slow
288-
self.assertLessEqual(dt, 0.9, dt)
285+
self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES)
289286
with self.assertRaises(TypeError, msg="when cannot be None"):
290287
self.loop.call_at(None, cb)
291288

Lib/test/test_asyncio/test_events.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,11 @@ async def coro2():
294294
# 15.6 msec, we use fairly long sleep times here (~100 msec).
295295

296296
def test_run_until_complete(self):
297+
delay = 0.100
297298
t0 = self.loop.time()
298-
self.loop.run_until_complete(asyncio.sleep(0.1))
299-
t1 = self.loop.time()
300-
self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
299+
self.loop.run_until_complete(asyncio.sleep(delay))
300+
dt = self.loop.time() - t0
301+
self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES)
301302

302303
def test_run_until_complete_stopped(self):
303304

@@ -1718,7 +1719,6 @@ def _run_once():
17181719
self.loop._run_once = _run_once
17191720

17201721
async def wait():
1721-
loop = self.loop
17221722
await asyncio.sleep(1e-2)
17231723
await asyncio.sleep(1e-4)
17241724
await asyncio.sleep(1e-6)

Lib/test/test_asyncio/test_timeouts.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ async def test_nested_timeouts(self):
4646
self.assertTrue(cm2.expired())
4747

4848
async def test_waiter_cancelled(self):
49-
loop = asyncio.get_running_loop()
5049
cancelled = False
5150
with self.assertRaises(TimeoutError):
5251
async with asyncio.timeout(0.01):
@@ -59,39 +58,26 @@ async def test_waiter_cancelled(self):
5958

6059
async def test_timeout_not_called(self):
6160
loop = asyncio.get_running_loop()
62-
t0 = loop.time()
6361
async with asyncio.timeout(10) as cm:
6462
await asyncio.sleep(0.01)
6563
t1 = loop.time()
6664

6765
self.assertFalse(cm.expired())
68-
# 2 sec for slow CI boxes
69-
self.assertLess(t1-t0, 2)
7066
self.assertGreater(cm.when(), t1)
7167

7268
async def test_timeout_disabled(self):
73-
loop = asyncio.get_running_loop()
74-
t0 = loop.time()
7569
async with asyncio.timeout(None) as cm:
7670
await asyncio.sleep(0.01)
77-
t1 = loop.time()
7871

7972
self.assertFalse(cm.expired())
8073
self.assertIsNone(cm.when())
81-
# 2 sec for slow CI boxes
82-
self.assertLess(t1-t0, 2)
8374

8475
async def test_timeout_at_disabled(self):
85-
loop = asyncio.get_running_loop()
86-
t0 = loop.time()
8776
async with asyncio.timeout_at(None) as cm:
8877
await asyncio.sleep(0.01)
89-
t1 = loop.time()
9078

9179
self.assertFalse(cm.expired())
9280
self.assertIsNone(cm.when())
93-
# 2 sec for slow CI boxes
94-
self.assertLess(t1-t0, 2)
9581

9682
async def test_timeout_zero(self):
9783
loop = asyncio.get_running_loop()
@@ -101,8 +87,6 @@ async def test_timeout_zero(self):
10187
await asyncio.sleep(10)
10288
t1 = loop.time()
10389
self.assertTrue(cm.expired())
104-
# 2 sec for slow CI boxes
105-
self.assertLess(t1-t0, 2)
10690
self.assertTrue(t0 <= cm.when() <= t1)
10791

10892
async def test_timeout_zero_sleep_zero(self):
@@ -113,8 +97,6 @@ async def test_timeout_zero_sleep_zero(self):
11397
await asyncio.sleep(0)
11498
t1 = loop.time()
11599
self.assertTrue(cm.expired())
116-
# 2 sec for slow CI boxes
117-
self.assertLess(t1-t0, 2)
118100
self.assertTrue(t0 <= cm.when() <= t1)
119101

120102
async def test_timeout_in_the_past_sleep_zero(self):
@@ -125,8 +107,6 @@ async def test_timeout_in_the_past_sleep_zero(self):
125107
await asyncio.sleep(0)
126108
t1 = loop.time()
127109
self.assertTrue(cm.expired())
128-
# 2 sec for slow CI boxes
129-
self.assertLess(t1-t0, 2)
130110
self.assertTrue(t0 >= cm.when() <= t1)
131111

132112
async def test_foreign_exception_passed(self):

Lib/test/test_asyncio/test_waitfor.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,30 +65,22 @@ async def test_wait_for_timeout_less_then_0_or_0_future_done(self):
6565
fut = loop.create_future()
6666
fut.set_result('done')
6767

68-
t0 = loop.time()
6968
ret = await asyncio.wait_for(fut, 0)
70-
t1 = loop.time()
7169

7270
self.assertEqual(ret, 'done')
7371
self.assertTrue(fut.done())
74-
self.assertLess(t1 - t0, 0.1)
7572

7673
async def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self):
77-
loop = asyncio.get_running_loop()
78-
7974
foo_started = False
8075

8176
async def foo():
8277
nonlocal foo_started
8378
foo_started = True
8479

8580
with self.assertRaises(asyncio.TimeoutError):
86-
t0 = loop.time()
8781
await asyncio.wait_for(foo(), 0)
88-
t1 = loop.time()
8982

9083
self.assertEqual(foo_started, False)
91-
self.assertLess(t1 - t0, 0.1)
9284

9385
async def test_wait_for_timeout_less_then_0_or_0(self):
9486
loop = asyncio.get_running_loop()
@@ -112,18 +104,14 @@ async def foo():
112104
await started
113105

114106
with self.assertRaises(asyncio.TimeoutError):
115-
t0 = loop.time()
116107
await asyncio.wait_for(fut, timeout)
117-
t1 = loop.time()
118108

119109
self.assertTrue(fut.done())
120110
# it should have been cancelled due to the timeout
121111
self.assertTrue(fut.cancelled())
122112
self.assertEqual(foo_running, False)
123-
self.assertLess(t1 - t0, 0.1)
124113

125114
async def test_wait_for(self):
126-
loop = asyncio.get_running_loop()
127115
foo_running = None
128116

129117
async def foo():
@@ -138,13 +126,10 @@ async def foo():
138126
fut = asyncio.create_task(foo())
139127

140128
with self.assertRaises(asyncio.TimeoutError):
141-
t0 = loop.time()
142129
await asyncio.wait_for(fut, 0.1)
143-
t1 = loop.time()
144130
self.assertTrue(fut.done())
145131
# it should have been cancelled due to the timeout
146132
self.assertTrue(fut.cancelled())
147-
self.assertLess(t1 - t0, 0.5)
148133
self.assertEqual(foo_running, False)
149134

150135
async def test_wait_for_blocking(self):

Lib/test/test_asyncio/test_windows_events.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,29 +163,25 @@ def test_wait_for_handle(self):
163163

164164
# Wait for unset event with 0.5s timeout;
165165
# result should be False at timeout
166-
fut = self.loop._proactor.wait_for_handle(event, 0.5)
166+
timeout = 0.5
167+
fut = self.loop._proactor.wait_for_handle(event, timeout)
167168
start = self.loop.time()
168169
done = self.loop.run_until_complete(fut)
169170
elapsed = self.loop.time() - start
170171

171172
self.assertEqual(done, False)
172173
self.assertFalse(fut.result())
173-
# bpo-31008: Tolerate only 450 ms (at least 500 ms expected),
174-
# because of bad clock resolution on Windows
175-
self.assertTrue(0.45 <= elapsed <= 0.9, elapsed)
174+
self.assertGreaterEqual(elapsed, timeout - test_utils.CLOCK_RES)
176175

177176
_overlapped.SetEvent(event)
178177

179178
# Wait for set event;
180179
# result should be True immediately
181180
fut = self.loop._proactor.wait_for_handle(event, 10)
182-
start = self.loop.time()
183181
done = self.loop.run_until_complete(fut)
184-
elapsed = self.loop.time() - start
185182

186183
self.assertEqual(done, True)
187184
self.assertTrue(fut.result())
188-
self.assertTrue(0 <= elapsed < 0.3, elapsed)
189185

190186
# asyncio issue #195: cancelling a done _WaitHandleFuture
191187
# must not crash
@@ -199,11 +195,8 @@ def test_wait_for_handle_cancel(self):
199195
# CancelledError should be raised immediately
200196
fut = self.loop._proactor.wait_for_handle(event, 10)
201197
fut.cancel()
202-
start = self.loop.time()
203198
with self.assertRaises(asyncio.CancelledError):
204199
self.loop.run_until_complete(fut)
205-
elapsed = self.loop.time() - start
206-
self.assertTrue(0 <= elapsed < 0.1, elapsed)
207200

208201
# asyncio issue #195: cancelling a _WaitHandleFuture twice
209202
# must not crash

Lib/test/test_asyncio/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
from test.support import threading_helper
3737

3838

39+
# Use the maximum known clock resolution (gh-75191, gh-110088): Windows
40+
# GetTickCount64() has a resolution of 15.6 ms. Use 20 ms to tolerate rounding
41+
# issues.
42+
CLOCK_RES = 0.020
43+
44+
3945
def data_file(filename):
4046
if hasattr(support, 'TEST_HOME_DIR'):
4147
fullname = os.path.join(support.TEST_HOME_DIR, filename)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix test_asyncio timeouts: don't measure the maximum duration, a test should
2+
not measure a CI performance. Only measure the minimum duration when a task has
3+
a timeout or delay. Add ``CLOCK_RES`` to ``test_asyncio.utils``. Patch by
4+
Victor Stinner.

0 commit comments

Comments
 (0)