From 6c29e873c791f3a143d729a4a9f0829730e2e4f3 Mon Sep 17 00:00:00 2001 From: Iris Ho Date: Tue, 15 Jul 2025 09:10:31 -0700 Subject: [PATCH 1/2] PYTHON-4931 Add spec tests for GridFS rename --- .evergreen/remove-unimplemented-tests.sh | 1 - .evergreen/spec-patch/PYTHON-4931.patch | 93 ------------ test/asynchronous/unified_format.py | 3 + test/gridfs/delete.json | 4 +- test/gridfs/download.json | 10 +- test/gridfs/downloadByName.json | 4 +- test/gridfs/rename.json | 179 +++++++++++++++++++++++ test/unified_format.py | 3 + 8 files changed, 194 insertions(+), 103 deletions(-) delete mode 100644 .evergreen/spec-patch/PYTHON-4931.patch create mode 100644 test/gridfs/rename.json diff --git a/.evergreen/remove-unimplemented-tests.sh b/.evergreen/remove-unimplemented-tests.sh index e31011f615..d4eaff473e 100755 --- a/.evergreen/remove-unimplemented-tests.sh +++ b/.evergreen/remove-unimplemented-tests.sh @@ -8,7 +8,6 @@ rm $PYMONGO/test/client-side-encryption/spec/unified/fle2v2-EncryptedFields-vs-E rm $PYMONGO/test/client-side-encryption/spec/unified/localSchema.json # PYTHON-5143 rm $PYMONGO/test/client-side-encryption/spec/unified/maxWireVersion.json # PYTHON-5143 rm $PYMONGO/test/unified-test-format/valid-pass/poc-queryable-encryption.json # PYTHON-5143 -rm $PYMONGO/test/gridfs/rename.json # PYTHON-4931 rm $PYMONGO/test/discovery_and_monitoring/unified/pool-clear-application-error.json # PYTHON-4918 rm $PYMONGO/test/discovery_and_monitoring/unified/pool-clear-checkout-error.json # PYTHON-4918 rm $PYMONGO/test/discovery_and_monitoring/unified/pool-clear-min-pool-size-error.json # PYTHON-4918 diff --git a/.evergreen/spec-patch/PYTHON-4931.patch b/.evergreen/spec-patch/PYTHON-4931.patch deleted file mode 100644 index ad7086b378..0000000000 --- a/.evergreen/spec-patch/PYTHON-4931.patch +++ /dev/null @@ -1,93 +0,0 @@ -diff --git a/test/gridfs/delete.json b/test/gridfs/delete.json -index 277b9ed7..9a9b22fc 100644 ---- a/test/gridfs/delete.json -+++ b/test/gridfs/delete.json -@@ -497,7 +497,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ], -@@ -650,7 +650,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ], -diff --git a/test/gridfs/download.json b/test/gridfs/download.json -index f0cb8517..67658ac5 100644 ---- a/test/gridfs/download.json -+++ b/test/gridfs/download.json -@@ -338,7 +338,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -@@ -370,7 +370,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -@@ -402,7 +402,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -@@ -471,7 +471,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -@@ -514,7 +514,7 @@ - } - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -diff --git a/test/gridfs/downloadByName.json b/test/gridfs/downloadByName.json -index 7b20933c..45abaf7b 100644 ---- a/test/gridfs/downloadByName.json -+++ b/test/gridfs/downloadByName.json -@@ -290,7 +290,7 @@ - "filename": "xyz" - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] -@@ -306,7 +306,7 @@ - "revision": 999 - }, - "expectError": { -- "isError": true -+ "isClientError": true - } - } - ] diff --git a/test/asynchronous/unified_format.py b/test/asynchronous/unified_format.py index 5c221a6df0..5e1454c6bd 100644 --- a/test/asynchronous/unified_format.py +++ b/test/asynchronous/unified_format.py @@ -66,6 +66,7 @@ from bson.codec_options import DEFAULT_CODEC_OPTIONS from bson.objectid import ObjectId from gridfs import AsyncGridFSBucket, GridOut, NoFile +from gridfs.errors import CorruptGridFile from pymongo import ASCENDING, AsyncMongoClient, CursorType, _csot from pymongo.asynchronous.change_stream import AsyncChangeStream from pymongo.asynchronous.client_session import AsyncClientSession, TransactionOptions, _TxnState @@ -613,6 +614,8 @@ def process_error(self, exception, spec): # Connection errors are considered client errors. if isinstance(error, ConnectionFailure): self.assertNotIsInstance(error, NotPrimaryError) + if isinstance(error, CorruptGridFile): + pass elif isinstance(error, (InvalidOperation, ConfigurationError, EncryptionError, NoFile)): pass else: diff --git a/test/gridfs/delete.json b/test/gridfs/delete.json index 277b9ed7e1..9a9b22fc1e 100644 --- a/test/gridfs/delete.json +++ b/test/gridfs/delete.json @@ -497,7 +497,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ], @@ -650,7 +650,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ], diff --git a/test/gridfs/download.json b/test/gridfs/download.json index f0cb851708..67658ac512 100644 --- a/test/gridfs/download.json +++ b/test/gridfs/download.json @@ -338,7 +338,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ] @@ -370,7 +370,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ] @@ -402,7 +402,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ] @@ -471,7 +471,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ] @@ -514,7 +514,7 @@ } }, "expectError": { - "isError": true + "isClientError": true } } ] diff --git a/test/gridfs/downloadByName.json b/test/gridfs/downloadByName.json index 7b20933c16..45abaf7b42 100644 --- a/test/gridfs/downloadByName.json +++ b/test/gridfs/downloadByName.json @@ -290,7 +290,7 @@ "filename": "xyz" }, "expectError": { - "isError": true + "isClientError": true } } ] @@ -306,7 +306,7 @@ "revision": 999 }, "expectError": { - "isError": true + "isClientError": true } } ] diff --git a/test/gridfs/rename.json b/test/gridfs/rename.json new file mode 100644 index 0000000000..08064d4a5c --- /dev/null +++ b/test/gridfs/rename.json @@ -0,0 +1,179 @@ +{ + "description": "gridfs-rename", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0" + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "gridfs-tests" + } + }, + { + "bucket": { + "id": "bucket0", + "database": "database0" + } + }, + { + "collection": { + "id": "bucket0_files_collection", + "database": "database0", + "collectionName": "fs.files" + } + }, + { + "collection": { + "id": "bucket0_chunks_collection", + "database": "database0", + "collectionName": "fs.chunks" + } + } + ], + "initialData": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "filename", + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "filename", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + } + ] + } + ], + "tests": [ + { + "description": "rename by id", + "operations": [ + { + "name": "rename", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000001" + }, + "newFilename": "newfilename" + } + } + ], + "outcome": [ + { + "collectionName": "fs.files", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "newfilename", + "metadata": {} + }, + { + "_id": { + "$oid": "000000000000000000000002" + }, + "length": 0, + "chunkSize": 4, + "uploadDate": { + "$date": "1970-01-01T00:00:00.000Z" + }, + "filename": "filename", + "metadata": {} + } + ] + }, + { + "collectionName": "fs.chunks", + "databaseName": "gridfs-tests", + "documents": [ + { + "_id": { + "$oid": "000000000000000000000001" + }, + "files_id": { + "$oid": "000000000000000000000002" + }, + "n": 0, + "data": { + "$binary": { + "base64": "", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "rename when file id does not exist", + "operations": [ + { + "name": "rename", + "object": "bucket0", + "arguments": { + "id": { + "$oid": "000000000000000000000003" + }, + "newFilename": "newfilename" + }, + "expectError": { + "isClientError": true + } + } + ] + } + ] +} diff --git a/test/unified_format.py b/test/unified_format.py index f1e55d87b9..2b38cc6475 100644 --- a/test/unified_format.py +++ b/test/unified_format.py @@ -65,6 +65,7 @@ from bson.codec_options import DEFAULT_CODEC_OPTIONS from bson.objectid import ObjectId from gridfs import GridFSBucket, GridOut, NoFile +from gridfs.errors import CorruptGridFile from pymongo import ASCENDING, CursorType, MongoClient, _csot from pymongo.driver_info import DriverInfo from pymongo.encryption_options import _HAVE_PYMONGOCRYPT @@ -612,6 +613,8 @@ def process_error(self, exception, spec): # Connection errors are considered client errors. if isinstance(error, ConnectionFailure): self.assertNotIsInstance(error, NotPrimaryError) + if isinstance(error, CorruptGridFile): + pass elif isinstance(error, (InvalidOperation, ConfigurationError, EncryptionError, NoFile)): pass else: From dc9cfec9be46a57a33733c7f0c13b383cfdafc1d Mon Sep 17 00:00:00 2001 From: Iris Ho Date: Tue, 15 Jul 2025 09:42:12 -0700 Subject: [PATCH 2/2] don't mind me making silly mistakes --- test/asynchronous/unified_format.py | 2 +- test/unified_format.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/unified_format.py b/test/asynchronous/unified_format.py index 5e1454c6bd..5b2e3563f9 100644 --- a/test/asynchronous/unified_format.py +++ b/test/asynchronous/unified_format.py @@ -614,7 +614,7 @@ def process_error(self, exception, spec): # Connection errors are considered client errors. if isinstance(error, ConnectionFailure): self.assertNotIsInstance(error, NotPrimaryError) - if isinstance(error, CorruptGridFile): + elif isinstance(error, CorruptGridFile): pass elif isinstance(error, (InvalidOperation, ConfigurationError, EncryptionError, NoFile)): pass diff --git a/test/unified_format.py b/test/unified_format.py index 2b38cc6475..859cb29977 100644 --- a/test/unified_format.py +++ b/test/unified_format.py @@ -613,7 +613,7 @@ def process_error(self, exception, spec): # Connection errors are considered client errors. if isinstance(error, ConnectionFailure): self.assertNotIsInstance(error, NotPrimaryError) - if isinstance(error, CorruptGridFile): + elif isinstance(error, CorruptGridFile): pass elif isinstance(error, (InvalidOperation, ConfigurationError, EncryptionError, NoFile)): pass