Skip to content

Commit 0745ab8

Browse files
authored
[3.12] gh-110088, gh-109878: Fix test_asyncio timeouts (#110092) (#110098)
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 c188a13 commit 0745ab8

File tree

7 files changed

+19
-54
lines changed

7 files changed

+19
-54
lines changed

Lib/test/test_asyncio/test_base_events.py

+2-5
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

+4-4
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

@@ -1715,7 +1716,6 @@ def _run_once():
17151716
self.loop._run_once = _run_once
17161717

17171718
async def wait():
1718-
loop = self.loop
17191719
await asyncio.sleep(1e-2)
17201720
await asyncio.sleep(1e-4)
17211721
await asyncio.sleep(1e-6)

Lib/test/test_asyncio/test_timeouts.py

-20
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

-15
Original file line numberDiff line numberDiff line change
@@ -66,30 +66,22 @@ async def test_wait_for_timeout_less_then_0_or_0_future_done(self):
6666
fut = loop.create_future()
6767
fut.set_result('done')
6868

69-
t0 = loop.time()
7069
ret = await asyncio.wait_for(fut, 0)
71-
t1 = loop.time()
7270

7371
self.assertEqual(ret, 'done')
7472
self.assertTrue(fut.done())
75-
self.assertLess(t1 - t0, 0.1)
7673

7774
async def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self):
78-
loop = asyncio.get_running_loop()
79-
8075
foo_started = False
8176

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

8681
with self.assertRaises(asyncio.TimeoutError):
87-
t0 = loop.time()
8882
await asyncio.wait_for(foo(), 0)
89-
t1 = loop.time()
9083

9184
self.assertEqual(foo_started, False)
92-
self.assertLess(t1 - t0, 0.1)
9385

9486
async def test_wait_for_timeout_less_then_0_or_0(self):
9587
loop = asyncio.get_running_loop()
@@ -113,18 +105,14 @@ async def foo():
113105
await started
114106

115107
with self.assertRaises(asyncio.TimeoutError):
116-
t0 = loop.time()
117108
await asyncio.wait_for(fut, timeout)
118-
t1 = loop.time()
119109

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

126115
async def test_wait_for(self):
127-
loop = asyncio.get_running_loop()
128116
foo_running = None
129117

130118
async def foo():
@@ -139,13 +127,10 @@ async def foo():
139127
fut = asyncio.create_task(foo())
140128

141129
with self.assertRaises(asyncio.TimeoutError):
142-
t0 = loop.time()
143130
await asyncio.wait_for(fut, 0.1)
144-
t1 = loop.time()
145131
self.assertTrue(fut.done())
146132
# it should have been cancelled due to the timeout
147133
self.assertTrue(fut.cancelled())
148-
self.assertLess(t1 - t0, support.SHORT_TIMEOUT)
149134
self.assertEqual(foo_running, False)
150135

151136
async def test_wait_for_blocking(self):

Lib/test/test_asyncio/test_windows_events.py

+3-10
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

+6
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)
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)