From ddc749dbf10789c7bfe2e62c70653728fa1b39d7 Mon Sep 17 00:00:00 2001 From: Casey Clements Date: Wed, 26 Nov 2025 14:57:59 -0500 Subject: [PATCH 1/3] Added long docstring to test.utils_shared.delay --- test/utils_shared.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/utils_shared.py b/test/utils_shared.py index 72fb943fc1..c24528240f 100644 --- a/test/utils_shared.py +++ b/test/utils_shared.py @@ -377,6 +377,43 @@ def oid_generated_on_process(oid): def delay(sec): + """Along with a ``$where`` operator, this returns a JavaScript function that + triggers an arbitrarily long-running operation on the MongoDB server. + + This can be useful in many time-sensitive situations, such as testing + client-side timeouts and signal handling. + + Note that you must have at least one matching document in the collection, + otherwise the server may choose not to invoke the ``$where`` function. + + Examples + -------- + Insert a document and verify a normal find: + + >>> db.coll.insert_one({'x': 1}) + >>> db.coll.find_one({'x': 1})['x'] + 1 + + The following will wait 2.5 seconds before returning: + + >>> db.coll.find_one({'$where': delay(2.5)})['x'] + 1 + + Use ``delay`` to trigger a KeyboardInterrupt while the server is working: + + >>> import signal + >>> def sigalarm(num, frame): + ... raise KeyboardInterrupt + >>> signal.signal(signal.SIGALRM, sigalarm) + >>> signal.alarm(1) + + >>> raised = False + >>> try: + ... db.coll.find_one({"$where": delay(1.5)}) + ... except KeyboardInterrupt: + ... raised = True + >>> assert raised + """ return """function() { sleep(%f * 1000); return true; }""" % sec From 20664ffac878ed13d4eb35210ebb34a1b1f55b38 Mon Sep 17 00:00:00 2001 From: Casey Clements Date: Wed, 26 Nov 2025 15:00:35 -0500 Subject: [PATCH 2/3] Second long example using code blocks. --- test/utils_shared.py | 62 ++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/test/utils_shared.py b/test/utils_shared.py index c24528240f..70a195215a 100644 --- a/test/utils_shared.py +++ b/test/utils_shared.py @@ -377,44 +377,50 @@ def oid_generated_on_process(oid): def delay(sec): - """Along with a ``$where`` operator, this returns a JavaScript function that - triggers an arbitrarily long-running operation on the MongoDB server. + """Along with a ``$where`` operator, this triggers an arbitrarily long-running + operation on the server. - This can be useful in many time-sensitive situations, such as testing - client-side timeouts and signal handling. + This can be useful in time-sensitive tests (e.g., timeouts, signals). + Note that you must have at least one document in the collection or the + server may decide not to sleep at all. - Note that you must have at least one matching document in the collection, - otherwise the server may choose not to invoke the ``$where`` function. + Example + ------- - Examples - -------- - Insert a document and verify a normal find: + .. code-block:: python - >>> db.coll.insert_one({'x': 1}) - >>> db.coll.find_one({'x': 1})['x'] - 1 + db.coll.insert_one({"x": 1}) + db.test.find_one({"x": 1}) + # {'x': 1, '_id': ObjectId('54f4e12bfba5220aa4d6dee8')} - The following will wait 2.5 seconds before returning: + # The following will wait 2.5 seconds before returning. + db.test.find_one({"$where": delay(2.5)}) + # {'x': 1, '_id': ObjectId('54f4e12bfba5220aa4d6dee8')} - >>> db.coll.find_one({'$where': delay(2.5)})['x'] - 1 + Using ``delay`` to provoke a KeyboardInterrupt + ---------------------------------------------- - Use ``delay`` to trigger a KeyboardInterrupt while the server is working: + .. code-block:: python - >>> import signal - >>> def sigalarm(num, frame): - ... raise KeyboardInterrupt - >>> signal.signal(signal.SIGALRM, sigalarm) - >>> signal.alarm(1) + import signal - >>> raised = False - >>> try: - ... db.coll.find_one({"$where": delay(1.5)}) - ... except KeyboardInterrupt: - ... raised = True - >>> assert raised + # Raise KeyboardInterrupt in 1 second + def sigalarm(num, frame): + raise KeyboardInterrupt + + + signal.signal(signal.SIGALRM, sigalarm) + signal.alarm(1) + + raised = False + try: + clxn.find_one({"$where": delay(1.5)}) + except KeyboardInterrupt: + raised = True + + assert raised """ - return """function() { sleep(%f * 1000); return true; }""" % sec + return "function() { sleep(%f * 1000); return true; }" % sec def camel_to_snake(camel): From ec11609bec6a004bf3b376a159a1a8fd96374846 Mon Sep 17 00:00:00 2001 From: Casey Clements Date: Mon, 1 Dec 2025 12:16:07 -0500 Subject: [PATCH 3/3] Added section in CONTRIBUTING.md about test.utils_shared.delay --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2cf15a9838..7e35063af6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -387,6 +387,11 @@ If you are running one of the `no-responder` tests, omit the `run-server` step. To run any of the test suites with minimum supported dependencies, pass `--test-min-deps` to `just setup-tests`. +## Testing time-dependent operations + +- `test.utils_shared.delay` - One can trigger an arbitrarily long-running operation on the server using this delay utility + in combination with a `$where` operation. Use this to test behaviors around timeouts or signals. + ## Adding a new test suite - If adding new tests files that should only be run for that test suite, add a pytest marker to the file and add