summaryrefslogtreecommitdiff
path: root/jstests/change_streams
diff options
context:
space:
mode:
authorNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-04-02 16:48:04 -0400
committerNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-04-04 17:01:01 -0400
commit69005c338fe103892d2941791b12f5c06aae3394 (patch)
tree02fad539a49ccffa20a96c99949c977b7c0896a5 /jstests/change_streams
parentb7631b5698effad672d22014156dc16d6f51bf3d (diff)
downloadmongo-69005c338fe103892d2941791b12f5c06aae3394.tar.gz
SERVER-33820: Allow change streams with 'updateLookup': "fullDocument" against an entire database
Diffstat (limited to 'jstests/change_streams')
-rw-r--r--jstests/change_streams/change_stream_shell_helper.js13
-rw-r--r--jstests/change_streams/change_stream_whole_db.js8
-rw-r--r--jstests/change_streams/lookup_post_image.js460
3 files changed, 239 insertions, 242 deletions
diff --git a/jstests/change_streams/change_stream_shell_helper.js b/jstests/change_streams/change_stream_shell_helper.js
index 3c59a551209..49e4d1656bd 100644
--- a/jstests/change_streams/change_stream_shell_helper.js
+++ b/jstests/change_streams/change_stream_shell_helper.js
@@ -91,15 +91,8 @@
jsTestLog("Testing watch() with updateLookup");
cursor = coll.watch([{$project: {_id: 0}}], {fullDocument: "updateLookup"});
- // wholeDbCursor = db.watch([{$project: {_id: 0}}], {fullDocument: "updateLookup"});
-
- // TODO SERVER-33820 adds supports for 'updateLookup' against an entire database.
- assert.commandFailedWithCode(db.runCommand({
- aggregate: 1,
- pipeline: [{$changeStream: {fullDocument: "updateLookup"}}, {$project: {_id: 0}}],
- cursor: {}
- }),
- 50761);
+ wholeDbCursor = db.watch([{$project: {_id: 0}}], {fullDocument: "updateLookup"});
+
assert.writeOK(coll.update({_id: 0}, {$set: {x: 10}}));
expected = {
documentKey: {_id: 0},
@@ -109,7 +102,7 @@
updateDescription: {removedFields: [], updatedFields: {x: 10}},
};
checkNextChange(cursor, expected);
- // checkNextChange(wholeDbCursor, expected);
+ checkNextChange(wholeDbCursor, expected);
jsTestLog("Testing watch() with batchSize");
// Only test mongod because mongos uses batch size 0 for aggregate commands internally to
diff --git a/jstests/change_streams/change_stream_whole_db.js b/jstests/change_streams/change_stream_whole_db.js
index 79c58dd3e0a..b24faeead15 100644
--- a/jstests/change_streams/change_stream_whole_db.js
+++ b/jstests/change_streams/change_stream_whole_db.js
@@ -43,14 +43,6 @@
};
cst.assertNextChangesEqual({cursor: cursor, expectedChanges: [expected]});
- // Test that 'updateLookup' is not allowed with a change stream on an entire database.
- assert.commandFailedWithCode(db.runCommand({
- aggregate: 1,
- pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
- cursor: {}
- }),
- 50761);
-
// Dropping the database should invalidate the change stream.
assert.commandWorked(db.dropDatabase());
expected = {operationType: "invalidate"};
diff --git a/jstests/change_streams/lookup_post_image.js b/jstests/change_streams/lookup_post_image.js
index 46f5bfd93bf..8ca05314e42 100644
--- a/jstests/change_streams/lookup_post_image.js
+++ b/jstests/change_streams/lookup_post_image.js
@@ -13,230 +13,242 @@
let cst = new ChangeStreamTest(db);
const coll = assertDropAndRecreateCollection(db, "change_post_image");
- jsTestLog("Testing change streams without 'fullDocument' specified");
- // Test that not specifying 'fullDocument' does include a 'fullDocument' in the result for an
- // insert.
- let cursor = cst.startWatchingChanges(
- {pipeline: [{$changeStream: {}}], collection: coll, includeToken: true});
- assert.writeOK(coll.insert({_id: "fullDocument not specified"}));
- let latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "insert");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument not specified"});
-
- // Test that not specifying 'fullDocument' does include a 'fullDocument' in the result for a
- // replacement-style update.
- assert.writeOK(coll.update({_id: "fullDocument not specified"},
- {_id: "fullDocument not specified", replaced: true}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "replace");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument not specified", replaced: true});
-
- // Test that not specifying 'fullDocument' does not include a 'fullDocument' in the result for
- // a non-replacement update.
- assert.writeOK(coll.update({_id: "fullDocument not specified"}, {$set: {updated: true}}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "update");
- assert(!latestChange.hasOwnProperty("fullDocument"));
-
- jsTestLog("Testing change streams with 'fullDocument' specified as 'default'");
-
- // Test that specifying 'fullDocument' as 'default' does include a 'fullDocument' in the result
- // for an insert.
- cursor = cst.startWatchingChanges({
- collection: coll,
- pipeline: [{$changeStream: {fullDocument: "default"}}],
- includeToken: true
- });
- assert.writeOK(coll.insert({_id: "fullDocument is default"}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "insert");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is default"});
-
- // Test that specifying 'fullDocument' as 'default' does include a 'fullDocument' in the result
- // for a replacement-style update.
- assert.writeOK(coll.update({_id: "fullDocument is default"},
- {_id: "fullDocument is default", replaced: true}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "replace");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is default", replaced: true});
-
- // Test that specifying 'fullDocument' as 'default' does not include a 'fullDocument' in the
- // result for a non-replacement update.
- assert.writeOK(coll.update({_id: "fullDocument is default"}, {$set: {updated: true}}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "update");
- assert(!latestChange.hasOwnProperty("fullDocument"));
-
- jsTestLog("Testing change streams with 'fullDocument' specified as 'updateLookup'");
-
- // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in the
- // result for an insert.
- cursor = cst.startWatchingChanges({
- collection: coll,
- pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
- includeToken: true
- });
- assert.writeOK(coll.insert({_id: "fullDocument is lookup"}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "insert");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup"});
-
- // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in the
- // result for a replacement-style update.
- assert.writeOK(coll.update({_id: "fullDocument is lookup"},
- {_id: "fullDocument is lookup", replaced: true}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "replace");
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup", replaced: true});
-
- // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in the
- // result for a non-replacement update.
- assert.writeOK(coll.update({_id: "fullDocument is lookup"}, {$set: {updated: true}}));
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "update");
- assert.eq(latestChange.fullDocument,
- {_id: "fullDocument is lookup", replaced: true, updated: true});
-
- // Test that looking up the post image of an update after deleting the document will result in a
- // 'fullDocument' with a value of null.
- cursor = cst.startWatchingChanges({
- collection: coll,
- pipeline:
- [{$changeStream: {fullDocument: "updateLookup"}}, {$match: {operationType: "update"}}],
- includeToken: true
- });
- assert.writeOK(coll.update({_id: "fullDocument is lookup"}, {$set: {updatedAgain: true}}));
- assert.writeOK(coll.remove({_id: "fullDocument is lookup"}));
- // If this test is running with secondary read preference, it's necessary for the remove
- // to propagate to all secondary nodes and be available for majority reads before we can
- // assume looking up the document will fail.
- FixtureHelpers.awaitLastOpCommitted(db);
-
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "update");
- assert(latestChange.hasOwnProperty("fullDocument"));
- assert.eq(latestChange.fullDocument, null);
- const deleteDocResumePoint = latestChange._id;
-
- // Test that looking up the post image of an update after the collection has been dropped will
- // result in 'fullDocument' with a value of null. This must be done using getMore because new
- // cursors cannot be established after a collection drop.
- assert.writeOK(coll.insert({_id: "fullDocument is lookup 2"}));
- assert.writeOK(coll.update({_id: "fullDocument is lookup 2"}, {$set: {updated: true}}));
-
- // Open a $changeStream cursor with batchSize 0, so that no oplog entries are retrieved yet.
- cursor = cst.startWatchingChanges({
- collection: coll,
- pipeline: [
- {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
- {$match: {operationType: {$ne: "delete"}}}
- ],
- aggregateOptions: {cursor: {batchSize: 0}}
- });
-
- // Save another stream to test post-image lookup after the collection is recreated.
- let cursorBeforeDrop = cst.startWatchingChanges({
- collection: coll,
- pipeline: [
- {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
- {$match: {operationType: {$ne: "delete"}}}
- ],
- aggregateOptions: {cursor: {batchSize: 0}}
- });
-
- // Retrieve the 'insert' operation from the latter stream. This is necessary on a sharded
- // collection so that the documentKey is retrieved before the collection is recreated;
- // otherwise, per SERVER-31691, a uassert will occur.
- // TODO SERVER-31847: all remaining operations on the old UUID should be visible even if we have
- // not retrieved the first oplog entry before the collection is recreated.
- latestChange = cst.getOneChange(cursorBeforeDrop);
- assert.eq(latestChange.operationType, "insert");
- assert(latestChange.hasOwnProperty("fullDocument"));
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup 2"});
-
- // Drop the collection and wait until two-phase drop finishes.
- assertDropCollection(db, coll.getName());
- assert.soon(function() {
- return !TwoPhaseDropCollectionTest.collectionIsPendingDropInDatabase(db, coll.getName());
- });
- // If this test is running with secondary read preference, it's necessary for the drop
- // to propagate to all secondary nodes and be available for majority reads before we can
- // assume looking up the document will fail.
- FixtureHelpers.awaitLastOpCommitted(db);
-
- // Check the next $changeStream entry; this is the test document inserted above.
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "insert");
- assert(latestChange.hasOwnProperty("fullDocument"));
- assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup 2"});
-
- // The next entry is the 'update' operation. Because the collection has been dropped, our
- // attempt to look up the post-image results in a null document.
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "update");
- assert(latestChange.hasOwnProperty("fullDocument"));
- assert.eq(latestChange.fullDocument, null);
-
- // Test establishing new cursors with resume token on dropped collections fails.
- let res = db.runCommand({
- aggregate: coll.getName(),
- pipeline: [
- {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
- {$match: {operationType: "update"}}
- ],
- cursor: {batchSize: 0}
- });
- assert.commandFailedWithCode(res, 40615);
-
- // Test that looking up the post image of an update after the collection has been dropped and
- // created again will result in 'fullDocument' with a value of null. This must be done using
- // getMore because new cursors cannot be established after a collection drop.
-
- // Insert a document with the same _id, verify the change stream won't return it due to
- // different UUID.
- assertCreateCollection(db, coll.getName());
- assert.writeOK(coll.insert({_id: "fullDocument is lookup 2"}));
-
- // Confirm that the next entry's post-image is null since new collection has a different UUID.
- latestChange = cst.getOneChange(cursorBeforeDrop);
- assert.eq(latestChange.operationType, "update");
- assert(latestChange.hasOwnProperty("fullDocument"));
- assert.eq(latestChange.fullDocument, null);
-
- // Test that invalidate entries don't have 'fullDocument' even if 'updateLookup' is specified.
- const collInvalidate = assertDropAndRecreateCollection(db, "collInvalidate");
- cursor = cst.startWatchingChanges({
- collection: collInvalidate.getName(),
- pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
- aggregateOptions: {cursor: {batchSize: 0}}
- });
- assert.writeOK(collInvalidate.insert({_id: "testing invalidate"}));
- assertDropCollection(db, collInvalidate.getName());
- // Wait until two-phase drop finishes.
- assert.soon(function() {
- return !TwoPhaseDropCollectionTest.collectionIsPendingDropInDatabase(
- db, collInvalidate.getName());
- });
- latestChange = cst.getOneChange(cursor);
- assert.eq(latestChange.operationType, "insert");
- latestChange = cst.getOneChange(cursor, true);
- assert.eq(latestChange.operationType, "invalidate");
- assert(!latestChange.hasOwnProperty("fullDocument"));
-
- // TODO(russotto): Can just use "coll" here once read majority is working.
- // For now, using the old collection results in us reading stale data sometimes.
- jsTestLog("Testing full document lookup with a real getMore");
- const coll2 = assertDropAndRecreateCollection(db, "real_get_more");
- assert.writeOK(coll2.insert({_id: "getMoreEnabled"}));
-
- cursor = cst.startWatchingChanges({
- collection: coll2,
- pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
- });
- assert.writeOK(coll2.update({_id: "getMoreEnabled"}, {$set: {updated: true}}));
-
- let doc = cst.getOneChange(cursor);
- assert.docEq(doc["fullDocument"], {_id: "getMoreEnabled", updated: true});
+ function testUpdateLookup(coll, collToWatch) {
+ coll.drop();
+
+ jsTestLog("Testing change streams without 'fullDocument' specified");
+ // Test that not specifying 'fullDocument' does include a 'fullDocument' in the result for
+ // an insert.
+ let cursor = cst.startWatchingChanges(
+ {pipeline: [{$changeStream: {}}], collection: collToWatch, includeToken: true});
+ assert.writeOK(coll.insert({_id: "fullDocument not specified"}));
+ let latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "insert");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument not specified"});
+
+ // Test that not specifying 'fullDocument' does include a 'fullDocument' in the result for a
+ // replacement-style update.
+ assert.writeOK(coll.update({_id: "fullDocument not specified"},
+ {_id: "fullDocument not specified", replaced: true}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "replace");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument not specified", replaced: true});
+
+ // Test that not specifying 'fullDocument' does not include a 'fullDocument' in the result
+ // for a non-replacement update.
+ assert.writeOK(coll.update({_id: "fullDocument not specified"}, {$set: {updated: true}}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "update");
+ assert(!latestChange.hasOwnProperty("fullDocument"));
+
+ jsTestLog("Testing change streams with 'fullDocument' specified as 'default'");
+
+ // Test that specifying 'fullDocument' as 'default' does include a 'fullDocument' in the
+ // result for an insert.
+ cursor = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [{$changeStream: {fullDocument: "default"}}],
+ includeToken: true
+ });
+ assert.writeOK(coll.insert({_id: "fullDocument is default"}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "insert");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is default"});
+
+ // Test that specifying 'fullDocument' as 'default' does include a 'fullDocument' in the
+ // result for a replacement-style update.
+ assert.writeOK(coll.update({_id: "fullDocument is default"},
+ {_id: "fullDocument is default", replaced: true}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "replace");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is default", replaced: true});
+
+ // Test that specifying 'fullDocument' as 'default' does not include a 'fullDocument' in the
+ // result for a non-replacement update.
+ assert.writeOK(coll.update({_id: "fullDocument is default"}, {$set: {updated: true}}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "update");
+ assert(!latestChange.hasOwnProperty("fullDocument"));
+
+ jsTestLog("Testing change streams with 'fullDocument' specified as 'updateLookup'");
+
+ // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in
+ // the result for an insert.
+ cursor = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
+ includeToken: true
+ });
+ assert.writeOK(coll.insert({_id: "fullDocument is lookup"}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "insert");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup"});
+
+ // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in
+ // the result for a replacement-style update.
+ assert.writeOK(coll.update({_id: "fullDocument is lookup"},
+ {_id: "fullDocument is lookup", replaced: true}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "replace");
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup", replaced: true});
+
+ // Test that specifying 'fullDocument' as 'updateLookup' does include a 'fullDocument' in
+ // the result for a non-replacement update.
+ assert.writeOK(coll.update({_id: "fullDocument is lookup"}, {$set: {updated: true}}));
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "update");
+ assert.eq(latestChange.fullDocument,
+ {_id: "fullDocument is lookup", replaced: true, updated: true});
+
+ // Test that looking up the post image of an update after deleting the document will result
+ // in a 'fullDocument' with a value of null.
+ cursor = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [
+ {$changeStream: {fullDocument: "updateLookup"}},
+ {$match: {operationType: "update"}}
+ ],
+ includeToken: true
+ });
+ assert.writeOK(coll.update({_id: "fullDocument is lookup"}, {$set: {updatedAgain: true}}));
+ assert.writeOK(coll.remove({_id: "fullDocument is lookup"}));
+ // If this test is running with secondary read preference, it's necessary for the remove
+ // to propagate to all secondary nodes and be available for majority reads before we can
+ // assume looking up the document will fail.
+ FixtureHelpers.awaitLastOpCommitted(db);
+
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "update");
+ assert(latestChange.hasOwnProperty("fullDocument"));
+ assert.eq(latestChange.fullDocument, null);
+ const deleteDocResumePoint = latestChange._id;
+
+ // Test that looking up the post image of an update after the collection has been dropped
+ // will result in 'fullDocument' with a value of null. This must be done using getMore
+ // because new cursors cannot be established after a collection drop.
+ assert.writeOK(coll.insert({_id: "fullDocument is lookup 2"}));
+ assert.writeOK(coll.update({_id: "fullDocument is lookup 2"}, {$set: {updated: true}}));
+
+ // Open a $changeStream cursor with batchSize 0, so that no oplog entries are retrieved yet.
+ cursor = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [
+ {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
+ {$match: {operationType: {$ne: "delete"}}}
+ ],
+ aggregateOptions: {cursor: {batchSize: 0}}
+ });
+
+ // Save another stream to test post-image lookup after the collection is recreated.
+ let cursorBeforeDrop = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [
+ {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
+ {$match: {operationType: {$ne: "delete"}}}
+ ],
+ aggregateOptions: {cursor: {batchSize: 0}}
+ });
+
+ // Retrieve the 'insert' operation from the latter stream. This is necessary on a sharded
+ // collection so that the documentKey is retrieved before the collection is recreated;
+ // otherwise, per SERVER-31691, a uassert will occur.
+ // TODO SERVER-31847: all remaining operations on the old UUID should be visible even if we
+ // have not retrieved the first oplog entry before the collection is recreated.
+ latestChange = cst.getOneChange(cursorBeforeDrop);
+ assert.eq(latestChange.operationType, "insert");
+ assert(latestChange.hasOwnProperty("fullDocument"));
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup 2"});
+
+ // Drop the collection and wait until two-phase drop finishes.
+ assertDropCollection(db, coll.getName());
+ assert.soon(function() {
+ return !TwoPhaseDropCollectionTest.collectionIsPendingDropInDatabase(db,
+ coll.getName());
+ });
+ // If this test is running with secondary read preference, it's necessary for the drop
+ // to propagate to all secondary nodes and be available for majority reads before we can
+ // assume looking up the document will fail.
+ FixtureHelpers.awaitLastOpCommitted(db);
+
+ // Check the next $changeStream entry; this is the test document inserted above.
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "insert");
+ assert(latestChange.hasOwnProperty("fullDocument"));
+ assert.eq(latestChange.fullDocument, {_id: "fullDocument is lookup 2"});
+
+ // The next entry is the 'update' operation. Because the collection has been dropped, our
+ // attempt to look up the post-image results in a null document.
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "update");
+ assert(latestChange.hasOwnProperty("fullDocument"));
+ assert.eq(latestChange.fullDocument, null);
+
+ // Test establishing new cursors with resume token on dropped collections fails.
+ let res = db.runCommand({
+ aggregate: collToWatch,
+ pipeline: [
+ {$changeStream: {fullDocument: "updateLookup", resumeAfter: deleteDocResumePoint}},
+ {$match: {operationType: "update"}}
+ ],
+ cursor: {batchSize: 0}
+ });
+ assert.commandFailedWithCode(res, 40615);
+
+ // Test that looking up the post image of an update after the collection has been dropped
+ // and created again will result in 'fullDocument' with a value of null. This must be done
+ // using getMore because new cursors cannot be established after a collection drop.
+
+ // Insert a document with the same _id, verify the change stream won't return it due to
+ // different UUID.
+ assertCreateCollection(db, coll.getName());
+ assert.writeOK(coll.insert({_id: "fullDocument is lookup 2"}));
+
+ // Confirm that the next entry's post-image is null since new collection has a different
+ // UUID.
+ latestChange = cst.getOneChange(cursorBeforeDrop);
+ assert.eq(latestChange.operationType, "update");
+ assert(latestChange.hasOwnProperty("fullDocument"));
+ assert.eq(latestChange.fullDocument, null);
+
+ // Test that invalidate entries don't have 'fullDocument' even if 'updateLookup' is
+ // specified.
+ const collInvalidate = assertDropAndRecreateCollection(db, "collInvalidate");
+ cursor = cst.startWatchingChanges({
+ collection: collInvalidate.getName(),
+ pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
+ aggregateOptions: {cursor: {batchSize: 0}}
+ });
+ assert.writeOK(collInvalidate.insert({_id: "testing invalidate"}));
+ assertDropCollection(db, collInvalidate.getName());
+ // Wait until two-phase drop finishes.
+ assert.soon(function() {
+ return !TwoPhaseDropCollectionTest.collectionIsPendingDropInDatabase(
+ db, collInvalidate.getName());
+ });
+ latestChange = cst.getOneChange(cursor);
+ assert.eq(latestChange.operationType, "insert");
+ latestChange = cst.getOneChange(cursor, true);
+ assert.eq(latestChange.operationType, "invalidate");
+ assert(!latestChange.hasOwnProperty("fullDocument"));
+
+ jsTestLog("Testing full document lookup with a real getMore");
+ assert.writeOK(coll.insert({_id: "getMoreEnabled"}));
+
+ cursor = cst.startWatchingChanges({
+ collection: collToWatch,
+ pipeline: [{$changeStream: {fullDocument: "updateLookup"}}],
+ });
+ assert.writeOK(coll.update({_id: "getMoreEnabled"}, {$set: {updated: true}}));
+
+ let doc = cst.getOneChange(cursor);
+ assert.docEq(doc["fullDocument"], {_id: "getMoreEnabled", updated: true});
+ }
+
+ // Test update lookup with a change stream on a single collection.
+ testUpdateLookup(coll, coll.getName());
+
+ // Test update lookup with a change stream on a whole database.
+ testUpdateLookup(coll, 1);
cst.cleanUp();
}());