Skip to content

Commit af944e7

Browse files
committed
Add regression test
1 parent 4e21b63 commit af944e7

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright 2025-present MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Test that the asynchronous API does not block the event loop."""
16+
from __future__ import annotations
17+
18+
import asyncio
19+
import time
20+
from test.asynchronous import AsyncIntegrationTest
21+
22+
from pymongo.errors import ServerSelectionTimeoutError
23+
24+
25+
class TestClientLoopUnblocked(AsyncIntegrationTest):
26+
async def test_client_does_not_block_loop(self):
27+
# Use an unreachable TEST-NET host to ensure that the client times out attempting to create a connection.
28+
client = self.simple_client("192.0.2.1", serverSelectionTimeoutMS=500)
29+
latencies = []
30+
31+
# If the loop is being blocked, at least one iteration will have a latency much more than 0.1 seconds
32+
async def background_task():
33+
last_run = None
34+
try:
35+
while True:
36+
if last_run:
37+
latencies.append(time.monotonic() - last_run)
38+
last_run = time.monotonic()
39+
await asyncio.sleep(0.1)
40+
except asyncio.CancelledError:
41+
latencies.append(time.monotonic() - last_run)
42+
raise
43+
44+
t = asyncio.create_task(background_task())
45+
46+
with self.assertRaisesRegex(ServerSelectionTimeoutError, "No servers found yet"):
47+
await client.admin.command("ping")
48+
49+
t.cancel()
50+
with self.assertRaises(asyncio.CancelledError):
51+
await t
52+
53+
self.assertLessEqual(
54+
sorted(latencies, reverse=True)[0],
55+
0.2,
56+
"Task took longer than twice its sleep time to run again",
57+
)

tools/synchro.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ def async_only_test(f: str) -> bool:
186186
"test_async_cancellation.py",
187187
"test_async_loop_safety.py",
188188
"test_async_contextvars_reset.py",
189+
"test_async_loop_unblocked.py",
189190
]
190191

191192

0 commit comments

Comments
 (0)