diff options
author | Bernard Gorman <bernard.gorman@gmail.com> | 2017-10-04 18:26:30 +0100 |
---|---|---|
committer | Bernard Gorman <bernard.gorman@gmail.com> | 2017-10-10 10:36:25 +0100 |
commit | f74896d9aae90d0b31eeb06f37f59ca386c03570 (patch) | |
tree | a05779131bc9fd608d2e6c6c0608251ea7a21d81 /jstests/change_streams | |
parent | 6ad292704df43031ee94f696e709bf6285376ed4 (diff) | |
download | mongo-f74896d9aae90d0b31eeb06f37f59ca386c03570.tar.gz |
SERVER-29137 Implement $changeStream whitelist
Diffstat (limited to 'jstests/change_streams')
-rw-r--r-- | jstests/change_streams/change_stream_whitelist.js | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/jstests/change_streams/change_stream_whitelist.js b/jstests/change_streams/change_stream_whitelist.js new file mode 100644 index 00000000000..817dd35fef4 --- /dev/null +++ b/jstests/change_streams/change_stream_whitelist.js @@ -0,0 +1,61 @@ +/** + * Tests that only whitelisted stages are permitted to run in a $changeStream pipeline. + */ + +(function() { + "use strict"; + + load('jstests/aggregation/extras/utils.js'); // For assertErrorCode(). + + // Bare-bones $changeStream pipeline which will be augmented during tests. + const changeStream = [{$changeStream: {}}]; + const coll = db[jsTestName()]; + + // List of non-$changeStream stages which are explicitly whitelisted. + const whitelist = [ + {$match: {_id: {$exists: true}}}, + {$project: {_id: 1}}, + {$addFields: {newField: 1}}, + {$replaceRoot: {newRoot: {_id: "$_id"}}}, + {$redact: "$$DESCEND"} + ]; + + // List of stages which the whitelist mechanism will prevent from running in a $changeStream. + // Does not include stages which are blacklisted but already implicitly prohibited, e.g. both + // $currentOp and $changeStream must be the first stage in a pipeline. + const blacklist = [ + {$group: {_id: "$_id"}}, + {$sort: {_id: 1}}, + {$skip: 100}, + {$limit: 100}, + {$sample: {size: 100}}, + {$unwind: "$_id"}, + {$lookup: {from: "coll", as: "as", localField: "_id", foreignField: "_id"}}, + { + $graphLookup: { + from: "coll", + as: "as", + startWith: "$_id", + connectFromField: "_id", + connectToField: "_id" + } + }, + {$bucketAuto: {groupBy: "$_id", buckets: 2}}, + {$facet: {facetPipe: [{$match: {_id: {$exists: true}}}]}} + ]; + + // Verify that each of the whitelisted stages are permitted to run in a $changeStream. + for (let allowedStage of whitelist) { + assert.commandWorked(db.runCommand( + {aggregate: coll.getName(), pipeline: changeStream.concat(allowedStage), cursor: {}})); + } + + // Verify that all of the whitelisted stages are able to run in a $changeStream together. + assert.commandWorked(db.runCommand( + {aggregate: coll.getName(), pipeline: changeStream.concat(whitelist), cursor: {}})); + + // Verify that a $changeStream pipeline fails to validate if a blacklisted stage is present. + for (let bannedStage of blacklist) { + assertErrorCode(coll, changeStream.concat(bannedStage), ErrorCodes.IllegalOperation); + } +}());
\ No newline at end of file |