From 1dbdd89ea20ad7d4f5c6f7e8953d2348bc336270 Mon Sep 17 00:00:00 2001 From: Sebastien Mendez Date: Wed, 9 Jun 2021 14:46:39 +0200 Subject: SERVER-56497 Add assert.throwsCode shell helper for testing --- jstests/aggregation/add_with_date.js | 32 +++++++++++----------- jstests/aggregation/dbref.js | 3 +- jstests/aggregation/illegal_reference_in_match.js | 3 +- .../sources/setWindowFields/derivative.js | 12 +++----- jstests/change_streams/lookup_pre_image.js | 3 +- jstests/core/always_true_false.js | 3 +- jstests/core/minmax.js | 30 ++++++++------------ .../agg_configurable_memory_limits.js | 12 ++++---- ...ream_pre_image_lookup_whole_db_whole_cluster.js | 10 +++---- jstests/noPassthrough/low_js_heap_limit.js | 4 +-- .../query_yields_catch_index_corruption.js | 5 ++-- jstests/replsets/linearizable_read_concern.js | 16 +++++------ .../change_stream_on_system_collection.js | 4 +-- jstests/sharding/check_sharding_index_versioned.js | 5 ++-- jstests/sharding/query/graph_lookup.js | 5 ++-- jstests/sharding/query/lookup.js | 22 +++++++-------- jstests/sharding/query/mrShardedOutput.js | 24 ++++++++-------- .../out_fails_to_replace_sharded_collection.js | 7 ++--- jstests/sharding/query/view_on_shard_rewrite.js | 4 +-- src/mongo/shell/assert.js | 12 ++++++++ 20 files changed, 103 insertions(+), 113 deletions(-) diff --git a/jstests/aggregation/add_with_date.js b/jstests/aggregation/add_with_date.js index 36ded4f7a86..8e3cb8597b5 100644 --- a/jstests/aggregation/add_with_date.js +++ b/jstests/aggregation/add_with_date.js @@ -71,19 +71,19 @@ assert.eq(ISODate("2019-01-30T07:30:12.596Z"), // The result of an addition must remain in the range of int64_t in order to convert back to a Date; // an overflow into the domain of double-precision floating point numbers triggers a query-fatal // error. -let err = assert.throws(() => getResultOfExpression({$add: ["$dateVal", "$overflowDouble"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode(() => getResultOfExpression({$add: ["$dateVal", "$overflowDouble"]}), + ErrorCodes.Overflow); -err = assert.throws(() => getResultOfExpression({$add: ["$dateVal", "$overflowInt64"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode(() => getResultOfExpression({$add: ["$dateVal", "$overflowInt64"]}), + ErrorCodes.Overflow); -err = assert.throws( - () => getResultOfExpression({$add: ["$dateVal", "$int64Val", "$overflowDouble"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode( + () => getResultOfExpression({$add: ["$dateVal", "$int64Val", "$overflowDouble"]}), + ErrorCodes.Overflow); -err = assert.throws( - () => getResultOfExpression({$add: ["$int64Val", "$dateVal", "$overflowDouble"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode( + () => getResultOfExpression({$add: ["$int64Val", "$dateVal", "$overflowDouble"]}), + ErrorCodes.Overflow); // One quirk of date addition semantics is that an overflow into the domain of Decimal128 is not // fatal and instead results in an invalid "NaN" Date value. @@ -94,19 +94,19 @@ assert.eq(nanDate, assert.eq(nanDate, getResultOfExpression({$add: ["$int64Val", "$dateVal", "$overflowDecimal"]})); // Adding a double-typed NaN to a date value. -err = assert.throws(() => getResultOfExpression({$add: ["$dateVal", "$nanDouble"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode(() => getResultOfExpression({$add: ["$dateVal", "$nanDouble"]}), + ErrorCodes.Overflow); -err = assert.throws(() => getResultOfExpression({$add: ["$nanDouble", "$dateVal"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode(() => getResultOfExpression({$add: ["$nanDouble", "$dateVal"]}), + ErrorCodes.Overflow); // Adding a Decimal128-typed NaN to a date value. assert.eq(nanDate, getResultOfExpression({$add: ["$dateVal", "$nanDecimal"]})); assert.eq(nanDate, getResultOfExpression({$add: ["$nanDecimal", "$dateVal"]})); // Addition with a date, a double-typed NaN, and a third value. -err = assert.throws(() => getResultOfExpression({$add: ["$dateVal", "$doubleVal", "$nanDouble"]})); -assert.eq(ErrorCodes.Overflow, err.code); +assert.throwsWithCode(() => getResultOfExpression({$add: ["$dateVal", "$doubleVal", "$nanDouble"]}), + ErrorCodes.Overflow); // Addition with a date, and both types of NaN. assert.eq(nanDate, getResultOfExpression({$add: ["$dateVal", "$nanDouble", "$nanDecimal"]})); diff --git a/jstests/aggregation/dbref.js b/jstests/aggregation/dbref.js index dbf7d48bb80..7860a66e790 100644 --- a/jstests/aggregation/dbref.js +++ b/jstests/aggregation/dbref.js @@ -72,8 +72,7 @@ assert.eq(projectOnlyPipeline({$ref: "$link.$ref"}), [{_id: 0, $ref: otherColl.g // One cannot refer to a top-level DBRef field, however, as it will be interpreted as a variable // dereference. -const err = assert.throws(() => coll.aggregate({$project: {x: "$$ref"}}).toArray()); -assert.eq(err.code, 17276); +assert.throwsWithCode(() => coll.aggregate({$project: {x: "$$ref"}}).toArray(), 17276); // It can be accessed through $$ROOT, however. assert.eq(coll.aggregate([ diff --git a/jstests/aggregation/illegal_reference_in_match.js b/jstests/aggregation/illegal_reference_in_match.js index eca2df0009c..872f806b11d 100644 --- a/jstests/aggregation/illegal_reference_in_match.js +++ b/jstests/aggregation/illegal_reference_in_match.js @@ -31,6 +31,5 @@ const pipeline = [ } ]; -const err = assert.throws(() => coll.aggregate(pipeline)); -assert.eq(err.code, 16410); +assert.throwsWithCode(() => coll.aggregate(pipeline), 16410); })(); diff --git a/jstests/aggregation/sources/setWindowFields/derivative.js b/jstests/aggregation/sources/setWindowFields/derivative.js index f125bf96872..b764d104ed4 100644 --- a/jstests/aggregation/sources/setWindowFields/derivative.js +++ b/jstests/aggregation/sources/setWindowFields/derivative.js @@ -210,8 +210,7 @@ assert.commandWorked(coll.insert([ {time: 1, y: 100}, {time: 2, y: 100}, ])); -let err = assert.throws(() => coll.aggregate(derivativeStage('millisecond')).toArray()); -assert.eq(err.code, 5624900); +assert.throwsWithCode(() => coll.aggregate(derivativeStage('millisecond')).toArray(), 5624900); result = coll.aggregate([derivativeStage(), {$unset: '_id'}]).toArray(); assert.sameMembers(result, [ {time: 0, y: 100, dy: null}, @@ -227,8 +226,7 @@ assert.commandWorked(coll.insert([ {time: ISODate("2020-01-01T00:00:00.002Z"), y: 6}, {time: ISODate("2020-01-01T00:00:00.003Z"), y: 5}, ])); -err = assert.throws(() => coll.aggregate(derivativeStage()).toArray()); -assert.eq(err.code, 5624901); +assert.throwsWithCode(() => coll.aggregate(derivativeStage()).toArray(), 5624901); result = coll.aggregate([derivativeStage('millisecond'), {$unset: '_id'}]).toArray(); assert.sameMembers(result, [ {time: ISODate("2020-01-01T00:00:00.000Z"), y: 5, dy: null}, @@ -288,10 +286,8 @@ assert.commandWorked(coll.insert([ {time: 12, y: 0}, {time: 13, y: 0}, ])); -err = assert.throws(() => coll.aggregate(derivativeStage()).toArray()); -assert.eq(err.code, 5624901); -err = assert.throws(() => coll.aggregate(derivativeStage('second')).toArray()); -assert.eq(err.code, 5624900); +assert.throwsWithCode(() => coll.aggregate(derivativeStage()).toArray(), 5624901); +assert.throwsWithCode(() => coll.aggregate(derivativeStage('second')).toArray(), 5624900); // Some examples of unbounded windows. coll.drop(); diff --git a/jstests/change_streams/lookup_pre_image.js b/jstests/change_streams/lookup_pre_image.js index 465a42a159b..3cad36ea3cc 100644 --- a/jstests/change_streams/lookup_pre_image.js +++ b/jstests/change_streams/lookup_pre_image.js @@ -116,8 +116,7 @@ assert.docEq(latestChange.fullDocument, {_id: "y", foo: "bar"}); // The "whenAvailable" cursor retrieves a document without the pre-image... assert.docEq(latestChange, cst.getOneChange(csPreImageWhenAvailableCursor)); // ... but the "required" cursor throws an exception. -const csErr = assert.throws(() => cst.getOneChange(csPreImageRequiredCursor)); -assert.eq(csErr.code, 51770); +assert.throwsWithCode(() => cst.getOneChange(csPreImageRequiredCursor), 51770); // Test pre-image lookup for an op-style update operation. assert.commandWorked(coll.update({_id: "y"}, {$set: {foo: "baz"}})); diff --git a/jstests/core/always_true_false.js b/jstests/core/always_true_false.js index 0b32ac22a16..9f6110d29e5 100644 --- a/jstests/core/always_true_false.js +++ b/jstests/core/always_true_false.js @@ -36,8 +36,7 @@ assert(coll.drop()); // Check that a rooted-$or query with each clause false will not return any results. assert.commandWorked(coll.insert([{}, {}, {}])); -const emptyOrError = assert.throws(() => coll.find({$or: []}).itcount()); -assert.eq(emptyOrError.code, ErrorCodes.BadValue); +assert.throwsWithCode(() => coll.find({$or: []}).itcount(), ErrorCodes.BadValue); assert.eq(coll.find({$or: [{$alwaysFalse: 1}]}).itcount(), 0); assert.eq(coll.find({$or: [{a: {$all: []}}]}).itcount(), 0); diff --git a/jstests/core/minmax.js b/jstests/core/minmax.js index b4f181689a2..fb16e718bca 100644 --- a/jstests/core/minmax.js +++ b/jstests/core/minmax.js @@ -47,11 +47,10 @@ assert.eq(1, coll.find().hint({a: 1, b: -1}).max({a: 1, b: 1.5}).hint({a: 1, b: -1}).toArray().length); // Check that min/max requires a hint. -let error = assert.throws(() => coll.find().min({a: 1, b: 2}).max({a: 2, b: 1}).toArray()); -assert.eq(error.code, 51173); +assert.throwsWithCode(() => coll.find().min({a: 1, b: 2}).max({a: 2, b: 1}).toArray(), 51173); // Hint doesn't match. -error = assert.throws(function() { +let error = assert.throws(function() { coll.find().min({a: 1}).hint({a: 1, b: -1}).toArray(); }); assert.eq(error.code, 51174, error); @@ -72,10 +71,9 @@ error = assert.throws(function() { }); assert.eq(error.code, ErrorCodes.NoQueryExecutionPlans, error); -error = assert.throws(function() { +assert.throwsWithCode(function() { coll.find().max({a: 1}).hint({$natural: 1}).toArray(); -}); -assert.eq(error.code, ErrorCodes.NoQueryExecutionPlans); +}, ErrorCodes.NoQueryExecutionPlans); coll.drop(); assert.commandWorked(coll.createIndex({a: 1})); @@ -85,30 +83,26 @@ for (let i = 0; i < 10; ++i) { // Reverse direction scan of the a:1 index between a:6 (inclusive) and a:3 (exclusive) is // expected to fail, as max must be > min. -error = assert.throws(function() { +assert.throwsWithCode(function() { coll.find().hint({a: 1}).min({a: 6}).max({a: 3}).sort({a: -1}).toArray(); -}); -assert.eq(error.code, 51175); +}, 51175); // A find with identical min and max values is expected to fail, as max is exclusive. -error = assert.throws(function() { +assert.throwsWithCode(function() { coll.find().hint({a: 1}).min({a: 2}).max({a: 2}).toArray(); -}); -assert.eq(error.code, 51175); +}, 51175); -error = assert.throws(function() { +assert.throwsWithCode(function() { coll.find().hint({a: 1}).min({a: 2}).max({a: 2}).sort({a: -1}).toArray(); -}); -assert.eq(error.code, 51175); +}, 51175); coll.drop(); addData(); assert.commandWorked(coll.createIndex({a: 1, b: 1})); -error = assert.throws(function() { +assert.throwsWithCode(function() { coll.find().min({a: 1, b: 2}).max({a: 1, b: 2}).hint({a: 1, b: 1}).toArray(); -}); -assert.eq(error.code, 51175); +}, 51175); // Test ascending index. coll.drop(); diff --git a/jstests/noPassthrough/agg_configurable_memory_limits.js b/jstests/noPassthrough/agg_configurable_memory_limits.js index 0441c7d4bb6..5e5df25f167 100644 --- a/jstests/noPassthrough/agg_configurable_memory_limits.js +++ b/jstests/noPassthrough/agg_configurable_memory_limits.js @@ -19,18 +19,18 @@ assert.doesNotThrow( // Now lower the limit to test that it's configuration is obeyed. assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryMaxPushBytes: 100})); -let error = assert.throws( - () => coll.aggregate([{$unwind: "$y"}, {$group: {_id: null, strings: {$push: "$y"}}}])); -assert.eq(error.code, ErrorCodes.ExceededMemoryLimit); +assert.throwsWithCode( + () => coll.aggregate([{$unwind: "$y"}, {$group: {_id: null, strings: {$push: "$y"}}}]), + ErrorCodes.ExceededMemoryLimit); // Test that using $addToSet behaves similarly. assert.doesNotThrow( () => coll.aggregate([{$unwind: "$y"}, {$group: {_id: null, strings: {$addToSet: "$y"}}}])); assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryMaxAddToSetBytes: 100})); -error = assert.throws( - () => coll.aggregate([{$unwind: "$y"}, {$group: {_id: null, strings: {$addToSet: "$y"}}}])); -assert.eq(error.code, ErrorCodes.ExceededMemoryLimit); +assert.throwsWithCode( + () => coll.aggregate([{$unwind: "$y"}, {$group: {_id: null, strings: {$addToSet: "$y"}}}]), + ErrorCodes.ExceededMemoryLimit); MongoRunner.stopMongod(conn); }()); diff --git a/jstests/noPassthrough/change_stream_pre_image_lookup_whole_db_whole_cluster.js b/jstests/noPassthrough/change_stream_pre_image_lookup_whole_db_whole_cluster.js index dc5b9ee9d3f..8d0fc941020 100644 --- a/jstests/noPassthrough/change_stream_pre_image_lookup_whole_db_whole_cluster.js +++ b/jstests/noPassthrough/change_stream_pre_image_lookup_whole_db_whole_cluster.js @@ -54,17 +54,16 @@ assert.commandWorked(collWithPreImages.remove({_id: 0})); assert.commandWorked(sentinelColl.insert({_id: "last_change_sentinel"})); // Confirm that attempting to open a whole-db stream on this database with mode "required" fails. -const csWholeDBErr = assert.throws(function() { +assert.throwsWithCode(function() { const wholeDBStream = testDB.watch([], {fullDocumentBeforeChange: "required", resumeAfter: resumeToken}); return assert.soon(() => wholeDBStream.hasNext() && wholeDBStream.next().documentKey._id === "last_change_sentinel"); -}); -assert.eq(csWholeDBErr.code, 51770); +}, 51770); // Confirm that attempting to open a whole-cluster stream on with mode "required" fails. -const csWholeClusterErr = assert.throws(function() { +assert.throwsWithCode(function() { const wholeClusterStream = adminDB.watch([], { fullDocumentBeforeChange: "required", resumeAfter: resumeToken, @@ -73,8 +72,7 @@ const csWholeClusterErr = assert.throws(function() { return assert.soon(() => wholeClusterStream.hasNext() && wholeClusterStream.next().documentKey._id == "last_change_sentinel"); -}); -assert.eq(csWholeClusterErr.code, 51770); +}, 51770); // However, if we open a whole-db or whole-cluster stream that filters for only the namespace with // pre-images, then the cursor can proceed. This is because the $match gets moved ahead of the diff --git a/jstests/noPassthrough/low_js_heap_limit.js b/jstests/noPassthrough/low_js_heap_limit.js index a50072b5bf4..b0e152895f6 100644 --- a/jstests/noPassthrough/low_js_heap_limit.js +++ b/jstests/noPassthrough/low_js_heap_limit.js @@ -9,8 +9,8 @@ var db = conn.getDB('db'); assert.commandWorked(db.adminCommand({setParameter: 1, jsHeapLimitMB: 1})); db.foo.insert({x: 1}); -const e = assert.throws(() => db.foo.findOne({$where: 'sleep(10000);'})); -assert.eq(e.code, ErrorCodes.ExceededMemoryLimit); +assert.throwsWithCode(() => db.foo.findOne({$where: 'sleep(10000);'}), + ErrorCodes.ExceededMemoryLimit); var returnCode = runProgram("mongo", "--jsHeapLimitMB=1", "--nodb", "--eval='exit();'"); assert.eq(returnCode, 1); diff --git a/jstests/noPassthrough/query_yields_catch_index_corruption.js b/jstests/noPassthrough/query_yields_catch_index_corruption.js index 0fd56037dec..d05119e8b1e 100644 --- a/jstests/noPassthrough/query_yields_catch_index_corruption.js +++ b/jstests/noPassthrough/query_yields_catch_index_corruption.js @@ -47,10 +47,9 @@ function createDanglingIndexEntry(doc) { const sessionDB = session.getDatabase(dbName); session.startTransaction(); - const error = assert.throws(() => { + assert.throwsWithCode(() => { sessionDB[collName].find(doc).toArray(); - }); - assert.eq(error.code, ErrorCodes.DataCorruptionDetected); + }, ErrorCodes.DataCorruptionDetected); session.abortTransaction_forTesting(); } diff --git a/jstests/replsets/linearizable_read_concern.js b/jstests/replsets/linearizable_read_concern.js index 4ea116bf40b..f492bf9046d 100644 --- a/jstests/replsets/linearizable_read_concern.js +++ b/jstests/replsets/linearizable_read_concern.js @@ -82,16 +82,16 @@ assert.eq(opTimeCmd.errmsg, "afterOpTime not compatible with linearizable read c assert.eq(opTimeCmd.code, ErrorCodes.FailedToParse); // A $out aggregation is not allowed with readConcern level "linearizable". -let outResult = assert.throws(() => primary.getDB("test").foo.aggregate( - [{$out: "out"}], {readConcern: {level: "linearizable"}})); -assert.eq(outResult.code, ErrorCodes.InvalidOptions); +assert.throwsWithCode(() => primary.getDB("test").foo.aggregate( + [{$out: "out"}], {readConcern: {level: "linearizable"}}), + ErrorCodes.InvalidOptions); // A $merge aggregation is not allowed with readConcern level "linearizable". -let mergeResult = - assert.throws(() => primary.getDB("test").foo.aggregate( - [{$merge: {into: "out", whenMatched: "replace", whenNotMatched: "insert"}}], - {readConcern: {level: "linearizable"}})); -assert.eq(mergeResult.code, ErrorCodes.InvalidOptions); +assert.throwsWithCode( + () => primary.getDB("test").foo.aggregate( + [{$merge: {into: "out", whenMatched: "replace", whenNotMatched: "insert"}}], + {readConcern: {level: "linearizable"}}), + ErrorCodes.InvalidOptions); primary = replTest.getPrimary(); diff --git a/jstests/sharding/change_streams/change_stream_on_system_collection.js b/jstests/sharding/change_streams/change_stream_on_system_collection.js index 08b6dab0de9..713e262f728 100644 --- a/jstests/sharding/change_streams/change_stream_on_system_collection.js +++ b/jstests/sharding/change_streams/change_stream_on_system_collection.js @@ -80,11 +80,11 @@ assert.commandWorked(db.t1.insert({_id: 2, a: 1})); // Verify that the system rejects a request to open a change stream on a system.* collection through // a mongos process even if parameter allowToRunOnSystemNS=true. -const changeStreamOpenError = assert.throws( +assert.throwsWithCode( () => systemCollection.watch([], {allowToRunOnSystemNS: true}), + ErrorCodes.InvalidNamespace, [], "expected a request with 'allowToRunOnSystemNS: true' to open a change stream on a system collection through mongos to fail"); -assert.eq(changeStreamOpenError.code, ErrorCodes.InvalidNamespace); const systemCollectionThroughShard = st.shard0.getCollection(systemCollection.getFullName()); diff --git a/jstests/sharding/check_sharding_index_versioned.js b/jstests/sharding/check_sharding_index_versioned.js index ae5eb461089..57e2ece67e5 100644 --- a/jstests/sharding/check_sharding_index_versioned.js +++ b/jstests/sharding/check_sharding_index_versioned.js @@ -17,14 +17,13 @@ assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {_id: 1}})); // // Note the shell connects to shards with a DBClient, which throws StaleConfig errors as JS // exceptions when the error does not come from a mongos. -const error = assert.throws(() => { +assert.throwsWithCode(() => { st.rs0.getPrimary().getDB(dbName).runCommand({ checkShardingIndex: ns, keyPattern: {x: 1}, shardVersion: [Timestamp(99, 10101), ObjectId()], }); -}); -assert.eq(error.code, ErrorCodes.StaleConfig); +}, ErrorCodes.StaleConfig); st.stop(); })(); diff --git a/jstests/sharding/query/graph_lookup.js b/jstests/sharding/query/graph_lookup.js index 90922f815a2..a51029fe2b0 100644 --- a/jstests/sharding/query/graph_lookup.js +++ b/jstests/sharding/query/graph_lookup.js @@ -34,7 +34,7 @@ res.forEach(function(c) { // Be sure $graphLookup is banned on sharded foreign collection. assert.commandWorked(st.s0.adminCommand({shardCollection: "test.baz", key: {_id: "hashed"}})); assert.commandWorked(db.baz.insert({_id: 1, x: 1})); -const err = assert.throws(() => db.foo.aggregate([{ +assert.throwsWithCode(() => db.foo.aggregate([{ $graphLookup: { from: "baz", startWith: {$literal: 1}, @@ -42,8 +42,7 @@ const err = assert.throws(() => db.foo.aggregate([{ connectToField: "_id", as: "res" } - }])); -assert.eq(28769, err.code); + }]), 28769); st.stop(); })(); diff --git a/jstests/sharding/query/lookup.js b/jstests/sharding/query/lookup.js index 8e2073bebd5..d749275185e 100644 --- a/jstests/sharding/query/lookup.js +++ b/jstests/sharding/query/lookup.js @@ -601,15 +601,15 @@ setParameterOnAllHosts(nodeList, "internalQueryAllowShardedLookup", false); // Re shard the foreign collection on _id. st.shardColl(mongosDB.from, {_id: 1}, {_id: 0}, {_id: 1}, mongosDB.getName()); -let err = assert.throws( +assert.throwsWithCode( () => sourceColl .aggregate([{ $lookup: {localField: "a", foreignField: "b", from: fromColl.getName(), as: "same"} }]) - .itcount()); -assert.eq(err.code, 28769); -err = assert.throws( + .itcount(), + 28769); +assert.throwsWithCode( () => sourceColl .aggregate( [{ @@ -617,9 +617,9 @@ err = assert.throws( {localField: "a", foreignField: "b", from: fromColl.getName(), as: "same"} }], {allowDiskUse: true}) - .itcount()); -assert.eq(err.code, 28769); -err = assert.throws(() => sourceColl + .itcount(), + 28769); +assert.throwsWithCode(() => sourceColl .aggregate( [ {$_internalSplitPipeline: {mergeType: "anyShard"}}, @@ -633,9 +633,8 @@ err = assert.throws(() => sourceColl } ], {allowDiskUse: true}) - .itcount()); -assert.eq(err.code, 28769); -err = assert.throws( + .itcount(), 28769); +assert.throwsWithCode( () => sourceColl .aggregate( [{$facet: { @@ -645,8 +644,7 @@ err = assert.throws( } }}], {allowDiskUse: true}) - .itcount()); -assert.eq(err.code, 40170); + .itcount(), 40170); st.stop(); }()); diff --git a/jstests/sharding/query/mrShardedOutput.js b/jstests/sharding/query/mrShardedOutput.js index 08aaa3a11ac..05abd736793 100644 --- a/jstests/sharding/query/mrShardedOutput.js +++ b/jstests/sharding/query/mrShardedOutput.js @@ -38,19 +38,19 @@ for (let i = 0; i < numDocs; ++i) { assert.commandWorked(bulk.execute()); // Should not be able to replace to a sharded collection. -let error = assert.throws( - () => inputColl.mapReduce(map, reduce, {out: {replace: outputColl.getName(), sharded: true}})); -assert.eq(error.code, ErrorCodes.InvalidOptions); +assert.throwsWithCode( + () => inputColl.mapReduce(map, reduce, {out: {replace: outputColl.getName(), sharded: true}}), + ErrorCodes.InvalidOptions); // Should fail if we specify "merge" or "reduce" with sharded: true and the collection does not yet // exist as sharded. -error = assert.throws( - () => inputColl.mapReduce(map, reduce, {out: {merge: outputColl.getName(), sharded: true}})); -assert.eq(error.code, ErrorCodes.InvalidOptions); +assert.throwsWithCode( + () => inputColl.mapReduce(map, reduce, {out: {merge: outputColl.getName(), sharded: true}}), + ErrorCodes.InvalidOptions); -error = assert.throws( - () => inputColl.mapReduce(map, reduce, {out: {reduce: outputColl.getName(), sharded: true}})); -assert.eq(error.code, ErrorCodes.InvalidOptions); +assert.throwsWithCode( + () => inputColl.mapReduce(map, reduce, {out: {reduce: outputColl.getName(), sharded: true}}), + ErrorCodes.InvalidOptions); // Now create and shard the output collection, again with one chunk on each shard. st.shardColl(outputColl, {_id: 1}, {_id: numDocs / 2}, {_id: numDocs / 2}); @@ -73,9 +73,9 @@ assert.eq(evenResult.value.count * 2, oddResult.value.count, [evenResult, oddRes // Should not be able to use replace mode if the collection exists and is sharded, even if the // 'sharded' option is not specified. -error = - assert.throws(() => inputColl.mapReduce(map, reduce, {out: {replace: outputColl.getName()}})); -assert.eq(error.code, ErrorCodes.IllegalOperation); +assert.throwsWithCode( + () => inputColl.mapReduce(map, reduce, {out: {replace: outputColl.getName()}}), + ErrorCodes.IllegalOperation); st.stop(); }()); diff --git a/jstests/sharding/query/out_fails_to_replace_sharded_collection.js b/jstests/sharding/query/out_fails_to_replace_sharded_collection.js index 0eef71b210a..619c8565d21 100644 --- a/jstests/sharding/query/out_fails_to_replace_sharded_collection.js +++ b/jstests/sharding/query/out_fails_to_replace_sharded_collection.js @@ -20,8 +20,7 @@ assertErrorCode(sourceColl, [{$out: targetColl.getName()}], 28769); // Test that the "legacy" mode will not succeed when outputting to a sharded collection, even // for explain. -let error = assert.throws(() => sourceColl.explain().aggregate([{$out: targetColl.getName()}])); -assert.eq(error.code, 28769); +assert.throwsWithCode(() => sourceColl.explain().aggregate([{$out: targetColl.getName()}]), 28769); // Then test that the $out fails if the collection becomes sharded between establishing the // cursor and performing the $out. @@ -32,8 +31,8 @@ const cursorResponse = assert.commandWorked(mongosDB.runCommand({ cursor: {batchSize: 0} })); st.shardColl(targetColl, {_id: 1}, false); -error = assert.throws(() => new DBCommandCursor(mongosDB, cursorResponse).itcount()); -assert.eq(error.code, ErrorCodes.IllegalOperation); +assert.throwsWithCode(() => new DBCommandCursor(mongosDB, cursorResponse).itcount(), + ErrorCodes.IllegalOperation); st.stop(); }()); diff --git a/jstests/sharding/query/view_on_shard_rewrite.js b/jstests/sharding/query/view_on_shard_rewrite.js index 9101d3f2e85..aebb0cda5c1 100644 --- a/jstests/sharding/query/view_on_shard_rewrite.js +++ b/jstests/sharding/query/view_on_shard_rewrite.js @@ -57,8 +57,8 @@ assertReadOnView(mongosDB.getCollection(viewName)); // View read with sharded collection on the primary shard is rejected. This mimics what happens // when mongos sends the equivalent read, with the caveat that mongos will use the view definition // returned to rewrite the query and execute against the underlying collection. -const result = assert.throws(() => shardDB.getCollection(viewName).findOne({})); -assert.eq(result.code, ErrorCodes.CommandOnShardedViewNotSupportedOnMongod); +assert.throwsWithCode(() => shardDB.getCollection(viewName).findOne({}), + ErrorCodes.CommandOnShardedViewNotSupportedOnMongod); st.stop(); })(); diff --git a/src/mongo/shell/assert.js b/src/mongo/shell/assert.js index e4d74097830..5e5ff7cdeca 100644 --- a/src/mongo/shell/assert.js +++ b/src/mongo/shell/assert.js @@ -580,6 +580,18 @@ assert = (function() { return error; }; + assert.throwsWithCode = function(func, code, params, msg) { + if (arguments.length < 2) { + throw new Error("assert.throwsWithCode expects at least 2 arguments"); + } + // Remove the 'code' parameter, and any undefined parameters, from the list of arguments. + // Use .apply() to preserve the length of the 'arguments' object. + const newArgs = [func, params, msg].filter(element => element !== undefined); + const error = assert.throws.apply(null, newArgs); + + assert.eq(error.code, code); + }; + assert.doesNotThrow = function(func, params, msg) { _validateAssertionMessage(msg); -- cgit v1.2.1