]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110088, gh-109878: Fix test_asyncio timeouts (#110092)
authorVictor Stinner <vstinner@python.org>
Fri, 29 Sep 2023 11:49:30 +0000 (13:49 +0200)
committerGitHub <noreply@github.com>
Fri, 29 Sep 2023 11:49:30 +0000 (11:49 +0000)
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.

Lib/test/test_asyncio/test_base_events.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_timeouts.py
Lib/test/test_asyncio/test_waitfor.py
Lib/test/test_asyncio/test_windows_events.py
Lib/test/test_asyncio/utils.py
Misc/NEWS.d/next/Tests/2023-09-29-12-48-42.gh-issue-110088.qUhRga.rst [new file with mode: 0644]

index 3b4026cb73869a7d766cb8c3cb1ba4cc9a84033e..abcb6f55c4b04e664d02a270f813df28a9c9f11d 100644 (file)
@@ -273,7 +273,7 @@ class BaseEventLoopTests(test_utils.TestCase):
             self.loop.stop()
 
         self.loop._process_events = mock.Mock()
-        delay = 0.1
+        delay = 0.100
 
         when = self.loop.time() + delay
         self.loop.call_at(when, cb)
@@ -282,10 +282,7 @@ class BaseEventLoopTests(test_utils.TestCase):
         dt = self.loop.time() - t0
 
         # 50 ms: maximum granularity of the event loop
-        self.assertGreaterEqual(dt, delay - 0.050, dt)
-        # tolerate a difference of +800 ms because some Python buildbots
-        # are really slow
-        self.assertLessEqual(dt, 0.9, dt)
+        self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES)
         with self.assertRaises(TypeError, msg="when cannot be None"):
             self.loop.call_at(None, cb)
 
index f22cb5e58bba62590e140e4e37c21b5f98d549ef..3ee6565b2b65ada0f4154ede7c76f6942c5c53ba 100644 (file)
@@ -293,10 +293,11 @@ class EventLoopTestsMixin:
     # 15.6 msec, we use fairly long sleep times here (~100 msec).
 
     def test_run_until_complete(self):
+        delay = 0.100
         t0 = self.loop.time()
-        self.loop.run_until_complete(asyncio.sleep(0.1))
-        t1 = self.loop.time()
-        self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
+        self.loop.run_until_complete(asyncio.sleep(delay))
+        dt = self.loop.time() - t0
+        self.assertGreaterEqual(dt, delay - test_utils.CLOCK_RES)
 
     def test_run_until_complete_stopped(self):
 
@@ -1717,7 +1718,6 @@ class EventLoopTestsMixin:
         self.loop._run_once = _run_once
 
         async def wait():
-            loop = self.loop
             await asyncio.sleep(1e-2)
             await asyncio.sleep(1e-4)
             await asyncio.sleep(1e-6)
index 8b6b9a1fea0be8fdf7171cf2364635a54790054a..e9b59b953518b3fc1e332240c1faeeebdf24083d 100644 (file)
@@ -46,7 +46,6 @@ class TimeoutTests(unittest.IsolatedAsyncioTestCase):
         self.assertTrue(cm2.expired())
 
     async def test_waiter_cancelled(self):
-        loop = asyncio.get_running_loop()
         cancelled = False
         with self.assertRaises(TimeoutError):
             async with asyncio.timeout(0.01):
@@ -59,39 +58,26 @@ class TimeoutTests(unittest.IsolatedAsyncioTestCase):
 
     async def test_timeout_not_called(self):
         loop = asyncio.get_running_loop()
-        t0 = loop.time()
         async with asyncio.timeout(10) as cm:
             await asyncio.sleep(0.01)
         t1 = loop.time()
 
         self.assertFalse(cm.expired())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
         self.assertGreater(cm.when(), t1)
 
     async def test_timeout_disabled(self):
-        loop = asyncio.get_running_loop()
-        t0 = loop.time()
         async with asyncio.timeout(None) as cm:
             await asyncio.sleep(0.01)
-        t1 = loop.time()
 
         self.assertFalse(cm.expired())
         self.assertIsNone(cm.when())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
 
     async def test_timeout_at_disabled(self):
-        loop = asyncio.get_running_loop()
-        t0 = loop.time()
         async with asyncio.timeout_at(None) as cm:
             await asyncio.sleep(0.01)
-        t1 = loop.time()
 
         self.assertFalse(cm.expired())
         self.assertIsNone(cm.when())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
 
     async def test_timeout_zero(self):
         loop = asyncio.get_running_loop()
@@ -101,8 +87,6 @@ class TimeoutTests(unittest.IsolatedAsyncioTestCase):
                 await asyncio.sleep(10)
         t1 = loop.time()
         self.assertTrue(cm.expired())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
         self.assertTrue(t0 <= cm.when() <= t1)
 
     async def test_timeout_zero_sleep_zero(self):
@@ -113,8 +97,6 @@ class TimeoutTests(unittest.IsolatedAsyncioTestCase):
                 await asyncio.sleep(0)
         t1 = loop.time()
         self.assertTrue(cm.expired())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
         self.assertTrue(t0 <= cm.when() <= t1)
 
     async def test_timeout_in_the_past_sleep_zero(self):
@@ -125,8 +107,6 @@ class TimeoutTests(unittest.IsolatedAsyncioTestCase):
                 await asyncio.sleep(0)
         t1 = loop.time()
         self.assertTrue(cm.expired())
-        # 2 sec for slow CI boxes
-        self.assertLess(t1-t0, 2)
         self.assertTrue(t0 >= cm.when() <= t1)
 
     async def test_foreign_exception_passed(self):
index e714b154c5cadfc727e0d5090b37e124d9007460..d52f32534a0cfef10326826f9880b89f4f270888 100644 (file)
@@ -66,17 +66,12 @@ class AsyncioWaitForTest(unittest.IsolatedAsyncioTestCase):
         fut = loop.create_future()
         fut.set_result('done')
 
-        t0 = loop.time()
         ret = await asyncio.wait_for(fut, 0)
-        t1 = loop.time()
 
         self.assertEqual(ret, 'done')
         self.assertTrue(fut.done())
-        self.assertLess(t1 - t0, 0.1)
 
     async def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self):
-        loop = asyncio.get_running_loop()
-
         foo_started = False
 
         async def foo():
@@ -84,12 +79,9 @@ class AsyncioWaitForTest(unittest.IsolatedAsyncioTestCase):
             foo_started = True
 
         with self.assertRaises(asyncio.TimeoutError):
-            t0 = loop.time()
             await asyncio.wait_for(foo(), 0)
-        t1 = loop.time()
 
         self.assertEqual(foo_started, False)
-        self.assertLess(t1 - t0, 0.1)
 
     async def test_wait_for_timeout_less_then_0_or_0(self):
         loop = asyncio.get_running_loop()
@@ -113,18 +105,14 @@ class AsyncioWaitForTest(unittest.IsolatedAsyncioTestCase):
                 await started
 
                 with self.assertRaises(asyncio.TimeoutError):
-                    t0 = loop.time()
                     await asyncio.wait_for(fut, timeout)
-                t1 = loop.time()
 
                 self.assertTrue(fut.done())
                 # it should have been cancelled due to the timeout
                 self.assertTrue(fut.cancelled())
                 self.assertEqual(foo_running, False)
-                self.assertLess(t1 - t0, 0.1)
 
     async def test_wait_for(self):
-        loop = asyncio.get_running_loop()
         foo_running = None
 
         async def foo():
@@ -139,13 +127,10 @@ class AsyncioWaitForTest(unittest.IsolatedAsyncioTestCase):
         fut = asyncio.create_task(foo())
 
         with self.assertRaises(asyncio.TimeoutError):
-            t0 = loop.time()
             await asyncio.wait_for(fut, 0.1)
-        t1 = loop.time()
         self.assertTrue(fut.done())
         # it should have been cancelled due to the timeout
         self.assertTrue(fut.cancelled())
-        self.assertLess(t1 - t0, support.SHORT_TIMEOUT)
         self.assertEqual(foo_running, False)
 
     async def test_wait_for_blocking(self):
index a36119a8004f9d7e6a4ef5d5f6e2df21b56b2ae5..6e6c90a247b29120859a9bf4f7dbaccd8b9073dc 100644 (file)
@@ -163,29 +163,25 @@ class ProactorTests(test_utils.TestCase):
 
         # Wait for unset event with 0.5s timeout;
         # result should be False at timeout
-        fut = self.loop._proactor.wait_for_handle(event, 0.5)
+        timeout = 0.5
+        fut = self.loop._proactor.wait_for_handle(event, timeout)
         start = self.loop.time()
         done = self.loop.run_until_complete(fut)
         elapsed = self.loop.time() - start
 
         self.assertEqual(done, False)
         self.assertFalse(fut.result())
-        # bpo-31008: Tolerate only 450 ms (at least 500 ms expected),
-        # because of bad clock resolution on Windows
-        self.assertTrue(0.45 <= elapsed <= 0.9, elapsed)
+        self.assertGreaterEqual(elapsed, timeout - test_utils.CLOCK_RES)
 
         _overlapped.SetEvent(event)
 
         # Wait for set event;
         # result should be True immediately
         fut = self.loop._proactor.wait_for_handle(event, 10)
-        start = self.loop.time()
         done = self.loop.run_until_complete(fut)
-        elapsed = self.loop.time() - start
 
         self.assertEqual(done, True)
         self.assertTrue(fut.result())
-        self.assertTrue(0 <= elapsed < 0.3, elapsed)
 
         # asyncio issue #195: cancelling a done _WaitHandleFuture
         # must not crash
@@ -199,11 +195,8 @@ class ProactorTests(test_utils.TestCase):
         # CancelledError should be raised immediately
         fut = self.loop._proactor.wait_for_handle(event, 10)
         fut.cancel()
-        start = self.loop.time()
         with self.assertRaises(asyncio.CancelledError):
             self.loop.run_until_complete(fut)
-        elapsed = self.loop.time() - start
-        self.assertTrue(0 <= elapsed < 0.1, elapsed)
 
         # asyncio issue #195: cancelling a _WaitHandleFuture twice
         # must not crash
index 1e5ab6eb935ef154af3c5bc6d4fc828754854c28..e1101bf42eb24ec7855467c7fab800f0fff72e29 100644 (file)
@@ -36,6 +36,12 @@ from test.support import socket_helper
 from test.support import threading_helper
 
 
+# Use the maximum known clock resolution (gh-75191, gh-110088): Windows
+# GetTickCount64() has a resolution of 15.6 ms.  Use 20 ms to tolerate rounding
+# issues.
+CLOCK_RES = 0.020
+
+
 def data_file(*filename):
     fullname = os.path.join(support.TEST_HOME_DIR, *filename)
     if os.path.isfile(fullname):
diff --git a/Misc/NEWS.d/next/Tests/2023-09-29-12-48-42.gh-issue-110088.qUhRga.rst b/Misc/NEWS.d/next/Tests/2023-09-29-12-48-42.gh-issue-110088.qUhRga.rst
new file mode 100644 (file)
index 0000000..cf44a12
--- /dev/null
@@ -0,0 +1,4 @@
+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``. Patch by
+Victor Stinner.