diff options
author | Mihai Andrei <mihai.andrei@10gen.com> | 2020-05-08 11:33:45 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-11 22:58:41 +0000 |
commit | 649790b0ba9df895f168ac061941eacb633792f9 (patch) | |
tree | f4deedf582d5efafe568a0bc5d46ff4dfbb3814d | |
parent | b9bd6ded04f0136157c50c85c8bdc6bb176cccc9 (diff) | |
download | mongo-649790b0ba9df895f168ac061941eacb633792f9.tar.gz |
SERVER-48043 mode_merge_fail.js and mode_pipeline_fail.js should not assume ordering of writes from $merge
-rw-r--r-- | jstests/aggregation/sources/merge/mode_merge_fail.js | 28 | ||||
-rw-r--r-- | jstests/aggregation/sources/merge/mode_pipeline_fail.js | 28 | ||||
-rw-r--r-- | jstests/aggregation/sources/merge/mode_replace_fail.js | 14 |
3 files changed, 57 insertions, 13 deletions
diff --git a/jstests/aggregation/sources/merge/mode_merge_fail.js b/jstests/aggregation/sources/merge/mode_merge_fail.js index ec9ca5af3a4..7235c8e1c7e 100644 --- a/jstests/aggregation/sources/merge/mode_merge_fail.js +++ b/jstests/aggregation/sources/merge/mode_merge_fail.js @@ -26,15 +26,37 @@ const pipeline = [mergeStage]; assert.commandWorked(target.insert([{_id: 1, b: 1}, {_id: 3, b: 3}])); let error = assert.throws(() => source.aggregate(pipeline)); assert.commandFailedWithCode(error, ErrorCodes.MergeStageNoMatchingDocument); - assertArrayEq( - {actual: target.find().toArray(), expected: [{_id: 1, a: 1, b: 1}, {_id: 3, a: 3, b: 3}]}); + // Since there is no way to guarantee the ordering of the writes performed by $merge, it + // follows that the contents of the target collection will depend on when the write which + // triggers the MergeStageNoMatchingDocument error executes. As such, we test that the + // target collection contains some combination of its original documents and expected + // updates. In particular, it should be the case that each document has fields '_id' and + // 'b', but may or not have field 'a'. All present fields must share the same value as _id. + let checkOutputDocument = function(document) { + const hasB = document.hasOwnProperty("b"); + const hasA = document.hasOwnProperty("a"); + assert(hasB, document); + const bValue = document["b"]; + assert.eq(bValue, document["_id"], document); + if (hasA) { + assert.eq(bValue, document["a"], document); + } + }; + + let result = target.find().toArray(); + assert.eq(result.length, 2, result); + for (let elem of result) { + checkOutputDocument(elem); + } // Multiple documents without a match. assert(target.drop()); assert.commandWorked(target.insert([{_id: 1, b: 1}])); error = assert.throws(() => source.aggregate(pipeline)); assert.commandFailedWithCode(error, ErrorCodes.MergeStageNoMatchingDocument); - assertArrayEq({actual: target.find().toArray(), expected: [{_id: 1, a: 1, b: 1}]}); + result = target.find().toArray(); + assert.eq(result.length, 1, result); + checkOutputDocument(result[0]); })(); // Test $merge when all documents in the source collection have a matching document in the diff --git a/jstests/aggregation/sources/merge/mode_pipeline_fail.js b/jstests/aggregation/sources/merge/mode_pipeline_fail.js index 39282011e5b..08e503a0086 100644 --- a/jstests/aggregation/sources/merge/mode_pipeline_fail.js +++ b/jstests/aggregation/sources/merge/mode_pipeline_fail.js @@ -25,15 +25,37 @@ const pipeline = [mergeStage]; assert.commandWorked(target.insert([{_id: 1, b: 1}, {_id: 3, b: 3}])); let error = assert.throws(() => source.aggregate(pipeline)); assert.commandFailedWithCode(error, ErrorCodes.MergeStageNoMatchingDocument); - assertArrayEq( - {actual: target.find().toArray(), expected: [{_id: 1, b: 1, x: 2}, {_id: 3, b: 3, x: 2}]}); + // Since there is no way to guarantee the ordering of the writes performed by $merge, it + // follows that the contents of the target collection will depend on when the write which + // triggers the MergeStageNoMatchingDocument error executes. As such, we test that the + // target collection contains some combination of its original documents and expected + // updates. In particular, it should be the case that each document has fields '_id' and + // 'b', but may or not have field 'x'. Additionally, 'b' should have the same value as + // '_id' and if 'x' is present, it should be equal to 2. + let checkOutputDocument = function(document) { + const hasB = document.hasOwnProperty("b"); + const hasX = document.hasOwnProperty("x"); + assert(hasB, document); + const value = document["b"]; + assert.eq(value, document['_id'], document); + if (hasX) + assert.eq(2, document['x'], document); + }; + + let result = target.find().toArray(); + assert.eq(result.length, 2, result); + for (let elem of result) { + checkOutputDocument(elem); + } // Multiple documents without a match. assert(target.drop()); assert.commandWorked(target.insert([{_id: 1, b: 1}])); error = assert.throws(() => source.aggregate(pipeline)); assert.commandFailedWithCode(error, ErrorCodes.MergeStageNoMatchingDocument); - assertArrayEq({actual: target.find().toArray(), expected: [{_id: 1, b: 1, x: 2}]}); + result = target.find().toArray(); + assert.eq(result.length, 1, result); + checkOutputDocument(result[0]); })(); // Test $merge when all documents in the source collection have a matching document in the diff --git a/jstests/aggregation/sources/merge/mode_replace_fail.js b/jstests/aggregation/sources/merge/mode_replace_fail.js index ff05d131a62..88582238c8f 100644 --- a/jstests/aggregation/sources/merge/mode_replace_fail.js +++ b/jstests/aggregation/sources/merge/mode_replace_fail.js @@ -24,17 +24,17 @@ const pipeline = [mergeStage]; let error = assert.throws(() => source.aggregate(pipeline)); assert.commandFailedWithCode(error, ErrorCodes.MergeStageNoMatchingDocument); // Since there is no way to guarantee the ordering of the writes performed by $merge, it - // follows that the contents of the target collection will depend on when the document which + // follows that the contents of the target collection will depend on when the write which // triggers the MergeStageNoMatchingDocument error executes. As such, we test that the // target collection contains some combination of its original documents and expected // updates. In particular, it should be the case that each document has exactly one of field // 'a' or field 'b' and its value should equal that of '_id'. - let checkOutputDocument = function(elem) { - const hasA = elem.hasOwnProperty('a'); - const hasB = elem.hasOwnProperty('b'); - assert(hasA ^ hasB); - const value = hasA ? elem['a'] : elem['b']; - assert.eq(value, elem['_id'], elem); + let checkOutputDocument = function(document) { + const hasA = document.hasOwnProperty('a'); + const hasB = document.hasOwnProperty('b'); + assert(hasA ^ hasB, document); + const value = hasA ? document['a'] : document['b']; + assert.eq(value, document['_id'], document); }; let result = target.find().toArray(); |