From 43c2062305d25a7c81fee27109ea30de57379690 Mon Sep 17 00:00:00 2001 From: Ben Warner Date: Wed, 15 Jun 2022 11:22:55 -0700 Subject: [PATCH] PYTHON-3093 Change streams support for user-facing PIT pre- and post-images (#972) --- pymongo/change_stream.py | 5 + pymongo/collection.py | 8 +- pymongo/database.py | 13 +- pymongo/mongo_client.py | 9 +- .../change-streams-pre_and_post_images.json | 827 ++++++++++++++++++ .../unified/change-streams.json | 63 +- .../createCollection-pre_and_post_images.json | 92 ++ .../modifyCollection-pre_and_post_images.json | 111 +++ test/unified_format.py | 2 + 9 files changed, 1076 insertions(+), 54 deletions(-) create mode 100644 test/change_streams/unified/change-streams-pre_and_post_images.json create mode 100644 test/collection_management/createCollection-pre_and_post_images.json create mode 100644 test/collection_management/modifyCollection-pre_and_post_images.json diff --git a/pymongo/change_stream.py b/pymongo/change_stream.py index b4bce8da5..d2d60e25a 100644 --- a/pymongo/change_stream.py +++ b/pymongo/change_stream.py @@ -96,6 +96,7 @@ class ChangeStream(Generic[_DocumentType]): session: Optional["ClientSession"], start_after: Optional[Mapping[str, Any]], comment: Optional[Any] = None, + full_document_before_change: Optional[str] = None, ) -> None: if pipeline is None: pipeline = [] @@ -118,6 +119,7 @@ class ChangeStream(Generic[_DocumentType]): self._pipeline = copy.deepcopy(pipeline) self._full_document = full_document + self._full_document_before_change = full_document_before_change self._uses_start_after = start_after is not None self._uses_resume_after = resume_after is not None self._resume_token = copy.deepcopy(start_after or resume_after) @@ -147,6 +149,9 @@ class ChangeStream(Generic[_DocumentType]): if self._full_document is not None: options["fullDocument"] = self._full_document + if self._full_document_before_change is not None: + options["fullDocumentBeforeChange"] = self._full_document_before_change + resume_token = self.resume_token if resume_token is not None: if self._uses_start_after: diff --git a/pymongo/collection.py b/pymongo/collection.py index 27550e0fb..b43e06c2a 100644 --- a/pymongo/collection.py +++ b/pymongo/collection.py @@ -2501,6 +2501,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]): session: Optional["ClientSession"] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, + full_document_before_change: Optional[str] = None, ) -> CollectionChangeStream[_DocumentType]: """Watch changes on this collection. @@ -2559,6 +2560,8 @@ class Collection(common.BaseObject, Generic[_DocumentType]): updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. + - `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events + may now result in a `fullDocumentBeforeChange` response field. - `resume_after` (optional): A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token @@ -2585,6 +2588,8 @@ class Collection(common.BaseObject, Generic[_DocumentType]): :Returns: A :class:`~pymongo.change_stream.CollectionChangeStream` cursor. + .. versionchanged:: 4.2 + Added ``full_document_before_change`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. @@ -2613,7 +2618,8 @@ class Collection(common.BaseObject, Generic[_DocumentType]): start_at_operation_time, session, start_after, - comment=comment, + comment, + full_document_before_change, ) def rename( diff --git a/pymongo/database.py b/pymongo/database.py index c9447c1a7..f764ade52 100644 --- a/pymongo/database.py +++ b/pymongo/database.py @@ -389,6 +389,8 @@ class Database(common.BaseObject, Generic[_DocumentType]): - ``pipeline`` (list): a list of aggregation pipeline stages - ``comment`` (str): a user-provided comment to attach to this command. This option is only supported on MongoDB >= 4.4. + - ``changeStreamPreAndPostImages`` (dict): a document with a boolean field ``enabled`` for + enabling pre- and post-images. .. versionchanged:: 4.2 Added ``encrypted_fields`` parameter. @@ -530,6 +532,7 @@ class Database(common.BaseObject, Generic[_DocumentType]): session: Optional["ClientSession"] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, + full_document_before_change: Optional[str] = None, ) -> DatabaseChangeStream[_DocumentType]: """Watch changes on this database. @@ -576,11 +579,13 @@ class Database(common.BaseObject, Generic[_DocumentType]): pipeline stages are valid after a ``$changeStream`` stage, see the MongoDB documentation on change streams for the supported stages. - `full_document` (optional): The fullDocument to pass as an option - to the ``$changeStream`` stage. Allowed values: 'updateLookup'. + to the ``$changeStream`` stage. Allowed values: 'updateLookup', 'whenAvailable', 'required'. When set to 'updateLookup', the change notification for partial updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. + - `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events + may now result in a `fullDocumentBeforeChange` response field. - `resume_after` (optional): A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token @@ -607,6 +612,9 @@ class Database(common.BaseObject, Generic[_DocumentType]): :Returns: A :class:`~pymongo.change_stream.DatabaseChangeStream` cursor. + .. versionchanged:: 4.2 + Added ``full_document_before_change`` parameter. + .. versionchanged:: 4.1 Added ``comment`` parameter. @@ -631,7 +639,8 @@ class Database(common.BaseObject, Generic[_DocumentType]): start_at_operation_time, session, start_after, - comment=comment, + comment, + full_document_before_change, ) def _command( diff --git a/pymongo/mongo_client.py b/pymongo/mongo_client.py index 5e4cf0d75..2a4b8a1d9 100644 --- a/pymongo/mongo_client.py +++ b/pymongo/mongo_client.py @@ -871,6 +871,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): session: Optional[client_session.ClientSession] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, + full_document_before_change: Optional[str] = None, ) -> ChangeStream[_DocumentType]: """Watch changes on this cluster. @@ -922,6 +923,8 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. + - `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events + may now result in a `fullDocumentBeforeChange` response field. - `resume_after` (optional): A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token @@ -948,6 +951,9 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): :Returns: A :class:`~pymongo.change_stream.ClusterChangeStream` cursor. + .. versionchanged:: 4.2 + Added ``full_document_before_change`` parameter. + .. versionchanged:: 4.1 Added ``comment`` parameter. @@ -972,7 +978,8 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]): start_at_operation_time, session, start_after, - comment=comment, + comment, + full_document_before_change, ) @property diff --git a/test/change_streams/unified/change-streams-pre_and_post_images.json b/test/change_streams/unified/change-streams-pre_and_post_images.json new file mode 100644 index 000000000..8beefb2bc --- /dev/null +++ b/test/change_streams/unified/change-streams-pre_and_post_images.json @@ -0,0 +1,827 @@ +{ + "description": "change-streams-pre_and_post_images", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "6.0.0", + "topologies": [ + "replicaset", + "sharded-replicaset", + "load-balanced" + ], + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "ignoreCommandMonitoringEvents": [ + "collMod", + "insert", + "update", + "getMore", + "killCursors" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "change-stream-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "change-stream-tests", + "documents": [ + { + "_id": 1 + } + ] + } + ], + "tests": [ + { + "description": "fullDocument:whenAvailable with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocument": "whenAvailable" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocument": { + "_id": 1, + "x": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocument": "whenAvailable" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocument:whenAvailable with changeStreamPreAndPostImages disabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocument": "whenAvailable" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocument": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocument": "whenAvailable" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocument:required with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocument": "required" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocument": { + "_id": 1, + "x": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocument": "required" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocument:required with changeStreamPreAndPostImages disabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocument": "required" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocument": "required" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "whenAvailable" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocumentBeforeChange": { + "_id": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "whenAvailable" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages disabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "whenAvailable" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocumentBeforeChange": null + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "whenAvailable" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:required with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "required" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocumentBeforeChange": { + "_id": 1 + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "required" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:required with changeStreamPreAndPostImages disabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "required" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "required" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:off with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "off" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocumentBeforeChange": { + "$$exists": false + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "off" + } + } + ] + } + } + } + ] + } + ] + }, + { + "description": "fullDocumentBeforeChange:off with changeStreamPreAndPostImages disabled", + "operations": [ + { + "name": "runCommand", + "object": "database0", + "arguments": { + "commandName": "collMod", + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "name": "createChangeStream", + "object": "collection0", + "arguments": { + "pipeline": [], + "fullDocumentBeforeChange": "off" + }, + "saveResultAsEntity": "changeStream0" + }, + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "x": 1 + } + } + } + }, + { + "name": "iterateUntilDocumentOrError", + "object": "changeStream0", + "expectResult": { + "operationType": "update", + "ns": { + "db": "change-stream-tests", + "coll": "test" + }, + "updateDescription": { + "$$type": "object" + }, + "fullDocumentBeforeChange": { + "$$exists": false + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "aggregate": "test", + "pipeline": [ + { + "$changeStream": { + "fullDocumentBeforeChange": "off" + } + } + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/test/change_streams/unified/change-streams.json b/test/change_streams/unified/change-streams.json index 572d2d6e9..c8b60ed4e 100644 --- a/test/change_streams/unified/change-streams.json +++ b/test/change_streams/unified/change-streams.json @@ -5,8 +5,7 @@ { "minServerVersion": "3.6", "topologies": [ - "replicaset", - "sharded-replicaset" + "replicaset" ], "serverless": "forbid" } @@ -314,10 +313,7 @@ "description": "Test that comment is set on getMore", "runOnRequirements": [ { - "minServerVersion": "4.4.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "4.4.0" } ], "operations": [ @@ -405,10 +401,7 @@ "description": "Test that comment is not set on getMore - pre 4.4", "runOnRequirements": [ { - "maxServerVersion": "4.3.99", - "topologies": [ - "replicaset" - ] + "maxServerVersion": "4.3.99" } ], "operations": [ @@ -806,10 +799,7 @@ "description": "$changeStream must be the first stage in a change stream pipeline sent to the server", "runOnRequirements": [ { - "minServerVersion": "3.6.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.6.0" } ], "operations": [ @@ -882,10 +872,7 @@ "description": "The server returns change stream responses in the specified server response format", "runOnRequirements": [ { - "minServerVersion": "3.6.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.6.0" } ], "operations": [ @@ -935,10 +922,7 @@ "description": "Executing a watch helper on a Collection results in notifications for changes to the specified collection", "runOnRequirements": [ { - "minServerVersion": "3.6.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.6.0" } ], "operations": [ @@ -1023,10 +1007,7 @@ "description": "Change Stream should allow valid aggregate pipeline stages", "runOnRequirements": [ { - "minServerVersion": "3.6.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.6.0" } ], "operations": [ @@ -1113,10 +1094,7 @@ "description": "Executing a watch helper on a Database results in notifications for changes to all collections in the specified database.", "runOnRequirements": [ { - "minServerVersion": "3.8.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.8.0" } ], "operations": [ @@ -1218,10 +1196,7 @@ "description": "Executing a watch helper on a MongoClient results in notifications for changes to all collections in all databases in the cluster.", "runOnRequirements": [ { - "minServerVersion": "3.8.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.8.0" } ], "operations": [ @@ -1342,10 +1317,7 @@ "description": "Test insert, update, replace, and delete event types", "runOnRequirements": [ { - "minServerVersion": "3.6.0", - "topologies": [ - "replicaset" - ] + "minServerVersion": "3.6.0" } ], "operations": [ @@ -1497,10 +1469,7 @@ "description": "Test rename and invalidate event types", "runOnRequirements": [ { - "minServerVersion": "4.0.1", - "topologies": [ - "replicaset" - ] + "minServerVersion": "4.0.1" } ], "operations": [ @@ -1577,10 +1546,7 @@ "description": "Test drop and invalidate event types", "runOnRequirements": [ { - "minServerVersion": "4.0.1", - "topologies": [ - "replicaset" - ] + "minServerVersion": "4.0.1" } ], "operations": [ @@ -1646,10 +1612,7 @@ "description": "Test consecutive resume", "runOnRequirements": [ { - "minServerVersion": "4.1.7", - "topologies": [ - "replicaset" - ] + "minServerVersion": "4.1.7" } ], "operations": [ diff --git a/test/collection_management/createCollection-pre_and_post_images.json b/test/collection_management/createCollection-pre_and_post_images.json new file mode 100644 index 000000000..f488deacd --- /dev/null +++ b/test/collection_management/createCollection-pre_and_post_images.json @@ -0,0 +1,92 @@ +{ + "description": "createCollection-pre_and_post_images", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "6.0", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "papi-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + } + ], + "tests": [ + { + "description": "createCollection with changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "dropCollection", + "object": "database0", + "arguments": { + "collection": "test" + } + }, + { + "name": "createCollection", + "object": "database0", + "arguments": { + "collection": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + }, + { + "name": "assertCollectionExists", + "object": "testRunner", + "arguments": { + "databaseName": "papi-tests", + "collectionName": "test" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "drop": "test" + }, + "databaseName": "papi-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "create": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + }, + "databaseName": "papi-tests" + } + } + ] + } + ] + } + ] +} diff --git a/test/collection_management/modifyCollection-pre_and_post_images.json b/test/collection_management/modifyCollection-pre_and_post_images.json new file mode 100644 index 000000000..8026faeb1 --- /dev/null +++ b/test/collection_management/modifyCollection-pre_and_post_images.json @@ -0,0 +1,111 @@ +{ + "description": "modifyCollection-pre_and_post_images", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "6.0", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "papi-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "test" + } + } + ], + "tests": [ + { + "description": "modifyCollection to changeStreamPreAndPostImages enabled", + "operations": [ + { + "name": "dropCollection", + "object": "database0", + "arguments": { + "collection": "test" + } + }, + { + "name": "createCollection", + "object": "database0", + "arguments": { + "collection": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + }, + { + "name": "assertCollectionExists", + "object": "testRunner", + "arguments": { + "databaseName": "papi-tests", + "collectionName": "test" + } + }, + { + "name": "modifyCollection", + "object": "database0", + "arguments": { + "collection": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "drop": "test" + }, + "databaseName": "papi-tests" + } + }, + { + "commandStartedEvent": { + "command": { + "create": "test", + "changeStreamPreAndPostImages": { + "enabled": false + } + } + } + }, + { + "commandStartedEvent": { + "command": { + "collMod": "test", + "changeStreamPreAndPostImages": { + "enabled": true + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/unified_format.py b/test/unified_format.py index cdba80c23..cb69882b2 100644 --- a/test/unified_format.py +++ b/test/unified_format.py @@ -844,6 +844,8 @@ class UnifiedSpecTestMixinV1(IntegrationTest): self.skipTest("PyMongo does not support timeoutMode") if name == "createEntities": self.maybe_skip_entity(op.get("arguments", {}).get("entities", [])) + if name == "modifyCollection": + self.skipTest("PyMongo does not support modifyCollection") def maybe_skip_entity(self, entities): for entity in entities: