diff --git a/.evergreen/scripts/resync-all-specs.py b/.evergreen/scripts/resync-all-specs.py index 16782de9a8..9886650a9d 100644 --- a/.evergreen/scripts/resync-all-specs.py +++ b/.evergreen/scripts/resync-all-specs.py @@ -40,13 +40,14 @@ def apply_patches(errored): try: # Avoid shell=True by passing arguments as a list. # Note: glob expansion doesn't work in shell=False, so we use a list of files. - patches = [str(p) for p in pathlib.Path("./.evergreen/spec-patch/").glob("*")] + spec_patch_dir = pathlib.Path("./.evergreen/spec-patch/") + patches = [str(p) for p in spec_patch_dir.glob("*.patch")] + patches += [str(p) for p in spec_patch_dir.glob("permanent/*.patch")] if patches: subprocess.run( [ # noqa: S603, S607 "git", "apply", - "-R", "--allow-empty", "--whitespace=fix", *patches, diff --git a/.evergreen/spec-patch/PYTHON-5809.patch b/.evergreen/spec-patch/PYTHON-5809.patch new file mode 100644 index 0000000000..22b2289782 --- /dev/null +++ b/.evergreen/spec-patch/PYTHON-5809.patch @@ -0,0 +1,97 @@ +PYMONGO DOES NOT IMPLEMENT afterClusterTime IN readConcern FOR TRANSACTIONS -- WE NEED THIS PATCH +diff --git a/test/transactions-convenient-api/unified/callback-aborts.json b/test/transactions-convenient-api/unified/callback-aborts.json +index dc8f7fb5..20642871 100644 +--- a/test/transactions-convenient-api/unified/callback-aborts.json ++++ b/test/transactions-convenient-api/unified/callback-aborts.json +@@ -308,14 +308,12 @@ + "lsid": { + "$$sessionLsid": "session0" + }, +- "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } +- }, + "autocommit": { + "$$exists": false + }, ++ "readConcern": { ++ "$$exists": false ++ }, + "startTransaction": { + "$$exists": false + }, +diff --git a/test/transactions-convenient-api/unified/callback-commits.json b/test/transactions-convenient-api/unified/callback-commits.json +index edda3864..06f791e9 100644 +--- a/test/transactions-convenient-api/unified/callback-commits.json ++++ b/test/transactions-convenient-api/unified/callback-commits.json +@@ -381,14 +381,12 @@ + "lsid": { + "$$sessionLsid": "session0" + }, +- "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } +- }, + "autocommit": { + "$$exists": false + }, ++ "readConcern": { ++ "$$exists": false ++ }, + "startTransaction": { + "$$exists": false + }, +diff --git a/test/transactions/unified/commit.json b/test/transactions/unified/commit.json +index f0339069..ab778d8d 100644 +--- a/test/transactions/unified/commit.json ++++ b/test/transactions/unified/commit.json +@@ -1040,9 +1040,7 @@ + ], + "ordered": true, + "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } ++ "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session1" +@@ -1198,9 +1196,7 @@ + ], + "ordered": true, + "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } ++ "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session1" +diff --git a/test/transactions/unified/retryable-writes.json b/test/transactions/unified/retryable-writes.json +index 21ef22b8..c196e686 100644 +--- a/test/transactions/unified/retryable-writes.json ++++ b/test/transactions/unified/retryable-writes.json +@@ -217,9 +217,7 @@ + ], + "ordered": true, + "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } ++ "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" +@@ -308,9 +306,7 @@ + ], + "ordered": true, + "readConcern": { +- "afterClusterTime": { +- "$$exists": true +- } ++ "$$exists": false + }, + "lsid": { + "$$sessionLsid": "session0" diff --git a/test/asynchronous/test_cursor.py b/test/asynchronous/test_cursor.py index 08da82762c..95604f65df 100644 --- a/test/asynchronous/test_cursor.py +++ b/test/asynchronous/test_cursor.py @@ -203,17 +203,22 @@ async def test_max_time_ms(self): async def test_maxtime_ms_message(self): db = self.db await db.t.insert_one({"x": 1}) - with self.assertRaises(Exception) as error: + with self.assertRaises(OperationFailure) as error: await db.t.find_one({"$where": delay(2)}, max_time_ms=1) - self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) + # Newer MongoDB executes $where in WASM and returns Interrupted (11601) instead + # of MaxTimeMSExpired (50) when max_time_ms kills execution; only MaxTimeMSExpired + # errors get the configured timeout details appended. + if isinstance(error.exception, ExecutionTimeout): + self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) client = await self.async_rs_client(document_class=RawBSONDocument) await client.db.t.insert_one({"x": 1}) - with self.assertRaises(Exception) as error: + with self.assertRaises(OperationFailure) as error: await client.db.t.find_one({"$where": delay(2)}, max_time_ms=1) - self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) + if isinstance(error.exception, ExecutionTimeout): + self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) async def test_max_await_time_ms(self): db = self.db diff --git a/test/client-side-encryption/etc/data/encryptedFields-prefix-suffix-ci-di.json b/test/client-side-encryption/etc/data/encryptedFields-prefix-suffix-ci-di.json new file mode 100644 index 0000000000..c43bf9390d --- /dev/null +++ b/test/client-side-encryption/etc/data/encryptedFields-prefix-suffix-ci-di.json @@ -0,0 +1,40 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "prefixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "contention": 0, + "caseSensitive": false, + "diacriticSensitive": false + }, + { + "queryType": "suffixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "contention": 0, + "caseSensitive": false, + "diacriticSensitive": false + } + ] + } + ] +} diff --git a/test/client-side-encryption/etc/data/encryptedFields-substring-ci-di.json b/test/client-side-encryption/etc/data/encryptedFields-substring-ci-di.json new file mode 100644 index 0000000000..d6aadfb877 --- /dev/null +++ b/test/client-side-encryption/etc/data/encryptedFields-substring-ci-di.json @@ -0,0 +1,31 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "substringPreview", + "strMaxLength": { + "$numberInt": "10" + }, + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "contention": 0, + "caseSensitive": false, + "diacriticSensitive": false + } + ] + } + ] +} \ No newline at end of file diff --git a/test/connection_monitoring/pool-checkout-custom-maxConnecting-is-enforced.json b/test/connection_monitoring/pool-checkout-custom-maxConnecting-is-enforced.json index 6620f82fd9..9a7c0174c5 100644 --- a/test/connection_monitoring/pool-checkout-custom-maxConnecting-is-enforced.json +++ b/test/connection_monitoring/pool-checkout-custom-maxConnecting-is-enforced.json @@ -17,13 +17,15 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 500 + "blockTimeMS": 500, + "appName": "PoolCheckoutCustomMaxConnectingIsEnforced" } }, "poolOptions": { "maxConnecting": 1, "maxPoolSize": 2, - "waitQueueTimeoutMS": 5000 + "waitQueueTimeoutMS": 5000, + "appName": "PoolCheckoutCustomMaxConnectingIsEnforced" }, "operations": [ { diff --git a/test/connection_monitoring/pool-checkout-maxConnecting-is-enforced.json b/test/connection_monitoring/pool-checkout-maxConnecting-is-enforced.json index 3a63818bfe..418ec7986f 100644 --- a/test/connection_monitoring/pool-checkout-maxConnecting-is-enforced.json +++ b/test/connection_monitoring/pool-checkout-maxConnecting-is-enforced.json @@ -19,12 +19,14 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 800 + "blockTimeMS": 800, + "appName": "PoolCheckoutMaxConnectingIsEnforced" } }, "poolOptions": { "maxPoolSize": 10, - "waitQueueTimeoutMS": 5000 + "waitQueueTimeoutMS": 5000, + "appName": "PoolCheckoutMaxConnectingIsEnforced" }, "operations": [ { diff --git a/test/connection_monitoring/pool-checkout-maxConnecting-timeout.json b/test/connection_monitoring/pool-checkout-maxConnecting-timeout.json index 4d9fda1a68..443104675d 100644 --- a/test/connection_monitoring/pool-checkout-maxConnecting-timeout.json +++ b/test/connection_monitoring/pool-checkout-maxConnecting-timeout.json @@ -19,12 +19,14 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 750 + "blockTimeMS": 750, + "appName": "PoolCheckoutMaxConnectingTimeout" } }, "poolOptions": { "maxPoolSize": 10, - "waitQueueTimeoutMS": 50 + "waitQueueTimeoutMS": 50, + "appName": "PoolCheckoutMaxConnectingTimeout" }, "operations": [ { diff --git a/test/connection_monitoring/pool-checkout-minPoolSize-connection-maxConnecting.json b/test/connection_monitoring/pool-checkout-minPoolSize-connection-maxConnecting.json index 3b0d43e877..b53b002805 100644 --- a/test/connection_monitoring/pool-checkout-minPoolSize-connection-maxConnecting.json +++ b/test/connection_monitoring/pool-checkout-minPoolSize-connection-maxConnecting.json @@ -17,13 +17,15 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 500 + "blockTimeMS": 500, + "appName": "PoolCheckoutMinPoolSizeConnectionMaxConnecting" } }, "poolOptions": { "minPoolSize": 2, "maxPoolSize": 3, - "waitQueueTimeoutMS": 5000 + "waitQueueTimeoutMS": 5000, + "appName": "PoolCheckoutMinPoolSizeConnectionMaxConnecting" }, "operations": [ { diff --git a/test/connection_monitoring/pool-checkout-returned-connection-maxConnecting.json b/test/connection_monitoring/pool-checkout-returned-connection-maxConnecting.json index 10b526e0c3..0bac21ae64 100644 --- a/test/connection_monitoring/pool-checkout-returned-connection-maxConnecting.json +++ b/test/connection_monitoring/pool-checkout-returned-connection-maxConnecting.json @@ -19,13 +19,15 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 750 + "blockTimeMS": 750, + "appName": "PoolCheckoutReturnedConnectionMaxConnecting" } }, "poolOptions": { "maxConnecting": 2, "maxPoolSize": 10, - "waitQueueTimeoutMS": 5000 + "waitQueueTimeoutMS": 5000, + "appName": "PoolCheckoutReturnedConnectionMaxConnecting" }, "operations": [ { diff --git a/test/connection_monitoring/pool-clear-interrupting-pending-connections.json b/test/connection_monitoring/pool-clear-interrupting-pending-connections.json index c1fd746329..a8452d8f84 100644 --- a/test/connection_monitoring/pool-clear-interrupting-pending-connections.json +++ b/test/connection_monitoring/pool-clear-interrupting-pending-connections.json @@ -17,11 +17,13 @@ ], "closeConnection": false, "blockConnection": true, - "blockTimeMS": 10000 + "blockTimeMS": 10000, + "appName": "PoolClearInterruptingPendingConnections" } }, "poolOptions": { - "minPoolSize": 0 + "minPoolSize": 0, + "appName": "PoolClearInterruptingPendingConnections" }, "operations": [ { diff --git a/test/test_cursor.py b/test/test_cursor.py index b63638bfab..cd13e9bfff 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -201,17 +201,22 @@ def test_max_time_ms(self): def test_maxtime_ms_message(self): db = self.db db.t.insert_one({"x": 1}) - with self.assertRaises(Exception) as error: + with self.assertRaises(OperationFailure) as error: db.t.find_one({"$where": delay(2)}, max_time_ms=1) - self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) + # Newer MongoDB executes $where in WASM and returns Interrupted (11601) instead + # of MaxTimeMSExpired (50) when max_time_ms kills execution; only MaxTimeMSExpired + # errors get the configured timeout details appended. + if isinstance(error.exception, ExecutionTimeout): + self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) client = self.rs_client(document_class=RawBSONDocument) client.db.t.insert_one({"x": 1}) - with self.assertRaises(Exception) as error: + with self.assertRaises(OperationFailure) as error: client.db.t.find_one({"$where": delay(2)}, max_time_ms=1) - self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) + if isinstance(error.exception, ExecutionTimeout): + self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception)) def test_max_await_time_ms(self): db = self.db