Skip to content

Commit 409c626

Browse files
committed
Add new prose test
1 parent e738bde commit 409c626

2 files changed

Lines changed: 74 additions & 4 deletions

File tree

test/asynchronous/test_client_backpressure.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import pathlib
2020
import sys
2121
from time import perf_counter
22+
from unittest import mock
2223
from unittest.mock import patch
2324

2425
from pymongo.common import MAX_ADAPTIVE_RETRIES
@@ -228,7 +229,7 @@ async def test_01_operation_retry_uses_exponential_backoff(self, random_func):
228229
self.assertTrue(abs((end1 - start1) - (end0 - start0 + 0.3)) < 0.3)
229230

230231
@async_client_context.require_failCommand_appName
231-
async def test_03_overload_retries_limited(self):
232+
async def test_02_overload_retries_limited(self):
232233
# Drivers should test that overload errors are retried a maximum of two times.
233234

234235
# 1. Let `client` be a `MongoClient`.
@@ -260,7 +261,7 @@ async def test_03_overload_retries_limited(self):
260261
self.assertEqual(len(self.listener.started_events), MAX_ADAPTIVE_RETRIES + 1)
261262

262263
@async_client_context.require_failCommand_appName
263-
async def test_04_overload_retries_limited_configured(self):
264+
async def test_03_overload_retries_limited_configured(self):
264265
# Drivers should test that overload errors are retried a maximum of maxAdaptiveRetries times.
265266
max_retries = 1
266267

@@ -294,6 +295,40 @@ async def test_04_overload_retries_limited_configured(self):
294295
# 6. Assert that the total number of started commands is max_retries + 1.
295296
self.assertEqual(len(self.listener.started_events), max_retries + 1)
296297

298+
@async_client_context.require_failCommand_fail_point
299+
async def test_04_backoff_is_not_applied_for_non_overload_errors(self):
300+
# Drivers should test that backoff is not applied for non-overload retryable errors.
301+
if _IS_SYNC:
302+
mock_target = "pymongo.synchronous.helpers._RetryPolicy.backoff"
303+
else:
304+
mock_target = "pymongo.asynchronous.helpers._RetryPolicy.backoff"
305+
306+
# 1. Let `client` be a `MongoClient`.
307+
client = self.client
308+
309+
# 2. Let `coll` be a collection.
310+
coll = client.test.test
311+
await coll.insert_one({})
312+
313+
# 3. Configure a failpoint with a retryable error that is NOT an overload error.
314+
failpoint = {
315+
"configureFailPoint": "failCommand",
316+
"mode": {"times": 1},
317+
"data": {
318+
"failCommands": ["find"],
319+
"errorCode": 91, # ShutdownInProgress
320+
"errorLabels": ["RetryableError"],
321+
},
322+
}
323+
324+
# 4. Perform a find operation with `coll` that succeeds on its first retry attempt.
325+
with mock.patch(mock_target, return_value=1) as mock_backoff:
326+
async with self.fail_point(failpoint):
327+
await coll.find_one({})
328+
329+
# 5. Assert that no backoff was used for the retry attempt.
330+
mock_backoff.assert_not_called()
331+
297332

298333
# Location of JSON test specifications.
299334
if _IS_SYNC:

test/test_client_backpressure.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import pathlib
2020
import sys
2121
from time import perf_counter
22+
from unittest import mock
2223
from unittest.mock import patch
2324

2425
from pymongo.common import MAX_ADAPTIVE_RETRIES
@@ -228,7 +229,7 @@ def test_01_operation_retry_uses_exponential_backoff(self, random_func):
228229
self.assertTrue(abs((end1 - start1) - (end0 - start0 + 0.3)) < 0.3)
229230

230231
@client_context.require_failCommand_appName
231-
def test_03_overload_retries_limited(self):
232+
def test_02_overload_retries_limited(self):
232233
# Drivers should test that overload errors are retried a maximum of two times.
233234

234235
# 1. Let `client` be a `MongoClient`.
@@ -260,7 +261,7 @@ def test_03_overload_retries_limited(self):
260261
self.assertEqual(len(self.listener.started_events), MAX_ADAPTIVE_RETRIES + 1)
261262

262263
@client_context.require_failCommand_appName
263-
def test_04_overload_retries_limited_configured(self):
264+
def test_03_overload_retries_limited_configured(self):
264265
# Drivers should test that overload errors are retried a maximum of maxAdaptiveRetries times.
265266
max_retries = 1
266267

@@ -292,6 +293,40 @@ def test_04_overload_retries_limited_configured(self):
292293
# 6. Assert that the total number of started commands is max_retries + 1.
293294
self.assertEqual(len(self.listener.started_events), max_retries + 1)
294295

296+
@client_context.require_failCommand_fail_point
297+
def test_04_backoff_is_not_applied_for_non_overload_errors(self):
298+
# Drivers should test that backoff is not applied for non-overload retryable errors.
299+
if _IS_SYNC:
300+
mock_target = "pymongo.synchronous.helpers._RetryPolicy.backoff"
301+
else:
302+
mock_target = "pymongo.helpers._RetryPolicy.backoff"
303+
304+
# 1. Let `client` be a `MongoClient`.
305+
client = self.client
306+
307+
# 2. Let `coll` be a collection.
308+
coll = client.test.test
309+
coll.insert_one({})
310+
311+
# 3. Configure a failpoint with a retryable error that is NOT an overload error.
312+
failpoint = {
313+
"configureFailPoint": "failCommand",
314+
"mode": {"times": 1},
315+
"data": {
316+
"failCommands": ["find"],
317+
"errorCode": 91, # ShutdownInProgress
318+
"errorLabels": ["RetryableError"],
319+
},
320+
}
321+
322+
# 4. Perform a find operation with `coll` that succeeds on its first retry attempt.
323+
with mock.patch(mock_target, return_value=1) as mock_backoff:
324+
with self.fail_point(failpoint):
325+
coll.find_one({})
326+
327+
# 5. Assert that no backoff was used for the retry attempt.
328+
mock_backoff.assert_not_called()
329+
295330

296331
# Location of JSON test specifications.
297332
if _IS_SYNC:

0 commit comments

Comments
 (0)