diff options
author | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-01-26 17:27:33 -0500 |
---|---|---|
committer | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-01-26 17:27:33 -0500 |
commit | c36c82ed483ffcd1087260e4a125c625a2026ed1 (patch) | |
tree | e07fcad183fb2bbe7885107779de027c9a3cc38a | |
parent | b342e083fb54e9f34ca2123db900c3ef43056ddc (diff) | |
download | mongo-c36c82ed483ffcd1087260e4a125c625a2026ed1.tar.gz |
SERVER-21499 Update FSM workloads to handle more frequent yielding.
When running different FSM workloads simultaneously, it is possible for
failpoints or configured server parameters to cause a workload to
experience conditions that would normally only occur under high load.
4 files changed, 50 insertions, 12 deletions
diff --git a/jstests/concurrency/fsm_workloads/update_array.js b/jstests/concurrency/fsm_workloads/update_array.js index fe741090dd6..b2681fb792a 100644 --- a/jstests/concurrency/fsm_workloads/update_array.js +++ b/jstests/concurrency/fsm_workloads/update_array.js @@ -49,9 +49,15 @@ var $config = (function() { assertWhenOwnColl.neq(null, doc); assertWhenOwnColl(doc.hasOwnProperty('arr'), 'doc should have contained a field named "arr": ' + tojson(doc)); - assertWhenOwnColl.contains(value, doc.arr, - "doc.arr doesn't contain value (" + value + - ') after $push: ' + tojson(doc.arr)); + + // If the document was invalidated during a yield, then we may not have updated + // anything. The $push operator always modifies the matched document, so if we + // matched something, then we must have updated it. + if (res.nMatched > 0) { + assertWhenOwnColl.contains(value, doc.arr, + "doc.arr doesn't contain value (" + value + + ') after $push: ' + tojson(doc.arr)); + } }); } @@ -65,9 +71,16 @@ var $config = (function() { var doc = db[collName].findOne({ _id: docIndex }); assertWhenOwnColl(function() { assertWhenOwnColl.neq(null, doc); - assertWhenOwnColl.eq(-1, doc.arr.indexOf(value), - 'doc.arr contains removed value (' + value + - ') after $pull: ' + tojson(doc.arr)); + + // If the document was invalidated during a yield, then we may not have updated + // anything. If the update matched a document, then the $pull operator would have + // removed all occurrences of 'value' from the array (meaning that there should be + // none left). + if (res.nMatched > 0) { + assertWhenOwnColl.eq(-1, doc.arr.indexOf(value), + 'doc.arr contains removed value (' + value + + ') after $pull: ' + tojson(doc.arr)); + } }); } diff --git a/jstests/concurrency/fsm_workloads/update_inc.js b/jstests/concurrency/fsm_workloads/update_inc.js index 32dca107456..adc1c536fdd 100644 --- a/jstests/concurrency/fsm_workloads/update_inc.js +++ b/jstests/concurrency/fsm_workloads/update_inc.js @@ -49,16 +49,23 @@ var $config = (function() { } } - ++this.count; + // The $inc operator always modifies the matched document, so if we matched something, + // then we must have updated it. + this.count += (res.nMatched >= 1); }, find: function find(db, collName) { var docs = db[collName].find().toArray(); assertWhenOwnColl.eq(1, docs.length); - assertWhenOwnColl((function() { + assertWhenOwnColl(() => { + // If the document hasn't been updated at all, then the field won't exist. var doc = docs[0]; - assertWhenOwnColl.eq(this.count, doc[this.fieldName]); - }).bind(this)); + if (doc.hasOwnProperty(this.fieldName)) { + assertWhenOwnColl.eq(this.count, doc[this.fieldName]); + } else { + assertWhenOwnColl.eq(this.count, 0); + } + }); } }; diff --git a/jstests/concurrency/fsm_workloads/update_ordered_bulk_inc.js b/jstests/concurrency/fsm_workloads/update_ordered_bulk_inc.js index 9bd36519229..93911a4a44f 100644 --- a/jstests/concurrency/fsm_workloads/update_ordered_bulk_inc.js +++ b/jstests/concurrency/fsm_workloads/update_ordered_bulk_inc.js @@ -54,7 +54,10 @@ var $config = (function() { } docs.forEach(function(doc) { - assertWhenOwnColl.lte(doc[this.fieldName], this.count); + // If the document hasn't been updated at all, then the field won't exist. + if (doc.hasOwnProperty(this.fieldName)) { + assertWhenOwnColl.lte(doc[this.fieldName], this.count); + } assertWhenOwnColl.lt(doc._id, this.docCount); }, this); } diff --git a/jstests/concurrency/fsm_workloads/update_replace.js b/jstests/concurrency/fsm_workloads/update_replace.js index 9776d6f31da..bc183d01fbb 100644 --- a/jstests/concurrency/fsm_workloads/update_replace.js +++ b/jstests/concurrency/fsm_workloads/update_replace.js @@ -6,14 +6,29 @@ * Does updates that replace an entire document. * The collection has indexes on some but not all fields. */ +load('jstests/concurrency/fsm_workload_helpers/server_types.js'); // for isMongod and isMMAPv1 + var $config = (function() { // explicitly pass db to avoid accidentally using the global `db` function assertResult(db, res) { assertAlways.eq(0, res.nUpserted, tojson(res)); - assertWhenOwnColl.eq(1, res.nMatched, tojson(res)); + + if (isMongod(db) && !isMMAPv1(db)) { + // For non-MMAPv1 storage engines we can make a stong assertion that exactly one + // document was matched. + assertWhenOwnColl.eq(res.nMatched, 1, tojson(res)); + } else { + // It's possible to match zero documents with MMAPv1 because the update can skip a + // document that was invalidated during a yield. + assertWhenOwnColl.contains(res.nMatched, [0, 1], tojson(res)); + } + if (db.getMongo().writeMode() === 'commands') { + // It's possible that we replaced the document with its current contents, making the + // update a no-op. assertWhenOwnColl.contains(res.nModified, [0, 1], tojson(res)); + assertAlways.lte(res.nModified, res.nMatched, tojson(res)); } } |