Files
mongo/jstests/core/apply_ops1.js

278 lines
11 KiB
JavaScript

(function() {
"use strict";
var t = db.apply_ops1;
t.drop();
//
// Input validation tests
//
// Empty array of operations.
assert.commandWorked(db.adminCommand({applyOps: []}),
'applyOps should not fail on empty array of operations');
// Non-array type for operations.
assert.commandFailed(db.adminCommand({applyOps: "not an array"}),
'applyOps should fail on non-array type for operations');
// Missing 'op' field in an operation.
assert.commandFailed(db.adminCommand({applyOps: [{ns: t.getFullName()}]}),
'applyOps should fail on operation without "op" field');
// Non-string 'op' field in an operation.
assert.commandFailed(db.adminCommand({applyOps: [{op: 12345, ns: t.getFullName()}]}),
'applyOps should fail on operation with non-string "op" field');
// Empty 'op' field value in an operation.
assert.commandFailed(db.adminCommand({applyOps: [{op: '', ns: t.getFullName()}]}),
'applyOps should fail on operation with empty "op" field value');
// Missing 'ns' field in an operation.
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c'}]}),
'applyOps should fail on operation without "ns" field');
// Non-string 'ns' field in an operation.
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c', ns: 12345}]}),
'applyOps should fail on operation with non-string "ns" field');
// Empty 'ns' field value in an operation of type 'n' (noop).
assert.commandWorked(db.adminCommand({applyOps: [{op: 'n', ns: ''}]}),
'applyOps should work on no op operation with empty "ns" field value');
// Missing dbname in 'ns' field.
assert.commandFailed(db.adminCommand({applyOps: [{op: 'd', ns: t.getName(), o: {_id: 1}}]}));
// Missing 'o' field value in an operation of type 'c' (command).
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c', ns: t.getFullName()}]}),
'applyOps should fail on command operation without "o" field');
// Non-object 'o' field value in an operation of type 'c' (command).
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c', ns: t.getFullName(), o: 'bar'}]}),
'applyOps should fail on command operation with non-object "o" field');
// Empty object 'o' field value in an operation of type 'c' (command).
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c', ns: t.getFullName(), o: {}}]}),
'applyOps should fail on command operation with empty object "o" field');
// Unknown key in 'o' field value in an operation of type 'c' (command).
assert.commandFailed(db.adminCommand({applyOps: [{op: 'c', ns: t.getFullName(), o: {a: 1}}]}),
'applyOps should fail on command operation on unknown key in "o" field');
// Empty 'ns' field value in operation type other than 'n'.
assert.commandFailed(
db.adminCommand({applyOps: [{op: 'c', ns: ''}]}),
'applyOps should fail on non-"n" operation type with empty "ns" field value');
// Missing 'o' field value in an operation of type 'i' on 'system.indexes' collection.
assert.commandFailedWithCode(
db.adminCommand({applyOps: [{op: 'i', ns: db.getName() + '.system.indexes'}]}),
ErrorCodes.NoSuchKey,
'applyOps should fail on system.indexes insert operation without "o" field');
// Non-object 'o' field value in an operation of type 'i' on 'system.indexes' collection.
assert.commandFailedWithCode(
db.adminCommand({applyOps: [{op: 'i', ns: db.getName() + '.system.indexes', o: 'bar'}]}),
ErrorCodes.TypeMismatch,
'applyOps should fail on system.indexes insert operation with non-object "o" field');
// Missing 'ns' field in index spec.
assert.commandFailedWithCode(
db.adminCommand({
applyOps: [{
op: 'i',
ns: db.getName() + '.system.indexes',
o: {
key: {a: 1},
name: 'a_1',
}
}]
}),
ErrorCodes.NoSuchKey,
'applyOps should fail on system.indexes insert operation with missing index namespace');
// Non-string 'ns' field in index spec.
assert.commandFailedWithCode(
db.adminCommand({
applyOps: [{
op: 'i',
ns: db.getName() + '.system.indexes',
o: {
ns: 12345,
key: {a: 1},
name: 'a_1',
}
}]
}),
ErrorCodes.TypeMismatch,
'applyOps should fail on system.indexes insert operation with non-string index namespace');
// Invalid 'ns' field in index spec.
assert.commandFailedWithCode(
db.adminCommand({
applyOps: [{
op: 'i',
ns: db.getName() + '.system.indexes',
o: {
ns: 'invalid_namespace',
key: {a: 1},
name: 'a_1',
}
}]
}),
ErrorCodes.InvalidNamespace,
'applyOps should fail on system.indexes insert operation with invalid index namespace');
// Inconsistent database name in index spec namespace.
assert.commandFailedWithCode(
db.adminCommand({
applyOps: [{
op: 'i',
ns: db.getName() + '.system.indexes',
o: {
ns: 'baddbprefix' + t.getFullName(),
key: {a: 1},
name: 'a_1',
}
}]
}),
ErrorCodes.InvalidNamespace,
'applyOps should fail on system.indexes insert operation with index namespace containing ' +
'inconsistent database name');
// Valid 'ns' field value in unknown operation type 'x'.
assert.commandFailed(
db.adminCommand({applyOps: [{op: 'x', ns: t.getFullName()}]}),
'applyOps should fail on unknown operation type "x" with valid "ns" value');
assert.eq(0, t.find().count(), "Non-zero amount of documents in collection to start");
assert.commandFailed(
db.adminCommand({applyOps: [{"op": "i", "ns": t.getFullName(), "o": {_id: 5, x: 17}}]}),
"Applying an insert operation on a non-existent collection should fail");
assert.commandWorked(db.createCollection(t.getName()));
var a = db.adminCommand({applyOps: [{"op": "i", "ns": t.getFullName(), "o": {_id: 5, x: 17}}]});
assert.eq(1, t.find().count(), "Valid insert failed");
assert.eq(true, a.results[0], "Bad result value for valid insert");
a = assert.commandWorked(
db.adminCommand({applyOps: [{"op": "i", "ns": t.getFullName(), "o": {_id: 5, x: 17}}]}));
assert.eq(1, t.find().count(), "Duplicate insert failed");
assert.eq(true, a.results[0], "Bad result value for duplicate insert");
var o = {_id: 5, x: 17};
assert.eq(o, t.findOne(), "Mismatching document inserted.");
// 'o' field is an empty array.
assert.commandFailed(db.adminCommand({applyOps: [{op: 'i', ns: t.getFullName(), o: []}]}),
'applyOps should fail on insert of object with empty array element');
var res = db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}}
]
});
o.x++;
o.x++;
assert.eq(1, t.find().count(), "Updates increased number of documents");
assert.eq(o, t.findOne(), "Document doesn't match expected");
assert.eq(true, res.results[0], "Bad result value for valid update");
assert.eq(true, res.results[1], "Bad result value for valid update");
// preCondition fully matches
res = db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}}
],
preCondition: [{ns: t.getFullName(), q: {_id: 5}, res: {x: 19}}]
});
o.x++;
o.x++;
assert.eq(1, t.find().count(), "Updates increased number of documents");
assert.eq(o, t.findOne(), "Document doesn't match expected");
assert.eq(true, res.results[0], "Bad result value for valid update");
assert.eq(true, res.results[1], "Bad result value for valid update");
// preCondition doesn't match ns
res = db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}}
],
preCondition: [{ns: "foo.otherName", q: {_id: 5}, res: {x: 21}}]
});
assert.eq(o, t.findOne(), "preCondition didn't match, but ops were still applied");
// preCondition doesn't match query
res = db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}}
],
preCondition: [{ns: t.getFullName(), q: {_id: 5}, res: {x: 19}}]
});
assert.eq(o, t.findOne(), "preCondition didn't match, but ops were still applied");
res = db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 6}, o: {$inc: {x: 1}}}
]
});
assert.eq(true, res.results[0], "Valid update failed");
assert.eq(true, res.results[1], "Valid update failed");
// Foreground index build.
res = assert.commandWorked(db.adminCommand({
applyOps: [{
"op": "i",
"ns": db.getName() + ".system.indexes",
"o": {
ns: t.getFullName(),
key: {a: 1},
name: "a_1",
}
}]
}));
assert.eq(1, res.applied, "Incorrect number of operations applied");
assert.eq(true, res.results[0], "Foreground index creation failed");
res = t.getIndexes();
assert.eq(1,
res.filter(function(element, index, array) {
return element.name == 'a_1';
})
.length,
'Foreground index not found in listIndexes result: ' + tojson(res));
// Background indexes are created in the foreground when processed by applyOps.
res = assert.commandWorked(db.adminCommand({
applyOps: [{
"op": "i",
"ns": db.getName() + ".system.indexes",
"o": {
ns: t.getFullName(),
key: {b: 1},
name: "b_1",
background: true,
}
}]
}));
assert.eq(1, res.applied, "Incorrect number of operations applied");
assert.eq(true, res.results[0], "Background index creation failed");
res = t.getIndexes();
assert.eq(1,
res.filter(function(element, index, array) {
return element.name == 'b_1';
})
.length,
'Background index not found in listIndexes result: ' + tojson(res));
})();