2013-08-01 20:05:21 -04:00
|
|
|
/**
|
|
|
|
|
* These tests verify that the oplog entries are created correctly for updates
|
|
|
|
|
*
|
|
|
|
|
* Do not add more tests here but instead add C++ unit tests in db/ops/modifier*_test files
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
var replTest = new ReplSetTest( { nodes: 1, oplogSize:2, nodeOptions: {smallfiles:""}} );
|
|
|
|
|
var nodes = replTest.startSet();
|
|
|
|
|
replTest.initiate();
|
2015-11-25 11:20:43 -05:00
|
|
|
var master = replTest.getPrimary();
|
2013-08-01 20:05:21 -04:00
|
|
|
var coll = master.getDB("o").fake;
|
|
|
|
|
var cdb = coll.getDB();
|
|
|
|
|
|
|
|
|
|
var assertLastOplog = function( o, o2 , msg) {
|
|
|
|
|
var last = master.getDB("local").oplog.rs.find().limit(1).sort({$natural:-1}).next();
|
|
|
|
|
|
|
|
|
|
assert.eq(last.ns, coll.getFullName(), "ns bad : " + msg);
|
|
|
|
|
assert.docEq(last.o, o, "o bad : " + msg);
|
|
|
|
|
if(o2)
|
|
|
|
|
assert.docEq(last.o2, o2, "o2 bad : " + msg);
|
|
|
|
|
return last.ts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set things up.
|
|
|
|
|
coll.save({_id:1});
|
|
|
|
|
assertLastOplog({_id:1}, null, "save -- setup ");
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The first ones are from the old updatetests which tested the internal impl using a modSet
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var msg = "IncRewriteExistingField: $inc $set"
|
|
|
|
|
coll.save({_id:1, a:2});
|
|
|
|
|
assertLastOplog({_id:1, a:2}, {_id:1}, "save " + msg);
|
2014-03-03 11:27:18 -05:00
|
|
|
var res = assert.writeOK(coll.update({}, { $inc: { a: 1 }, $set: { b: 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:3, b:2}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:3, b:2}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "IncRewriteNonExistingField: $inc $set"
|
|
|
|
|
coll.save({_id:1, c:0});
|
|
|
|
|
assertLastOplog({_id:1, c:0}, {_id:1}, "save " + msg);
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $inc: { a: 1 }, $set: { b: 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, c:0, a:1, b:2}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:1, b:2}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "TwoNestedPulls: two $pull"
|
|
|
|
|
coll.save({_id:1, a:{ b:[ 1, 2 ], c:[ 1, 2 ] }});
|
|
|
|
|
assertLastOplog({_id:1, a:{ b:[ 1, 2 ], c:[ 1, 2 ] }}, {_id:1}, "save " + msg);
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $pull: { 'a.b': 2, 'a.c': 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:{ b:[ 1 ], c:[ 1 ] }}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{'a.b':[1], 'a.c':[1]}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "MultiSets: two $set"
|
|
|
|
|
coll.save({_id:1, a:1, b:1});
|
|
|
|
|
assertLastOplog({_id:1, a:1, b:1}, {_id:1}, "save " + msg);
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $set: { a: 2, b: 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:2, b:2}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:2, b:2}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
// More tests to validate the oplog format and correct excution
|
|
|
|
|
|
|
|
|
|
var msg = "bad single $set"
|
|
|
|
|
coll.save({_id:1, a:1});
|
|
|
|
|
assertLastOplog({_id:1, a:1}, {_id:1}, "save " + msg);
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $set: { a: 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:2}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:2}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad single $inc";
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $inc: { a: 1 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:3}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:3}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad double $set";
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $set: { a: 2, b: 2 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:2, b:2}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a:2, b:2}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad save";
|
2014-03-03 11:27:18 -05:00
|
|
|
assert.writeOK(coll.save({ _id: 1, a: [2] }));
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:[2]}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({_id:1, a:[2]}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad array $inc";
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $inc: { "a.0": 1 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:[3]}, coll.findOne({}), msg);
|
|
|
|
|
var lastTS = assertLastOplog({$set:{"a.0": 3}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad $setOnInsert";
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $setOnInsert: { a: -1 }}));
|
|
|
|
|
assert.eq(res.nMatched, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:[3]}, coll.findOne({}), msg); // No-op
|
|
|
|
|
var otherTS = assertLastOplog({$set:{"a.0": 3}}, {_id:1}, msg); // Nothing new
|
|
|
|
|
assert.eq(lastTS, otherTS, "new oplog was not expected -- " + msg) // No new oplog entry
|
|
|
|
|
|
|
|
|
|
coll.remove({})
|
|
|
|
|
assert.eq(coll.count(), 0, "collection not empty")
|
|
|
|
|
|
|
|
|
|
var msg = "bad $setOnInsert w/upsert";
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $setOnInsert: { a: 200 }}, { upsert: true })); // upsert
|
|
|
|
|
assert.eq(res.nUpserted, 1, "update failed for '" + msg + "': " + res.toString());
|
|
|
|
|
var id = res.getUpsertedId()._id;
|
|
|
|
|
assert.docEq({_id: id, a: 200 }, coll.findOne({}), msg); // No-op
|
|
|
|
|
assertLastOplog({ _id: id, a: 200 }, null, msg); // No new oplog entry
|
2013-08-01 20:05:21 -04:00
|
|
|
|
|
|
|
|
coll.remove({})
|
|
|
|
|
assert.eq(coll.count(), 0, "collection not empty-2")
|
|
|
|
|
|
|
|
|
|
/* inconsistent oplog format with old code -- new is okay but less efficient
|
|
|
|
|
* enable once we switch the default
|
|
|
|
|
var msg = "bad array $push";
|
|
|
|
|
coll.save({_id:1, a:[1,2]})
|
|
|
|
|
coll.update({}, {$push:{a:3}});
|
|
|
|
|
var gle = cdb.getLastErrorObj();
|
|
|
|
|
assert.isnull(gle.err, msg);
|
|
|
|
|
assert.eq(gle.n, 1, "update failed for '" + msg +"': "+ tojson(gle));
|
|
|
|
|
assert.docEq({_id:1, a:[1,2,3]}, coll.findOne({}), msg);
|
|
|
|
|
//assertLastOplog({$set:{"a.2": 3}}, {_id:1}, msg); // old format
|
|
|
|
|
assertLastOplog({$set:{"a": [1,2,3]}}, {_id:1}, msg); // new format
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var msg = "bad array $push 2";
|
|
|
|
|
coll.save({_id:1, a:"foo"})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $push: { c: 18 }}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a:"foo", c:[18]}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{"c": [18]}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad array $push $slice";
|
|
|
|
|
coll.save({_id:1, a:{b:[18]}})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({ _id: { $gt: 0 }},
|
|
|
|
|
{ $push: { "a.b": { $each: [1, 2], $slice: -2 }}}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-01 20:05:21 -04:00
|
|
|
assert.docEq({_id:1, a: {b:[1,2]}}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{"a.b": [1,2]}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
var msg = "bad array $push $sort ($slice -100)";
|
2013-08-02 13:16:32 -04:00
|
|
|
coll.save({_id:1, a:{b:[{c:2}, {c:1}]}})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({}, { $push: { "a.b": { $each: [{ c: -1 }],
|
|
|
|
|
$sort: { c: 1 },
|
|
|
|
|
$slice: -100 }}}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-02 13:16:32 -04:00
|
|
|
assert.docEq({_id:1, a: {b:[{c:-1}, {c:1}, {c:2}]}}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{"a.b": [{c:-1},{c:1}, {c:2}]}}, {_id:1}, msg);
|
2013-08-01 20:05:21 -04:00
|
|
|
|
|
|
|
|
var msg = "bad array $push $slice $sort";
|
2013-08-02 13:16:32 -04:00
|
|
|
coll.save({_id:1, a:[{b:2}, {b:1}]})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({ _id: { $gt: 0 }}, { $push: { a: { $each: [{ b: -1 }],
|
|
|
|
|
$slice:-2,
|
|
|
|
|
$sort: { b: 1 }}}}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-02 13:16:32 -04:00
|
|
|
assert.docEq({_id:1, a: [{b:1}, {b:2}]}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{a: [{b:1},{b:2}]}}, {_id:1}, msg);
|
2013-08-01 20:05:21 -04:00
|
|
|
|
2013-08-02 13:16:32 -04:00
|
|
|
var msg = "bad array $push $slice $sort first two";
|
|
|
|
|
coll.save({_id:1, a:{b:[{c:2}, {c:1}]}})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({ _id: { $gt: 0 }}, { $push: { "a.b": { $each: [{ c: -1 }],
|
|
|
|
|
$slice: -2,
|
|
|
|
|
$sort: { c: 1 }}}}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-02 13:16:32 -04:00
|
|
|
assert.docEq({_id:1, a: {b:[{c:1}, {c:2}]}}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{"a.b": [{c:1},{c:2}]}}, {_id:1}, msg);
|
2013-08-01 20:05:21 -04:00
|
|
|
|
2013-08-02 13:16:32 -04:00
|
|
|
var msg = "bad array $push $slice $sort reversed first two";
|
|
|
|
|
coll.save({_id:1, a:{b:[{c:1}, {c:2}]}})
|
2014-03-03 11:27:18 -05:00
|
|
|
res = assert.writeOK(coll.update({ _id: { $gt: 0 }}, { $push: { "a.b": { $each: [{ c: -1 }],
|
|
|
|
|
$slice: -2,
|
|
|
|
|
$sort: { c: -1 }}}}));
|
|
|
|
|
assert.eq(res.nModified, 1, "update failed for '" + msg + "': " + res.toString());
|
2013-08-02 13:16:32 -04:00
|
|
|
assert.docEq({_id:1, a: {b:[{c:1}, {c:-1}]}}, coll.findOne({}), msg);
|
|
|
|
|
assertLastOplog({$set:{"a.b": [{c:1},{c:-1}]}}, {_id:1}, msg);
|
|
|
|
|
|
|
|
|
|
replTest.stopSet();
|