From 981465c35e9c104ef3e4de3d9c5d033337220cf7 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Wed, 18 May 2022 17:13:03 -0400 Subject: [PATCH] feat(NODE-3938): Add support for pre/post images in change streams (#3250) --- src/change_stream.ts | 63 +- src/operations/create_collection.ts | 5 + .../collection_management.spec.test.js | 5 +- .../change-streams-pre_and_post_images.json | 826 ++++++++++++++++++ .../change-streams-pre_and_post_images.yml | 350 ++++++++ .../clustered-indexes.json | 7 +- .../clustered-indexes.yml | 5 +- .../createCollection-pre_and_post_images.json | 92 ++ .../createCollection-pre_and_post_images.yml | 50 ++ .../modifyCollection-pre_and_post_images.json | 111 +++ .../modifyCollection-pre_and_post_images.yml | 58 ++ 11 files changed, 1559 insertions(+), 13 deletions(-) create mode 100644 test/spec/change-streams/unified/change-streams-pre_and_post_images.json create mode 100644 test/spec/change-streams/unified/change-streams-pre_and_post_images.yml create mode 100644 test/spec/collection-management/createCollection-pre_and_post_images.json create mode 100644 test/spec/collection-management/createCollection-pre_and_post_images.yml create mode 100644 test/spec/collection-management/modifyCollection-pre_and_post_images.json create mode 100644 test/spec/collection-management/modifyCollection-pre_and_post_images.yml diff --git a/src/change_stream.ts b/src/change_stream.ts index 86aafa6373..4997206df0 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -50,7 +50,8 @@ const CHANGE_STREAM_OPTIONS = [ 'resumeAfter', 'startAfter', 'startAtOperationTime', - 'fullDocument' + 'fullDocument', + 'fullDocumentBeforeChange' ] as const; const CURSOR_OPTIONS = [ @@ -131,11 +132,35 @@ export type ChangeStreamAggregateRawResult = { */ export interface ChangeStreamOptions extends AggregateOptions { /** - * Allowed values: 'updateLookup'. When set to 'updateLookup', - * the change stream 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. + * 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. + * + * When set to 'whenAvailable', configures the change stream to return the + * post-image of the modified document for replace and update change events + * if the post-image for this event is available. + * + * When set to 'required', the same behavior as 'whenAvailable' except that + * an error is raised if the post-image is not available. */ fullDocument?: string; + + /** + * Allowed values: 'whenAvailable', 'required', 'off'. + * + * The default is to not send a value, which is equivalent to 'off'. + * + * When set to 'whenAvailable', configures the change stream to return the + * pre-image of the modified document for replace, update, and delete change + * events if it is available. + * + * When set to 'required', the same behavior as 'whenAvailable' except that + * an error is raised if the pre-image is not available. + */ + fullDocumentBeforeChange?: string; /** The maximum amount of time for the server to wait on new documents to satisfy a change stream query. */ maxAwaitTimeMS?: number; /** @@ -230,15 +255,23 @@ export interface ChangeStreamUpdateDocument operationType: 'update'; /** * This is only set if `fullDocument` is set to `'updateLookup'` - * The fullDocument document represents the most current majority-committed version of the updated document. - * The fullDocument document may vary from the document at the time of the update operation depending on the - * number of interleaving majority-committed operations that occur between the update operation and the document lookup. + * Contains the point-in-time post-image of the modified document if the + * post-image is available and either 'required' or 'whenAvailable' was + * specified for the 'fullDocument' option when creating the change stream. */ fullDocument?: TSchema; /** Contains a description of updated and removed fields in this operation */ updateDescription: UpdateDescription; /** Namespace the update event occured on */ ns: ChangeStreamNameSpace; + /** + * Contains the pre-image of the modified or deleted document if the + * pre-image is available for the change event and either 'required' or + * 'whenAvailable' was specified for the 'fullDocumentBeforeChange' option + * when creating the change stream. If 'whenAvailable' was specified but the + * pre-image is unavailable, this will be explicitly set to null. + */ + fullDocumentBeforeChange?: TSchema; } /** @@ -254,6 +287,14 @@ export interface ChangeStreamReplaceDocument operationType: 'delete'; /** Namespace the delete event occured on */ ns: ChangeStreamNameSpace; + /** + * Contains the pre-image of the modified or deleted document if the + * pre-image is available for the change event and either 'required' or + * 'whenAvailable' was specified for the 'fullDocumentBeforeChange' option + * when creating the change stream. If 'whenAvailable' was specified but the + * pre-image is unavailable, this will be explicitly set to null. + */ + fullDocumentBeforeChange?: TSchema; } /** diff --git a/src/operations/create_collection.ts b/src/operations/create_collection.ts index 8a9e02add7..6da9bf0a6a 100644 --- a/src/operations/create_collection.ts +++ b/src/operations/create_collection.ts @@ -91,6 +91,11 @@ export interface CreateCollectionOptions extends CommandOperationOptions { expireAfterSeconds?: number; /** @experimental */ encryptedFields?: Document; + /** + * If set, enables pre-update and post-update document events to be included for any + * change streams that listen on this collection. + */ + changeStreamPreAndPostImages?: { enabled: boolean }; } /** @internal */ diff --git a/test/integration/collection-management/collection_management.spec.test.js b/test/integration/collection-management/collection_management.spec.test.js index 5906110a7b..88db4d6a0a 100644 --- a/test/integration/collection-management/collection_management.spec.test.js +++ b/test/integration/collection-management/collection_management.spec.test.js @@ -3,6 +3,9 @@ const { loadSpecTests } = require('../../spec/index'); const { runUnifiedSuite } = require('../../tools/unified-spec-runner/runner'); +// The Node driver does not have a Collection.modifyCollection helper. +const SKIPPED_TESTS = ['modifyCollection to changeStreamPreAndPostImages enabled']; + describe('Collection management unified spec tests', function () { - runUnifiedSuite(loadSpecTests('collection-management')); + runUnifiedSuite(loadSpecTests('collection-management'), SKIPPED_TESTS); }); diff --git a/test/spec/change-streams/unified/change-streams-pre_and_post_images.json b/test/spec/change-streams/unified/change-streams-pre_and_post_images.json new file mode 100644 index 0000000000..b6f0e2c3bd --- /dev/null +++ b/test/spec/change-streams/unified/change-streams-pre_and_post_images.json @@ -0,0 +1,826 @@ +{ + "description": "change-streams-pre_and_post_images", + "schemaVersion": "1.0", + "runOnRequirements": [ + { + "minServerVersion": "6.0.0", + "topologies": [ + "replicaset", + "sharded-replicaset", + "load-balanced" + ] + } + ], + "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/spec/change-streams/unified/change-streams-pre_and_post_images.yml b/test/spec/change-streams/unified/change-streams-pre_and_post_images.yml new file mode 100644 index 0000000000..3dc6afab74 --- /dev/null +++ b/test/spec/change-streams/unified/change-streams-pre_and_post_images.yml @@ -0,0 +1,350 @@ +description: "change-streams-pre_and_post_images" + +schemaVersion: "1.3" + +runOnRequirements: + - minServerVersion: "6.0.0" + topologies: [ replicaset, sharded-replicaset, load-balanced ] + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + ignoreCommandMonitoringEvents: [ collMod, insert, update, getMore, killCursors ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name change-stream-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name test + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1 } + +tests: + - description: "fullDocument:whenAvailable with changeStreamPreAndPostImages enabled" + operations: + - name: runCommand + object: *database0 + arguments: &enablePreAndPostImages + commandName: collMod + command: + collMod: *collection0Name + changeStreamPreAndPostImages: { enabled: true } + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocument: "whenAvailable" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocument: { _id: 1, x: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocument: "whenAvailable" } + + - description: "fullDocument:whenAvailable with changeStreamPreAndPostImages disabled" + operations: + - name: runCommand + object: *database0 + arguments: &disablePreAndPostImages + commandName: collMod + command: + collMod: *collection0Name + changeStreamPreAndPostImages: { enabled: false } + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocument: "whenAvailable" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocument: null + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocument: "whenAvailable" } + + - description: "fullDocument:required with changeStreamPreAndPostImages enabled" + operations: + - name: runCommand + object: *database0 + arguments: *enablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocument: "required" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocument: { _id: 1, x: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocument: "required" } + + - description: "fullDocument:required with changeStreamPreAndPostImages disabled" + operations: + - name: runCommand + object: *database0 + arguments: *disablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocument: "required" + saveResultAsEntity: &changeStream0 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: *collection0Name + pipeline: + - $changeStream: { fullDocument: "required" } + + - description: "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages enabled" + operations: + - name: runCommand + object: *database0 + arguments: *enablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "whenAvailable" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocumentBeforeChange: { _id: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "whenAvailable" } + + - description: "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages disabled" + operations: + - name: runCommand + object: *database0 + arguments: *disablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "whenAvailable" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocumentBeforeChange: null + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "whenAvailable" } + + - description: "fullDocumentBeforeChange:required with changeStreamPreAndPostImages enabled" + operations: + - name: runCommand + object: *database0 + arguments: *enablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "required" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocumentBeforeChange: { _id: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "required" } + + - description: "fullDocumentBeforeChange:required with changeStreamPreAndPostImages disabled" + operations: + - name: runCommand + object: *database0 + arguments: *disablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "required" + saveResultAsEntity: &changeStream0 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: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "required" } + + - description: "fullDocumentBeforeChange:off with changeStreamPreAndPostImages enabled" + operations: + - name: runCommand + object: *database0 + arguments: *enablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "off" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocumentBeforeChange: { $$exists: false } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "off" } + + - description: "fullDocumentBeforeChange:off with changeStreamPreAndPostImages disabled" + operations: + - name: runCommand + object: *database0 + arguments: *disablePreAndPostImages + - name: createChangeStream + object: *collection0 + arguments: + pipeline: [] + fullDocumentBeforeChange: "off" + saveResultAsEntity: &changeStream0 changeStream0 + - name: updateOne + object: *collection0 + arguments: + filter: { _id: 1 } + update: { $set: { x: 1 }} + - name: iterateUntilDocumentOrError + object: *changeStream0 + expectResult: + operationType: "update" + ns: { db: *database0Name, coll: *collection0Name } + updateDescription: { $$type: "object" } + fullDocumentBeforeChange: { $$exists: false } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + aggregate: *collection0Name + pipeline: + - $changeStream: { fullDocumentBeforeChange: "off" } diff --git a/test/spec/collection-management/clustered-indexes.json b/test/spec/collection-management/clustered-indexes.json index 3910f4d4f8..739d0fd8b6 100644 --- a/test/spec/collection-management/clustered-indexes.json +++ b/test/spec/collection-management/clustered-indexes.json @@ -1,9 +1,10 @@ { "description": "clustered-indexes", - "schemaVersion": "1.0", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "5.3" + "minServerVersion": "5.3", + "serverless": "forbid" } ], "createEntities": [ @@ -173,4 +174,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/test/spec/collection-management/clustered-indexes.yml b/test/spec/collection-management/clustered-indexes.yml index 6e3163305d..d4a69eab51 100644 --- a/test/spec/collection-management/clustered-indexes.yml +++ b/test/spec/collection-management/clustered-indexes.yml @@ -1,9 +1,10 @@ description: "clustered-indexes" -schemaVersion: "1.0" +schemaVersion: "1.4" runOnRequirements: - minServerVersion: "5.3" + serverless: forbid createEntities: - client: @@ -91,4 +92,4 @@ tests: name: *index0Name clustered: true unique: true - v: { $$type: [ int, long ] } \ No newline at end of file + v: { $$type: [ int, long ] } diff --git a/test/spec/collection-management/createCollection-pre_and_post_images.json b/test/spec/collection-management/createCollection-pre_and_post_images.json new file mode 100644 index 0000000000..f488deacd8 --- /dev/null +++ b/test/spec/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/spec/collection-management/createCollection-pre_and_post_images.yml b/test/spec/collection-management/createCollection-pre_and_post_images.yml new file mode 100644 index 0000000000..100e9a1d7c --- /dev/null +++ b/test/spec/collection-management/createCollection-pre_and_post_images.yml @@ -0,0 +1,50 @@ +description: "createCollection-pre_and_post_images" + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "6.0" + serverless: forbid + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name papi-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name test + +tests: + - description: "createCollection with changeStreamPreAndPostImages enabled" + operations: + - name: dropCollection + object: *database0 + arguments: + collection: *collection0Name + - name: createCollection + object: *database0 + arguments: + collection: *collection0Name + changeStreamPreAndPostImages: { enabled: true } + - name: assertCollectionExists + object: testRunner + arguments: + databaseName: *database0Name + collectionName: *collection0Name + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + drop: *collection0Name + databaseName: *database0Name + - commandStartedEvent: + command: + create: *collection0Name + changeStreamPreAndPostImages: { enabled: true } + databaseName: *database0Name diff --git a/test/spec/collection-management/modifyCollection-pre_and_post_images.json b/test/spec/collection-management/modifyCollection-pre_and_post_images.json new file mode 100644 index 0000000000..8026faeb17 --- /dev/null +++ b/test/spec/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/spec/collection-management/modifyCollection-pre_and_post_images.yml b/test/spec/collection-management/modifyCollection-pre_and_post_images.yml new file mode 100644 index 0000000000..75675bf2c7 --- /dev/null +++ b/test/spec/collection-management/modifyCollection-pre_and_post_images.yml @@ -0,0 +1,58 @@ +description: "modifyCollection-pre_and_post_images" + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "6.0" + serverless: forbid + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name papi-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name test + +tests: + - description: "modifyCollection to changeStreamPreAndPostImages enabled" + operations: + - name: dropCollection + object: *database0 + arguments: + collection: *collection0Name + - name: createCollection + object: *database0 + arguments: + collection: *collection0Name + changeStreamPreAndPostImages: { enabled: false } + - name: assertCollectionExists + object: testRunner + arguments: + databaseName: *database0Name + collectionName: *collection0Name + - name: modifyCollection + object: *database0 + arguments: + collection: *collection0Name + changeStreamPreAndPostImages: { enabled: true } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + drop: *collection0Name + databaseName: *database0Name + - commandStartedEvent: + command: + create: *collection0Name + changeStreamPreAndPostImages: { enabled: false } + - commandStartedEvent: + command: + collMod: *collection0Name + changeStreamPreAndPostImages: { enabled: true }