mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
SERVER-31335 cmd assertions check write errors
This commit is contained in:
parent
9d1f323a13
commit
5e28f4a352
@ -5,8 +5,8 @@
|
||||
|
||||
var authzErrorCode = 13;
|
||||
var hasAuthzError = function(result) {
|
||||
assert(result.hasWriteError());
|
||||
assert.eq(authzErrorCode, result.getWriteError().code);
|
||||
assert(result instanceof WriteCommandError);
|
||||
assert.eq(authzErrorCode, result.code);
|
||||
};
|
||||
|
||||
var st = new ShardingTest({
|
||||
@ -107,7 +107,7 @@ db3.auth('spencer', 'pwd');
|
||||
// s1/db2 should update its cache in 10 seconds.
|
||||
assert.soon(function() {
|
||||
var res = db2.foo.update({}, {$inc: {a: 1}});
|
||||
if (res.hasWriteError()) {
|
||||
if (res instanceof WriteCommandError) {
|
||||
return false;
|
||||
}
|
||||
return db2.foo.findOne().a == 3;
|
||||
@ -133,7 +133,7 @@ db3.auth('spencer', 'pwd');
|
||||
// s1/db2 should update its cache in 10 seconds.
|
||||
assert.soon(function() {
|
||||
var res = db2.foo.update({}, {$inc: {a: 1}});
|
||||
return res.hasWriteError() && res.getWriteError().code == authzErrorCode;
|
||||
return res instanceof WriteCommandError && res.code == authzErrorCode;
|
||||
}, "Mongos did not update its user cache after 10 seconds", 10 * 1000);
|
||||
|
||||
// We manually invalidate the cache on s1/db3.
|
||||
@ -155,7 +155,7 @@ db3.auth('spencer', 'pwd');
|
||||
|
||||
// s1/db2 should update its cache in 10 seconds.
|
||||
assert.soon(function() {
|
||||
return !db2.foo.update({}, {$inc: {a: 1}}).hasWriteError();
|
||||
return !(db2.foo.update({}, {$inc: {a: 1}}) instanceof WriteCommandError);
|
||||
}, "Mongos did not update its user cache after 10 seconds", 10 * 1000);
|
||||
|
||||
// We manually invalidate the cache on s1/db3.
|
||||
|
@ -6,8 +6,8 @@ function runAllRoleManagementCommandsTests(conn, writeConcern) {
|
||||
'use strict';
|
||||
|
||||
var hasAuthzError = function(result) {
|
||||
assert(result.hasWriteError());
|
||||
assert.eq(ErrorCodes.Unauthorized, result.getWriteError().code);
|
||||
assert(result instanceof WriteCommandError);
|
||||
assert.eq(ErrorCodes.Unauthorized, result.code);
|
||||
};
|
||||
|
||||
var userAdminConn = new Mongo(conn.host);
|
||||
|
@ -6,8 +6,8 @@
|
||||
function runTest(conn) {
|
||||
var authzErrorCode = 13;
|
||||
var hasAuthzError = function(result) {
|
||||
assert(result.hasWriteError());
|
||||
assert.eq(authzErrorCode, result.getWriteError().code);
|
||||
assert(result instanceof WriteCommandError);
|
||||
assert.eq(authzErrorCode, result.code);
|
||||
};
|
||||
|
||||
conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
|
||||
|
@ -6,8 +6,8 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
|
||||
'use strict';
|
||||
|
||||
var hasAuthzError = function(result) {
|
||||
assert(result.hasWriteError());
|
||||
assert.eq(ErrorCodes.Unauthorized, result.getWriteError().code);
|
||||
assert(result instanceof WriteCommandError);
|
||||
assert.eq(ErrorCodes.Unauthorized, result.code);
|
||||
};
|
||||
|
||||
conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']}, writeConcern);
|
||||
|
@ -166,7 +166,7 @@ request = {
|
||||
ordered: true
|
||||
};
|
||||
result = coll.runCommand(request);
|
||||
assert.commandWorked(result);
|
||||
assert.commandWorkedIgnoringWriteErrors(result);
|
||||
assert.eq(1, result.n);
|
||||
assert(result.writeErrors != null);
|
||||
assert.eq(1, result.writeErrors.length);
|
||||
@ -187,7 +187,7 @@ request = {
|
||||
ordered: false
|
||||
};
|
||||
result = coll.runCommand(request);
|
||||
assert.commandWorked(result);
|
||||
assert.commandWorkedIgnoringWriteErrors(result);
|
||||
assert.eq(1, result.n);
|
||||
assert.eq(2, result.writeErrors.length);
|
||||
|
||||
|
@ -8,7 +8,6 @@ var resultLower = dbLowerCase.c.insert({});
|
||||
assert.eq(1, resultLower.nInserted);
|
||||
|
||||
var resultUpper = dbUpperCase.c.insert({});
|
||||
assert.eq(0, resultUpper.nInserted);
|
||||
assert.writeError(resultUpper);
|
||||
assert.commandFailed(resultUpper);
|
||||
|
||||
assert.eq(-1, db.getMongo().getDBNames().indexOf("dbcase2test_dbnameA"));
|
||||
|
@ -296,7 +296,7 @@
|
||||
delete: coll.getName(),
|
||||
deletes: [{q: {_id: 0}, limit: 1}, {q: {$expr: "$$unbound"}, limit: 1}]
|
||||
});
|
||||
assert.commandWorked(writeRes);
|
||||
assert.commandWorkedIgnoringWriteErrors(writeRes);
|
||||
assert.eq(writeRes.writeErrors[0].code, 17276, tojson(writeRes));
|
||||
assert.eq(writeRes.n, 1, tojson(writeRes));
|
||||
|
||||
@ -344,7 +344,7 @@
|
||||
update: coll.getName(),
|
||||
updates: [{q: {_id: 0}, u: {$set: {b: 6}}}, {q: {$expr: "$$unbound"}, u: {$set: {b: 6}}}]
|
||||
});
|
||||
assert.commandWorked(writeRes);
|
||||
assert.commandWorkedIgnoringWriteErrors(writeRes);
|
||||
assert.eq(writeRes.writeErrors[0].code, 17276, tojson(writeRes));
|
||||
assert.eq(writeRes.n, 1, tojson(writeRes));
|
||||
})();
|
||||
|
@ -37,7 +37,7 @@ function assertSchemaMatch(coll, schema, doc, valid) {
|
||||
assert.writeOK(res, errmsg + " during insert document validation");
|
||||
} else {
|
||||
assert.writeErrorWithCode(res,
|
||||
ErrorCodes.DocumentFailedValidation,
|
||||
ErrorCodes.DocumentValidationFailure,
|
||||
errmsg + " during insert document validation");
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ function assertSchemaMatch(coll, schema, doc, valid) {
|
||||
assert.writeOK(res, errmsg + " during update document validation in strict mode");
|
||||
} else {
|
||||
assert.writeErrorWithCode(res,
|
||||
ErrorCodes.DocumentFailedValidation,
|
||||
ErrorCodes.DocumentValidationFailure,
|
||||
errmsg + " during update document validation in strict mode");
|
||||
}
|
||||
}
|
||||
|
254
jstests/noPassthrough/shell_cmd_assertions.js
Normal file
254
jstests/noPassthrough/shell_cmd_assertions.js
Normal file
@ -0,0 +1,254 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
const conn = MongoRunner.runMongod();
|
||||
const db = conn.getDB("commandAssertions");
|
||||
const kFakeErrCode = 1234567890;
|
||||
const tests = [];
|
||||
|
||||
function setup() {
|
||||
db.coll.drop();
|
||||
assert.writeOK(db.coll.insert({_id: 1}));
|
||||
}
|
||||
|
||||
// Raw command responses.
|
||||
tests.push(function rawCommandOk() {
|
||||
const res = db.runCommand({"ping": 1});
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function rawCommandErr() {
|
||||
const res = db.runCommand({"IHopeNobodyEverMakesThisACommand": 1});
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.throws(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.CommandNotFound));
|
||||
// commandFailedWithCode should succeed if any of the passed error codes are matched.
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.CommandNotFound, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function rawCommandWriteOk() {
|
||||
const res = db.runCommand({insert: "coll", documents: [{_id: 2}]});
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function rawCommandWriteErr() {
|
||||
const res = db.runCommand({insert: "coll", documents: [{_id: 1}]});
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function collInsertWriteOk() {
|
||||
const res = db.coll.insert({_id: 2});
|
||||
assert(res instanceof WriteResult);
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function collInsertWriteErr() {
|
||||
const res = db.coll.insert({_id: 1});
|
||||
assert(res instanceof WriteResult);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function collMultiInsertWriteOk() {
|
||||
const res = db.coll.insert([{_id: 3}, {_id: 2}]);
|
||||
assert(res instanceof BulkWriteResult);
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function collMultiInsertWriteErr() {
|
||||
const res = db.coll.insert([{_id: 1}, {_id: 2}]);
|
||||
assert(res instanceof BulkWriteResult);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
// Test when the insert command fails with ok:0 (i.e. not failing due to write err)
|
||||
tests.push(function collInsertCmdErr() {
|
||||
const res = db.coll.insert({x: 1}, {writeConcern: {"bad": 1}});
|
||||
assert(res instanceof WriteCommandError);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.throws(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.FailedToParse));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.FailedToParse, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function collMultiInsertCmdErr() {
|
||||
const res = db.coll.insert([{x: 1}, {x: 2}], {writeConcern: {"bad": 1}});
|
||||
assert(res instanceof WriteCommandError);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.throws(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.FailedToParse));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.FailedToParse, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function mapReduceOk() {
|
||||
const res = db.coll.mapReduce(
|
||||
function() {
|
||||
emit(this._id, 0);
|
||||
},
|
||||
function(k, v) {
|
||||
return v[0];
|
||||
},
|
||||
{out: "coll_out"});
|
||||
assert(res instanceof MapReduceResult);
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function mapReduceErr() {
|
||||
// db.coll.mapReduce throws if the command response has ok:0
|
||||
// Instead manually construct a MapReduceResult with ok:0
|
||||
const res = new MapReduceResult(db, {
|
||||
"ok": 0,
|
||||
"errmsg": "Example Error",
|
||||
"code": ErrorCodes.JSInterpreterFailure,
|
||||
"codeName": "JSInterpreterFailure"
|
||||
});
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.throws(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() =>
|
||||
assert.commandFailedWithCode(res, ErrorCodes.JSInterpreterFailure));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(
|
||||
res, [ErrorCodes.JSInterpreterFailure, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function errObject() {
|
||||
// Some functions throw an Error with a code property attached.
|
||||
let threw = false;
|
||||
let res = null;
|
||||
try {
|
||||
db.eval("this is a syntax error");
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
res = e;
|
||||
}
|
||||
assert(threw);
|
||||
assert(res instanceof Error);
|
||||
assert(res.hasOwnProperty("code"));
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.throws(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.InternalError));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.InternalError, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function crudInsertOneOk() {
|
||||
const res = db.coll.insertOne({_id: 2});
|
||||
assert(res.hasOwnProperty("acknowledged"));
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function crudInsertOneErr() {
|
||||
let threw = false;
|
||||
let res = null;
|
||||
try {
|
||||
db.coll.insertOne({_id: 1});
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
res = e;
|
||||
}
|
||||
assert(threw);
|
||||
assert(res instanceof WriteError);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function crudInsertManyOk() {
|
||||
const res = db.coll.insertMany([{_id: 2}, {_id: 3}]);
|
||||
assert(res.hasOwnProperty("acknowledged"));
|
||||
assert.doesNotThrow(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.throws(() => assert.commandFailed(res));
|
||||
assert.throws(() => assert.commandFailedWithCode(res, 0));
|
||||
});
|
||||
|
||||
tests.push(function crudInsertManyErr() {
|
||||
let threw = false;
|
||||
let res = null;
|
||||
try {
|
||||
db.coll.insertMany([{_id: 1}, {_id: 2}]);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
res = e;
|
||||
}
|
||||
assert(threw);
|
||||
assert(res instanceof BulkWriteError);
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function rawMultiWriteErr() {
|
||||
// Do an unordered bulk insert with duplicate keys to produce multiple write errors.
|
||||
const res =
|
||||
db.runCommand({"insert": "coll", documents: [{_id: 1}, {_id: 1}], ordered: false});
|
||||
assert(res.writeErrors.length == 2, "did not get multiple write errors");
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.push(function bulkMultiWriteErr() {
|
||||
// Do an unordered bulk insert with duplicate keys to produce multiple write errors.
|
||||
const res = db.coll.insert([{_id: 1}, {_id: 1}], {ordered: false});
|
||||
assert.throws(() => assert.commandWorked(res));
|
||||
assert.doesNotThrow(() => assert.commandWorkedIgnoringWriteErrors(res));
|
||||
assert.doesNotThrow(() => assert.commandFailed(res));
|
||||
assert.doesNotThrow(() => assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey));
|
||||
assert.doesNotThrow(
|
||||
() => assert.commandFailedWithCode(res, [ErrorCodes.DuplicateKey, kFakeErrCode]));
|
||||
});
|
||||
|
||||
tests.forEach((test) => {
|
||||
jsTest.log(`Starting test '${test.name}'`);
|
||||
setup();
|
||||
test();
|
||||
});
|
||||
})();
|
@ -14,4 +14,4 @@ assert(v.valid);
|
||||
|
||||
db.runCommand({applyOps: [{op: 'u', ns: 'a\0b'}]});
|
||||
var res = db["a\0a"].insert({});
|
||||
assert(res.hasWriteError(), "A write to collection a\0a succceeded");
|
||||
assert(res instanceof WriteCommandError, "A write to collection a\0a succceeded");
|
||||
|
@ -157,7 +157,7 @@ request = {
|
||||
writeConcern: {wtimeout: 1},
|
||||
ordered: false
|
||||
};
|
||||
result = assert.commandWorked(coll.runCommand(request));
|
||||
result = assert.commandWorkedIgnoringWriteErrors(coll.runCommand(request));
|
||||
assert.eq(1, result.n);
|
||||
assert.eq(result.writeErrors.length, 1);
|
||||
assert.eq(result.writeErrors[0].index, 1);
|
||||
|
@ -45,8 +45,8 @@
|
||||
|
||||
// Make sure that node 2 cannot write anything. Because it is lagged and replication
|
||||
// has been stopped, it shouldn't be able to become master.
|
||||
assert.writeErrorWithCode(nodes[2].getDB(name).bar.insert({z: 100}, writeConcern),
|
||||
ErrorCodes.NotMaster);
|
||||
assert.commandFailedWithCode(nodes[2].getDB(name).bar.insert({z: 100}, writeConcern),
|
||||
ErrorCodes.NotMaster);
|
||||
|
||||
// Confirm that the most up-to-date node becomes primary
|
||||
// after the default catchup delay.
|
||||
|
@ -190,7 +190,7 @@
|
||||
assert.writeOK(coll.insert({_id: 1}));
|
||||
},
|
||||
confirmFunc: function(res) {
|
||||
assert.commandWorked(res);
|
||||
assert.commandWorkedIgnoringWriteErrors(res);
|
||||
assert.eq(res.n, 0);
|
||||
assert.eq(res.writeErrors[0].code, ErrorCodes.DuplicateKey);
|
||||
assert.eq(coll.count({_id: 1}), 1);
|
||||
|
@ -77,12 +77,12 @@
|
||||
// Ensure dropping the `config.transactions` collection breaks the retryable writes feature, but
|
||||
// doesn't crash the server
|
||||
assert(config.transactions.drop());
|
||||
var res = assert.commandWorked(db.runCommand(cmdObj2));
|
||||
var res = assert.commandWorkedIgnoringWriteErrors(db.runCommand(cmdObj2));
|
||||
assert.eq(0, res.nModified);
|
||||
assert.eq(1, db.user.find({_id: 1}).toArray()[0].x);
|
||||
|
||||
assert(config.dropDatabase());
|
||||
res = assert.commandWorked(db.runCommand(cmdObj2));
|
||||
res = assert.commandWorkedIgnoringWriteErrors(db.runCommand(cmdObj2));
|
||||
assert.eq(0, res.nModified);
|
||||
assert.eq(1, db.user.find({_id: 1}).toArray()[0].x);
|
||||
|
||||
|
@ -61,7 +61,7 @@
|
||||
|
||||
jsTestLog("Ensure that writes start failing with NotMaster errors");
|
||||
assert.soonNoExcept(function() {
|
||||
assert.writeErrorWithCode(primary.getDB(name).foo.insert({x: 2}), ErrorCodes.NotMaster);
|
||||
assert.commandFailedWithCode(primary.getDB(name).foo.insert({x: 2}), ErrorCodes.NotMaster);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
|
||||
jsTestLog("Ensure that writes start failing with NotMaster errors");
|
||||
assert.soonNoExcept(function() {
|
||||
assert.writeErrorWithCode(primary.getDB(name).foo.insert({x: 2}), ErrorCodes.NotMaster);
|
||||
assert.commandFailedWithCode(primary.getDB(name).foo.insert({x: 2}), ErrorCodes.NotMaster);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -313,7 +313,7 @@
|
||||
lsid: lsid,
|
||||
txnNumber: NumberLong(1),
|
||||
};
|
||||
var res = assert.commandWorked(testDb.runCommand(cmd));
|
||||
var res = assert.commandWorkedIgnoringWriteErrors(testDb.runCommand(cmd));
|
||||
assert.eq(1,
|
||||
res.writeErrors.length,
|
||||
'expected only one write error, received: ' + tojson(res.writeErrors));
|
||||
@ -334,7 +334,7 @@
|
||||
lsid: lsid,
|
||||
txnNumber: NumberLong(1),
|
||||
};
|
||||
res = assert.commandWorked(testDb.runCommand(cmd));
|
||||
res = assert.commandWorkedIgnoringWriteErrors(testDb.runCommand(cmd));
|
||||
assert.eq(1,
|
||||
res.writeErrors.length,
|
||||
'expected only one write error, received: ' + tojson(res.writeErrors));
|
||||
|
@ -394,40 +394,244 @@ assert.doesNotThrow.automsg = function(func, params) {
|
||||
assert.doesNotThrow(func, params, func.toString());
|
||||
};
|
||||
|
||||
assert.commandWorked = function(res, msg) {
|
||||
if (assert._debug && msg)
|
||||
print("in assert for: " + msg);
|
||||
(function() {
|
||||
function _rawReplyOkAndNoWriteErrors(raw) {
|
||||
if (raw.ok === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (res.ok == 1)
|
||||
return res;
|
||||
doassert("command failed: " + tojson(res) + " : " + msg, res);
|
||||
};
|
||||
// A write command response may have ok:1 but write errors.
|
||||
if (raw.hasOwnProperty("writeErrors") && raw.writeErrors.length > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert.commandFailed = function(res, msg) {
|
||||
if (assert._debug && msg)
|
||||
print("in assert for: " + msg);
|
||||
|
||||
if (res.ok == 0)
|
||||
return res;
|
||||
doassert("command worked when it should have failed: " + tojson(res) + " : " + msg);
|
||||
};
|
||||
|
||||
assert.commandFailedWithCode = function(res, code, msg) {
|
||||
if (assert._debug && msg)
|
||||
print("in assert for: " + msg);
|
||||
|
||||
if (!Array.isArray(code)) {
|
||||
code = [code];
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(!res.ok,
|
||||
"Command result indicates success, but expected failure with code " + tojson(code) +
|
||||
": " + tojson(res) + " : " + msg);
|
||||
assert(code.indexOf(res.code) >= 0,
|
||||
"Expected failure code " + tojson(code) + " did not match actual in command result: " +
|
||||
tojson(res) + " : " + msg);
|
||||
return res;
|
||||
};
|
||||
// Returns whether res is a type which may have write errors (not command errors).
|
||||
// These types imply that the write command succeeded.
|
||||
function _isWriteResultType(res) {
|
||||
return res instanceof WriteResult || res instanceof WriteError ||
|
||||
res instanceof BulkWriteResult || res instanceof BulkWriteError;
|
||||
}
|
||||
|
||||
function _assertCommandWorked(res, msg, {ignoreWriteErrors}) {
|
||||
if (assert._debug && msg) {
|
||||
print("in assert for: " + msg);
|
||||
}
|
||||
|
||||
if (typeof res !== "object") {
|
||||
doassert("unknown response given to commandWorked");
|
||||
}
|
||||
|
||||
const failMsg = "command failed: " + tojson(res) + " : " + msg;
|
||||
|
||||
if (_isWriteResultType(res)) {
|
||||
// These can only contain write errors, not command errors.
|
||||
if (!ignoreWriteErrors) {
|
||||
assert.writeOK(res, msg);
|
||||
}
|
||||
} else if (res instanceof WriteCommandError || res instanceof Error) {
|
||||
// A WriteCommandError implies ok:0.
|
||||
// Error objects may have a `code` property added (e.g.
|
||||
// DBCollection.prototype.mapReduce) without a `ok` property.
|
||||
doassert(failMsg, res);
|
||||
} else if (res.hasOwnProperty("ok")) {
|
||||
// Handle raw command responses or cases like MapReduceResult which extend command
|
||||
// response.
|
||||
if (ignoreWriteErrors) {
|
||||
if (res.ok === 0) {
|
||||
doassert(failMsg, res);
|
||||
}
|
||||
} else {
|
||||
if (!_rawReplyOkAndNoWriteErrors(res)) {
|
||||
doassert(failMsg, res);
|
||||
}
|
||||
}
|
||||
} else if (res.hasOwnProperty("acknowledged")) {
|
||||
// CRUD api functions return plain js objects with an acknowledged property.
|
||||
// no-op.
|
||||
} else {
|
||||
doassert("unknown type of result, cannot check ok: " + tojson(res) + " : " + msg, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const kAnyErrorCode = Object.create(null);
|
||||
function _assertCommandFailed(res, expectedCode, msg) {
|
||||
if (assert._debug && msg) {
|
||||
print("in assert for: " + msg);
|
||||
}
|
||||
|
||||
if (typeof res !== "object") {
|
||||
doassert("unknown response given to commandFailed");
|
||||
}
|
||||
|
||||
if (expectedCode !== kAnyErrorCode && !Array.isArray(expectedCode)) {
|
||||
expectedCode = [expectedCode];
|
||||
}
|
||||
|
||||
const failMsg = "command worked when it should have failed: " + tojson(res) + " : " + msg;
|
||||
|
||||
const failCodeMsg = (expectedCode !== kAnyErrorCode)
|
||||
? "command did not fail with any of the following codes " + tojson(expectedCode) + " " +
|
||||
tojson(res) + " : " + msg
|
||||
: "";
|
||||
|
||||
if (_isWriteResultType(res)) {
|
||||
// These can only contain write errors, not command errors.
|
||||
assert.writeErrorWithCode(res, expectedCode, msg);
|
||||
} else if (res instanceof WriteCommandError || res instanceof Error) {
|
||||
// A WriteCommandError implies ok:0.
|
||||
// Error objects may have a `code` property added (e.g.
|
||||
// DBCollection.prototype.mapReduce) without a `ok` property.
|
||||
if (expectedCode !== kAnyErrorCode) {
|
||||
if (!res.hasOwnProperty("code") || !expectedCode.includes(res.code)) {
|
||||
doassert(failCodeMsg, res);
|
||||
}
|
||||
}
|
||||
} else if (res.hasOwnProperty("ok")) {
|
||||
// Handle raw command responses or cases like MapReduceResult which extend command
|
||||
// response.
|
||||
if (_rawReplyOkAndNoWriteErrors(res)) {
|
||||
doassert(failMsg, res);
|
||||
}
|
||||
if (expectedCode !== kAnyErrorCode) {
|
||||
let foundCode = false;
|
||||
if (res.hasOwnProperty("code") && expectedCode.includes(res.code)) {
|
||||
foundCode = true;
|
||||
} else if (res.hasOwnProperty("writeErrors")) {
|
||||
foundCode = res.writeErrors.some((err) => expectedCode.includes(err.code));
|
||||
}
|
||||
if (!foundCode) {
|
||||
doassert(failCodeMsg, res);
|
||||
}
|
||||
}
|
||||
} else if (res.hasOwnProperty("acknowledged")) {
|
||||
// CRUD api functions return plain js objects with an acknowledged property.
|
||||
doassert(failMsg);
|
||||
} else {
|
||||
doassert("unknown type of result, cannot check error: " + tojson(res) + " : " + msg,
|
||||
res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
assert.commandWorked = function(res, msg) {
|
||||
return _assertCommandWorked(res, msg, {ignoreWriteErrors: false});
|
||||
};
|
||||
|
||||
assert.commandWorkedIgnoringWriteErrors = function(res, msg) {
|
||||
return _assertCommandWorked(res, msg, {ignoreWriteErrors: true});
|
||||
};
|
||||
|
||||
assert.commandFailed = function(res, msg) {
|
||||
return _assertCommandFailed(res, kAnyErrorCode, msg);
|
||||
};
|
||||
|
||||
// expectedCode can be an array of possible codes.
|
||||
assert.commandFailedWithCode = function(res, expectedCode, msg) {
|
||||
return _assertCommandFailed(res, expectedCode, msg);
|
||||
};
|
||||
|
||||
assert.writeOK = function(res, msg) {
|
||||
|
||||
var errMsg = null;
|
||||
|
||||
if (res instanceof WriteResult) {
|
||||
if (res.hasWriteError()) {
|
||||
errMsg = "write failed with error: " + tojson(res);
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
errMsg = "write concern failed with errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof BulkWriteResult) {
|
||||
// Can only happen with bulk inserts
|
||||
if (res.hasWriteErrors()) {
|
||||
errMsg = "write failed with errors: " + tojson(res);
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
errMsg = "write concern failed with errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof WriteCommandError || res instanceof WriteError ||
|
||||
res instanceof BulkWriteError) {
|
||||
errMsg = "write command failed: " + tojson(res);
|
||||
} else {
|
||||
if (!res || !res.ok) {
|
||||
errMsg = "unknown type of write result, cannot check ok: " + tojson(res);
|
||||
}
|
||||
}
|
||||
|
||||
if (errMsg) {
|
||||
if (msg)
|
||||
errMsg = errMsg + ": " + msg;
|
||||
doassert(errMsg, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
assert.writeError = function(res, msg) {
|
||||
return assert.writeErrorWithCode(res, kAnyErrorCode, msg);
|
||||
};
|
||||
|
||||
// If expectedCode is an array then this asserts that the found code is one of the codes in
|
||||
// the expectedCode array.
|
||||
assert.writeErrorWithCode = function(res, expectedCode, msg) {
|
||||
if (expectedCode === undefined) {
|
||||
doassert("assert.writeErrorWithCode called with undefined error code");
|
||||
}
|
||||
|
||||
var errMsg = null;
|
||||
var writeErrorCodes = new Set();
|
||||
|
||||
if (res instanceof WriteResult) {
|
||||
if (res.hasWriteError()) {
|
||||
writeErrorCodes.add(res.getWriteError().code);
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
writeErrorCodes.add(res.getWriteConcernError().code);
|
||||
} else {
|
||||
errMsg = "no write error: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof BulkWriteResult || res instanceof BulkWriteError) {
|
||||
// Can only happen with bulk inserts
|
||||
if (res.hasWriteErrors()) {
|
||||
// Save every write error code.
|
||||
res.getWriteErrors().forEach((we) => writeErrorCodes.add(we.code));
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
writeErrorCodes.add(res.getWriteConcernError().code);
|
||||
} else {
|
||||
errMsg = "no write errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof WriteCommandError) {
|
||||
// Can only happen with bulk inserts
|
||||
// No-op since we're expecting an error
|
||||
} else if (res instanceof WriteError) {
|
||||
writeErrorCodes.add(res.code);
|
||||
} else {
|
||||
if (!res || res.ok) {
|
||||
errMsg = "unknown type of write result, cannot check error: " + tojson(res);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errMsg && expectedCode !== kAnyErrorCode) {
|
||||
if (!Array.isArray(expectedCode)) {
|
||||
expectedCode = [expectedCode];
|
||||
}
|
||||
const found = expectedCode.some((ec) => writeErrorCodes.has(ec));
|
||||
if (!found) {
|
||||
errMsg = "found code(s) " + tojson(Array.from(writeErrorCodes)) +
|
||||
" does not match any of the expected codes " + tojson(expectedCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (errMsg) {
|
||||
if (msg)
|
||||
errMsg = errMsg + ": " + msg;
|
||||
doassert(errMsg);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
})();
|
||||
|
||||
assert.isnull = function(what, msg) {
|
||||
if (assert._debug && msg)
|
||||
@ -532,102 +736,6 @@ assert.closeWithinMS = function(a, b, msg, deltaMS) {
|
||||
actualDelta + " millis : " + msg);
|
||||
};
|
||||
|
||||
assert.writeOK = function(res, msg) {
|
||||
|
||||
var errMsg = null;
|
||||
|
||||
if (res instanceof WriteResult) {
|
||||
if (res.hasWriteError()) {
|
||||
errMsg = "write failed with error: " + tojson(res);
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
errMsg = "write concern failed with errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof BulkWriteResult) {
|
||||
// Can only happen with bulk inserts
|
||||
if (res.hasWriteErrors()) {
|
||||
errMsg = "write failed with errors: " + tojson(res);
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
errMsg = "write concern failed with errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof WriteCommandError) {
|
||||
// Can only happen with bulk inserts
|
||||
errMsg = "write command failed: " + tojson(res);
|
||||
} else {
|
||||
if (!res || !res.ok) {
|
||||
errMsg = "unknown type of write result, cannot check ok: " + tojson(res);
|
||||
}
|
||||
}
|
||||
|
||||
if (errMsg) {
|
||||
if (msg)
|
||||
errMsg = errMsg + ": " + msg;
|
||||
doassert(errMsg, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
assert.writeError = function(res, msg) {
|
||||
return assert.writeErrorWithCode(res, null, msg);
|
||||
};
|
||||
|
||||
// If expectedCode is an array then this asserts that the found code is one of the codes in
|
||||
// the expectedCode array.
|
||||
assert.writeErrorWithCode = function(res, expectedCode, msg) {
|
||||
|
||||
var errMsg = null;
|
||||
var foundCode = null;
|
||||
|
||||
if (res instanceof WriteResult) {
|
||||
if (res.hasWriteError()) {
|
||||
foundCode = res.getWriteError().code;
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
foundCode = res.getWriteConcernError().code;
|
||||
} else {
|
||||
errMsg = "no write error: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof BulkWriteResult) {
|
||||
// Can only happen with bulk inserts
|
||||
if (res.hasWriteErrors()) {
|
||||
if (res.getWriteErrorCount() > 1 && expectedCode != null) {
|
||||
errMsg = "can't check for specific code when there was more than one write error";
|
||||
} else {
|
||||
foundCode = res.getWriteErrorAt(0).code;
|
||||
}
|
||||
} else if (res.hasWriteConcernError()) {
|
||||
foundCode = res.getWriteConcernError().code;
|
||||
} else {
|
||||
errMsg = "no write errors: " + tojson(res);
|
||||
}
|
||||
} else if (res instanceof WriteCommandError) {
|
||||
// Can only happen with bulk inserts
|
||||
// No-op since we're expecting an error
|
||||
} else {
|
||||
if (!res || res.ok) {
|
||||
errMsg = "unknown type of write result, cannot check error: " + tojson(res);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errMsg && expectedCode) {
|
||||
if (Array.isArray(expectedCode)) {
|
||||
if (!expectedCode.includes(foundCode)) {
|
||||
errMsg = "found code " + foundCode + " does not match any of the expected codes " +
|
||||
tojson(expectedCode);
|
||||
}
|
||||
} else if (foundCode != expectedCode) {
|
||||
errMsg = "found code " + foundCode + " does not match expected code " + expectedCode;
|
||||
}
|
||||
}
|
||||
|
||||
if (errMsg) {
|
||||
if (msg)
|
||||
errMsg = errMsg + ": " + msg;
|
||||
doassert(errMsg);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
assert.gleOK = function(res, msg) {
|
||||
|
||||
var errMsg = null;
|
||||
|
@ -419,14 +419,6 @@ var _bulk_api_module = (function() {
|
||||
this.shellPrint = function() {
|
||||
return this.toString();
|
||||
};
|
||||
|
||||
this.toSingleResult = function() {
|
||||
// This is *only* safe to do with a WriteCommandError from the bulk api when the bulk is
|
||||
// known to be of size == 1
|
||||
var bulkResult = getEmptyBulkResult();
|
||||
bulkResult.writeErrors.push({code: this.code, index: 0, errmsg: this.errmsg});
|
||||
return new BulkWriteResult(bulkResult, NONE).toSingleResult();
|
||||
};
|
||||
};
|
||||
|
||||
WriteCommandError.prototype = Object.create(Error.prototype);
|
||||
@ -1210,6 +1202,7 @@ var _bulk_api_module = (function() {
|
||||
module.BulkWriteResult = BulkWriteResult;
|
||||
module.BulkWriteError = BulkWriteError;
|
||||
module.WriteCommandError = WriteCommandError;
|
||||
module.WriteError = WriteError;
|
||||
module.initializeUnorderedBulkOp = function() {
|
||||
return new Bulk(this, false);
|
||||
};
|
||||
@ -1227,6 +1220,7 @@ WriteResult = _bulk_api_module.WriteResult;
|
||||
BulkWriteResult = _bulk_api_module.BulkWriteResult;
|
||||
BulkWriteError = _bulk_api_module.BulkWriteError;
|
||||
WriteCommandError = _bulk_api_module.WriteCommandError;
|
||||
WriteError = _bulk_api_module.WriteError;
|
||||
|
||||
/***********************************************************
|
||||
* Adds the initializers of bulk operations to the db collection
|
||||
|
@ -261,6 +261,9 @@ DBCollection.prototype.findOne = function(query, fields, options, readConcern, c
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Returns a WriteResult for a single insert or a BulkWriteResult for a multi-insert if write
|
||||
// command succeeded, but may contain write errors.
|
||||
// Returns a WriteCommandError if the write command responded with ok:0.
|
||||
DBCollection.prototype.insert = function(obj, options) {
|
||||
if (!obj)
|
||||
throw Error("no object passed to insert!");
|
||||
@ -317,7 +320,7 @@ DBCollection.prototype.insert = function(obj, options) {
|
||||
if (ex instanceof BulkWriteError) {
|
||||
result = isMultiInsert ? ex.toResult() : ex.toSingleResult();
|
||||
} else if (ex instanceof WriteCommandError) {
|
||||
result = isMultiInsert ? ex : ex.toSingleResult();
|
||||
result = ex;
|
||||
} else {
|
||||
// Other exceptions rethrown as-is.
|
||||
throw ex;
|
||||
@ -374,6 +377,8 @@ DBCollection.prototype._parseRemove = function(t, justOne) {
|
||||
return {"query": query, "justOne": justOne, "wc": wc, "collation": collation};
|
||||
};
|
||||
|
||||
// Returns a WriteResult if write command succeeded, but may contain write errors.
|
||||
// Returns a WriteCommandError if the write command responded with ok:0.
|
||||
DBCollection.prototype.remove = function(t, justOne) {
|
||||
var parsed = this._parseRemove(t, justOne);
|
||||
var query = parsed.query;
|
||||
@ -402,8 +407,10 @@ DBCollection.prototype.remove = function(t, justOne) {
|
||||
try {
|
||||
result = bulk.execute(wc).toSingleResult();
|
||||
} catch (ex) {
|
||||
if (ex instanceof BulkWriteError || ex instanceof WriteCommandError) {
|
||||
if (ex instanceof BulkWriteError) {
|
||||
result = ex.toSingleResult();
|
||||
} else if (ex instanceof WriteCommandError) {
|
||||
result = ex;
|
||||
} else {
|
||||
// Other exceptions thrown
|
||||
throw Error(ex);
|
||||
@ -475,6 +482,8 @@ DBCollection.prototype._parseUpdate = function(query, obj, upsert, multi) {
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a WriteResult if write command succeeded, but may contain write errors.
|
||||
// Returns a WriteCommandError if the write command responded with ok:0.
|
||||
DBCollection.prototype.update = function(query, obj, upsert, multi) {
|
||||
var parsed = this._parseUpdate(query, obj, upsert, multi);
|
||||
var query = parsed.query;
|
||||
@ -514,8 +523,10 @@ DBCollection.prototype.update = function(query, obj, upsert, multi) {
|
||||
try {
|
||||
result = bulk.execute(wc).toSingleResult();
|
||||
} catch (ex) {
|
||||
if (ex instanceof BulkWriteError || ex instanceof WriteCommandError) {
|
||||
if (ex instanceof BulkWriteError) {
|
||||
result = ex.toSingleResult();
|
||||
} else if (ex instanceof WriteCommandError) {
|
||||
result = ex;
|
||||
} else {
|
||||
// Other exceptions thrown
|
||||
throw Error(ex);
|
||||
|
Loading…
Reference in New Issue
Block a user