diff options
author | George Wangensteen <george.wangensteen@10gen.com> | 2019-07-08 13:19:22 -0400 |
---|---|---|
committer | George Wangensteen <george.wangensteen@10gen.com> | 2019-07-24 17:44:23 -0400 |
commit | f4399fceab41c4dfaad6b846b94e1366f67d93cd (patch) | |
tree | 11f0fd253c9fd9cc1670725bb037e160efc47017 /jstests | |
parent | e09a81707daf75e8965cc10d909282db158bc809 (diff) | |
download | mongo-f4399fceab41c4dfaad6b846b94e1366f67d93cd.tar.gz |
SERVER-42017 make stage names in error messages match name used
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/aggregation/expressions/date_from_parts.js | 56 | ||||
-rw-r--r-- | jstests/aggregation/expressions/date_from_string.js | 61 | ||||
-rw-r--r-- | jstests/aggregation/expressions/date_from_string_on_error.js | 4 | ||||
-rw-r--r-- | jstests/aggregation/expressions/date_to_string.js | 18 | ||||
-rw-r--r-- | jstests/aggregation/extras/utils.js | 27 | ||||
-rw-r--r-- | jstests/aggregation/single_stage_alias_error.js | 41 | ||||
-rw-r--r-- | jstests/sharding/agg_error_reports_shard_host_and_port.js | 4 | ||||
-rw-r--r-- | jstests/sharding/merge_requires_unique_index.js | 28 |
8 files changed, 157 insertions, 82 deletions
diff --git a/jstests/aggregation/expressions/date_from_parts.js b/jstests/aggregation/expressions/date_from_parts.js index cd16fe6af49..1f53aebc193 100644 --- a/jstests/aggregation/expressions/date_from_parts.js +++ b/jstests/aggregation/expressions/date_from_parts.js @@ -558,7 +558,7 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDoubleA"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.DurationOverflow, @@ -566,7 +566,7 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDecimal128A"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.DurationOverflow, @@ -574,11 +574,13 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDoubleB"}}}}]; - assertErrMsgContains(coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, millisecond: "$veryBigDecimal128B"}}}}]; - assertErrMsgContains(coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 40515, "'millisecond' must evaluate to an integer"); /* --------------------------------------------------------------------------------------- */ /* Testing that year values are only allowed in the range [0, 9999] and that month, day, hour, @@ -594,92 +596,94 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE }])); pipeline = [{$project: {date: {"$dateFromParts": {year: "$bigYear"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 40523, "'year' must evaluate to an integer in the range 0 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {year: "$smallYear"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 40523, "'year' must evaluate to an integer in the range 0 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: "$prettyBigInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'month' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: "$prettyBigNegativeInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'month' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, month: 1, day: "$prettyBigInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'day' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{ $project: {date: {"$dateFromParts": {year: 1970, month: 1, day: "$prettyBigNegativeInt"}}} }]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'day' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: "$prettyBigInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'hour' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: "$prettyBigNegativeInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'hour' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {year: 1970, hour: 0, minute: "$prettyBigInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'minute' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{ $project: {date: {"$dateFromParts": {year: 1970, hour: 0, minute: "$prettyBigNegativeInt"}}} }]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'minute' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: "$bigYear"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31095, "'isoWeekYear' must evaluate to an integer in the range 0 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: "$smallYear"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31095, "'isoWeekYear' must evaluate to an integer in the range 0 to 9999"); pipeline = [{$project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoWeek: "$prettyBigInt"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{ $project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoWeek: "$prettyBigNegativeInt"}}} }]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 31034, "'isoWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [ {$project: {date: {"$dateFromParts": {isoWeekYear: 1970, isoDayOfWeek: "$prettyBigInt"}}}} ]; - assertErrMsgContains(coll, - pipeline, - 31034, - "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); + assertErrCodeAndErrMsgContains( + coll, + pipeline, + 31034, + "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); pipeline = [{ $project: { date: {"$dateFromParts": {isoWeekYear: 1970, isoDayOfWeek: "$prettyBigNegativeInt"}} } }]; - assertErrMsgContains(coll, - pipeline, - 31034, - "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); + assertErrCodeAndErrMsgContains( + coll, + pipeline, + 31034, + "'isoDayOfWeek' must evaluate to a value in the range [-32768, 32767]"); /* --------------------------------------------------------------------------------------- */ /* Testing wrong arguments */ diff --git a/jstests/aggregation/expressions/date_from_string.js b/jstests/aggregation/expressions/date_from_string.js index e62b4f9f392..3e905d9fbfe 100644 --- a/jstests/aggregation/expressions/date_from_string.js +++ b/jstests/aggregation/expressions/date_from_string.js @@ -593,10 +593,10 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE ]; pipelines.forEach(function(pipeline) { - assertErrMsgContains(coll, - pipeline, - ErrorCodes.ConversionFailure, - "an incomplete date/time string has been found"); + assertErrCodeAndErrMsgContains(coll, + pipeline, + ErrorCodes.ConversionFailure, + "an incomplete date/time string has been found"); }); /* --------------------------------------------------------------------------------------- */ @@ -614,7 +614,7 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE ]; pipelines.forEach(function(pipeline) { - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.ConversionFailure, "Error parsing date string"); }); @@ -666,17 +666,17 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE /* Parse errors. */ let pipeline = [{$project: {date: {$dateFromString: "no-object"}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 40540, "$dateFromString only supports an object as an argument"); pipeline = [{$project: {date: {$dateFromString: {"unknown": "$tz"}}}}]; - assertErrMsgContains(coll, pipeline, 40541, "Unrecognized argument"); + assertErrCodeAndErrMsgContains(coll, pipeline, 40541, "Unrecognized argument"); pipeline = [{$project: {date: {$dateFromString: {dateString: 5}}}}]; - assertErrMsgContains(coll, - pipeline, - ErrorCodes.ConversionFailure, - "$dateFromString requires that 'dateString' be a string"); + assertErrCodeAndErrMsgContains(coll, + pipeline, + ErrorCodes.ConversionFailure, + "$dateFromString requires that 'dateString' be a string"); /* --------------------------------------------------------------------------------------- */ /* Passing in time zone with date/time string. */ @@ -723,17 +723,18 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE // Test umatched format specifier string. pipeline = [{$project: {date: {$dateFromString: {dateString: "2018-01", format: "%Y-%m-%d"}}}}]; - assertErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Data missing"); + assertErrCodeAndErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Data missing"); pipeline = [{$project: {date: {$dateFromString: {dateString: "2018-01", format: "%Y"}}}}]; - assertErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Trailing data"); + assertErrCodeAndErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Trailing data"); // Test missing specifier prefix '%'. pipeline = [{$project: {date: {$dateFromString: {dateString: "1992-26-04", format: "Y-d-m"}}}}]; - assertErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Format literal not found"); + assertErrCodeAndErrMsgContains( + coll, pipeline, ErrorCodes.ConversionFailure, "Format literal not found"); pipeline = [{$project: {date: {$dateFromString: {dateString: "1992", format: "%n"}}}}]; - assertErrMsgContains(coll, pipeline, 18536, "Invalid format character"); + assertErrCodeAndErrMsgContains(coll, pipeline, 18536, "Invalid format character"); pipeline = [{ $project: { @@ -743,28 +744,28 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE } } }]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.ConversionFailure, "you cannot pass in a date/time string with GMT offset together with a timezone argument"); pipeline = [{$project: {date: {$dateFromString: {dateString: "4/26/1992", format: 5}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 40684, "$dateFromString requires that 'format' be a string"); pipeline = [{$project: {date: {$dateFromString: {dateString: "4/26/1992", format: {}}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, 40684, "$dateFromString requires that 'format' be a string"); pipeline = [{$project: {date: {$dateFromString: {dateString: "ISO Day 6", format: "ISO Day %u"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.ConversionFailure, "The parsed date was invalid"); pipeline = [{$project: {date: {$dateFromString: {dateString: "ISO Week 52", format: "ISO Week %V"}}}}]; - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, pipeline, ErrorCodes.ConversionFailure, "The parsed date was invalid"); pipeline = [{ @@ -772,24 +773,24 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode and assertE date: {$dateFromString: {dateString: "ISO Week 1, 2018", format: "ISO Week %V, %Y"}} } }]; - assertErrMsgContains(coll, - pipeline, - ErrorCodes.ConversionFailure, - "Mixing of ISO dates with natural dates is not allowed"); + assertErrCodeAndErrMsgContains(coll, + pipeline, + ErrorCodes.ConversionFailure, + "Mixing of ISO dates with natural dates is not allowed"); pipeline = [{$project: {date: {$dateFromString: {dateString: "12/31/2018", format: "%m/%d/%G"}}}}]; - assertErrMsgContains(coll, - pipeline, - ErrorCodes.ConversionFailure, - "Mixing of ISO dates with natural dates is not allowed"); + assertErrCodeAndErrMsgContains(coll, + pipeline, + ErrorCodes.ConversionFailure, + "Mixing of ISO dates with natural dates is not allowed"); // Test embedded null bytes in the 'dateString' and 'format' fields. pipeline = [{$project: {date: {$dateFromString: {dateString: "12/31\0/2018", format: "%m/%d/%Y"}}}}]; - assertErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Data missing"); + assertErrCodeAndErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Data missing"); pipeline = [{$project: {date: {$dateFromString: {dateString: "12/31/2018", format: "%m/%d\0/%Y"}}}}]; - assertErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Trailing data"); + assertErrCodeAndErrMsgContains(coll, pipeline, ErrorCodes.ConversionFailure, "Trailing data"); })(); diff --git a/jstests/aggregation/expressions/date_from_string_on_error.js b/jstests/aggregation/expressions/date_from_string_on_error.js index ba0ce0fa573..2947c8ed35f 100644 --- a/jstests/aggregation/expressions/date_from_string_on_error.js +++ b/jstests/aggregation/expressions/date_from_string_on_error.js @@ -166,7 +166,7 @@ .toArray()); // Test that 'onError' is ignored when the 'format' is invalid. - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, [{ $project: { @@ -178,7 +178,7 @@ 40684, "$dateFromString requires that 'format' be a string"); - assertErrMsgContains( + assertErrCodeAndErrMsgContains( coll, [{ $project: { diff --git a/jstests/aggregation/expressions/date_to_string.js b/jstests/aggregation/expressions/date_to_string.js index dad8775a3e8..a1cbaa83fd9 100644 --- a/jstests/aggregation/expressions/date_to_string.js +++ b/jstests/aggregation/expressions/date_to_string.js @@ -239,11 +239,13 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode $project: {date: {$dateToString: {date: new ISODate("2017-01-04T15:08:51.911Z"), format: 5}}} }]; - assertErrMsgContains(coll, pipeline, 18533, "$dateToString requires that 'format' be a string"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 18533, "$dateToString requires that 'format' be a string"); pipeline = [{$project: {date: {$dateToString: {format: "%Y-%m-%d %H:%M:%S", timezone: "$tz"}}}}]; - assertErrMsgContains(coll, pipeline, 18628, "Missing 'date' parameter to $dateToString"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 18628, "Missing 'date' parameter to $dateToString"); pipeline = [{ $project: { @@ -256,10 +258,11 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode } } }]; - assertErrMsgContains(coll, pipeline, 40517, "timezone must evaluate to a string"); + assertErrCodeAndErrMsgContains(coll, pipeline, 40517, "timezone must evaluate to a string"); pipeline = [{$project: {date: {$dateToString: {format: "%Y-%m-%d %H:%M:%S", date: 42}}}}]; - assertErrMsgContains(coll, pipeline, 16006, "can't convert from BSON type double to Date"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 16006, "can't convert from BSON type double to Date"); pipeline = [{ $project: { @@ -272,13 +275,13 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode } } }]; - assertErrMsgContains(coll, pipeline, 40485, "unrecognized time zone identifier"); + assertErrCodeAndErrMsgContains(coll, pipeline, 40485, "unrecognized time zone identifier"); pipeline = [{ $project: {date: {$dateToString: {date: new ISODate("2017-01-04T15:08:51.911Z"), format: "%"}}} }]; - assertErrMsgContains(coll, pipeline, 18535, "Unmatched '%' at end of format string"); + assertErrCodeAndErrMsgContains(coll, pipeline, 18535, "Unmatched '%' at end of format string"); // Fails for unknown format specifier. pipeline = [{ @@ -286,5 +289,6 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode date: {$dateToString: {date: new ISODate("2017-01-04T15:08:51.911Z"), format: "%n"}} } }]; - assertErrMsgContains(coll, pipeline, 18536, "Invalid format character '%n' in format string"); + assertErrCodeAndErrMsgContains( + coll, pipeline, 18536, "Invalid format character '%n' in format string"); })(); diff --git a/jstests/aggregation/extras/utils.js b/jstests/aggregation/extras/utils.js index 3a8bbf5d071..57f61956792 100644 --- a/jstests/aggregation/extras/utils.js +++ b/jstests/aggregation/extras/utils.js @@ -269,7 +269,7 @@ function assertErrorCode(coll, pipe, code, errmsg, options = {}) { * Assert that an aggregation fails with a specific code and the error message contains the given * string. */ -function assertErrMsgContains(coll, pipe, code, expectedMessage) { +function assertErrCodeAndErrMsgContains(coll, pipe, code, expectedMessage) { const response = assert.commandFailedWithCode( coll.getDB().runCommand({aggregate: coll.getName(), pipeline: pipe, cursor: {}}), code); assert.neq( @@ -279,6 +279,31 @@ function assertErrMsgContains(coll, pipe, code, expectedMessage) { } /** + * Assert that an aggregation fails with any code and the error message contains the given + * string. + */ +function assertErrMsgContains(coll, pipe, expectedMessage) { + const response = assert.commandFailed( + coll.getDB().runCommand({aggregate: coll.getName(), pipeline: pipe, cursor: {}})); + assert.neq( + -1, + response.errmsg.indexOf(expectedMessage), + "Error message did not contain '" + expectedMessage + "', found:\n" + tojson(response)); +} + +/** + * Assert that an aggregation fails with any code and the error message does not contain the given + * string. + */ +function assertErrMsgDoesNotContain(coll, pipe, expectedMessage) { + const response = assert.commandFailed( + coll.getDB().runCommand({aggregate: coll.getName(), pipeline: pipe, cursor: {}})); + assert.eq(-1, + response.errmsg.indexOf(expectedMessage), + "Error message contained '" + expectedMessage + "'"); +} + +/** * Asserts that two arrays are equal - that is, if their sizes are equal and each element in * the 'actual' array has a matching element in the 'expected' array, without honoring elements * order. diff --git a/jstests/aggregation/single_stage_alias_error.js b/jstests/aggregation/single_stage_alias_error.js new file mode 100644 index 00000000000..cdf440093cb --- /dev/null +++ b/jstests/aggregation/single_stage_alias_error.js @@ -0,0 +1,41 @@ +/** + * Tests to verify that single aggregation stages that are input into an aggregation pipeline by + * the user under an aliased name use that name when reporting errors back to the user. + */ + +(function() { + "use strict"; + + // For assertErrMessageContains and assertErrMessageDoesNotContain. + load("jstests/aggregation/extras/utils.js"); + const coll = db.single_stage_alias_error; + + coll.drop(); + + // Assert that, despite the fact $set and $addFields are internally identical, error messages + // use only the name used by the user. + var pipeline = [{'$set': {}}]; + assertErrMsgContains(coll, pipeline, "$set"); + assertErrMsgDoesNotContain(coll, pipeline, "$addFields"); + + pipeline = [{'$addFields': {}}]; + assertErrMsgContains(coll, pipeline, "$addFields"); + assertErrMsgDoesNotContain(coll, pipeline, "$set"); + + // Assert that, despite the fact $unset is an alias for an exclusion projection, error messages + // use only the name used by the user. + pipeline = [{'$unset': [""]}]; + assertErrMsgContains(coll, pipeline, "$unset"); + assertErrMsgDoesNotContain(coll, pipeline, "$project"); + + pipeline = [{'$project': [""]}]; + assertErrMsgContains(coll, pipeline, "$project"); + assertErrMsgDoesNotContain(coll, pipeline, "$unset"); + + // Assert that, despite the fact that $replaceWith is just an alias for $replaceRoot, error + // messages contain syntax that matches the documentation for whichever name the user inputs. + var doc = {'_id': 0}; + coll.insert(doc); + pipeline = [{'$replaceWith': "abc"}]; + +})(); diff --git a/jstests/sharding/agg_error_reports_shard_host_and_port.js b/jstests/sharding/agg_error_reports_shard_host_and_port.js index 3a73c1d2493..5c9fd65d8f2 100644 --- a/jstests/sharding/agg_error_reports_shard_host_and_port.js +++ b/jstests/sharding/agg_error_reports_shard_host_and_port.js @@ -3,7 +3,7 @@ (function() { "use strict"; - load("jstests/aggregation/extras/utils.js"); // For assertErrMsgContains. + load("jstests/aggregation/extras/utils.js"); // For assertErrCodeAndErrMsgContains. const st = new ShardingTest({shards: 2, config: 1}); @@ -28,7 +28,7 @@ const pipe = [{$project: {a: {$divide: ["$_id", 0]}}}]; const divideByZeroErrorCode = 16608; - assertErrMsgContains(coll, pipe, divideByZeroErrorCode, st.rs1.getPrimary().host); + assertErrCodeAndErrMsgContains(coll, pipe, divideByZeroErrorCode, st.rs1.getPrimary().host); st.stop(); }()); diff --git a/jstests/sharding/merge_requires_unique_index.js b/jstests/sharding/merge_requires_unique_index.js index 78ee6c7f9eb..868b40c0e7e 100644 --- a/jstests/sharding/merge_requires_unique_index.js +++ b/jstests/sharding/merge_requires_unique_index.js @@ -215,20 +215,20 @@ {"newField.subField": 1, proofOfUpdate: 1, _id: 0}), {newField: {subField: "hi"}, proofOfUpdate: "PROOF"}); } else { - assertErrMsgContains(sourceColl, - [{ - $merge: { - into: { - db: targetColl.getDB().getName(), - coll: targetColl.getName(), - }, - whenMatched: "replace", - whenNotMatched: "insert", - on: Object.keys(dottedPathIndexSpec) - } - }], - ErrorCodes.ImmutableField, - "did you attempt to modify the _id or the shard key?"); + assertErrCodeAndErrMsgContains(sourceColl, + [{ + $merge: { + into: { + db: targetColl.getDB().getName(), + coll: targetColl.getName(), + }, + whenMatched: "replace", + whenNotMatched: "insert", + on: Object.keys(dottedPathIndexSpec) + } + }], + ErrorCodes.ImmutableField, + "did you attempt to modify the _id or the shard key?"); assert.doesNotThrow(() => sourceColl.aggregate([ {$project: {_id: 0}}, |