diff options
Diffstat (limited to 'jstests/core/write/crud_api.js')
-rw-r--r-- | jstests/core/write/crud_api.js | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/jstests/core/write/crud_api.js b/jstests/core/write/crud_api.js new file mode 100644 index 00000000000..de8d72e50af --- /dev/null +++ b/jstests/core/write/crud_api.js @@ -0,0 +1,730 @@ +// Cannot implicitly shard accessed collections because of following errmsg: A single +// update/delete on a sharded collection must contain an exact match on _id or contain the shard +// key. +// +// @tags: [ +// assumes_unsharded_collection, +// assumes_write_concern_unchanged, +// requires_fastcount, +// # This test writes with {w: 0} which doesn't wait for the storage transaction writing the +// # document and the oplog entry to commit so the TenantMigrationConflict will not be caught. +// tenant_migration_incompatible, +// ] + +(function() { +"use strict"; + +load("jstests/aggregation/extras/utils.js"); // For arrayEq. + +var crudAPISpecTests = function crudAPISpecTests() { + "use strict"; + + // Get the colllection + var coll = db.crud_tests; + + // Setup + function createTestExecutor(coll, method, verifyResult) { + return function(args) { + // Drop collection + coll.drop(); + // Insert test data + var r = coll.insertMany(args.insert); + assert.eq(args.insert.length, r.insertedIds.length); + + // Execute the method with arguments + r = coll[method].apply(coll, args.params); + verifyResult(args.result, r); + + // Get all the results + assert.soonNoExcept( + function() { + var results = coll.find({}).sort({_id: 1}).toArray(); + assert.docEq(args.expected, results); + return true; + }, + function() { + return "collection never contained expected documents"; + }); + }; + } + + function checkResultObject(expected, actual) { + // Only assert on the "modifiedCount" property + assert.docEq(expected, actual); + } + + // Setup executors + var deleteManyExecutor = createTestExecutor(coll, 'deleteMany', checkResultObject); + var deleteOneExecutor = createTestExecutor(coll, 'deleteOne', checkResultObject); + var bulkWriteExecutor = createTestExecutor(coll, 'bulkWrite', checkResultObject); + var findOneAndDeleteExecutor = createTestExecutor(coll, 'findOneAndDelete', checkResultObject); + var findOneAndReplaceExecutor = + createTestExecutor(coll, 'findOneAndReplace', checkResultObject); + var findOneAndUpdateExecutor = createTestExecutor(coll, 'findOneAndUpdate', checkResultObject); + var insertManyExecutor = createTestExecutor(coll, 'insertMany', checkResultObject); + var insertOneExecutor = createTestExecutor(coll, 'insertOne', checkResultObject); + var replaceOneExecutor = createTestExecutor(coll, 'replaceOne', checkResultObject); + var updateManyExecutor = createTestExecutor(coll, 'updateMany', checkResultObject); + var updateOneExecutor = createTestExecutor(coll, 'updateOne', checkResultObject); + var countExecutor = createTestExecutor(coll, 'count', assert.eq); + var distinctExecutor = createTestExecutor(coll, 'distinct', (a, b) => assert(arrayEq(a, b))); + + // + // BulkWrite + // + + bulkWriteExecutor({ + insert: [{_id: 1, c: 1}, {_id: 2, c: 2}, {_id: 3, c: 3}], + params: [[ + {insertOne: {document: {_id: 4, a: 1}}}, + {updateOne: {filter: {_id: 5, a: 2}, update: {$set: {a: 2}}, upsert: true}}, + {updateMany: {filter: {_id: 6, a: 3}, update: {$set: {a: 3}}, upsert: true}}, + {deleteOne: {filter: {c: 1}}}, + {insertOne: {document: {_id: 7, c: 2}}}, + {deleteMany: {filter: {c: 2}}}, + {replaceOne: {filter: {c: 3}, replacement: {c: 4}, upsert: true}} + ]], + result: { + acknowledged: true, + insertedCount: 2, + matchedCount: 1, + deletedCount: 3, + upsertedCount: 2, + insertedIds: {'0': 4, '4': 7}, + upsertedIds: {'1': 5, '2': 6} + }, + expected: [{"_id": 3, "c": 4}, {"_id": 4, "a": 1}, {"_id": 5, "a": 2}, {"_id": 6, "a": 3}] + }); + + bulkWriteExecutor({ + insert: [{_id: 1, c: 1}, {_id: 2, c: 2}, {_id: 3, c: 3}], + params: [ + [ + {insertOne: {document: {_id: 4, a: 1}}}, + {updateOne: {filter: {_id: 5, a: 2}, update: {$set: {a: 2}}, upsert: true}}, + {updateMany: {filter: {_id: 6, a: 3}, update: {$set: {a: 3}}, upsert: true}}, + {deleteOne: {filter: {c: 1}}}, + {deleteMany: {filter: {c: 2}}}, + {replaceOne: {filter: {c: 3}, replacement: {c: 4}, upsert: true}} + ], + {ordered: false} + ], + result: { + acknowledged: true, + insertedCount: 1, + matchedCount: 1, + deletedCount: 2, + upsertedCount: 2, + insertedIds: {'0': 4}, + upsertedIds: {'1': 5, '2': 6} + }, + expected: [{"_id": 3, "c": 4}, {"_id": 4, "a": 1}, {"_id": 5, "a": 2}, {"_id": 6, "a": 3}] + }); + + // DeleteMany + // + + // DeleteMany when many documents match + deleteManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}], + result: {acknowledged: true, deletedCount: 2}, + expected: [{_id: 1, x: 11}] + }); + // DeleteMany when no document matches + deleteManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}], + result: {acknowledged: true, deletedCount: 0}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // DeleteMany when many documents match, no write concern + deleteManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}] + }); + + // + // DeleteOne + // + + // DeleteOne when many documents match + deleteOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}], + result: {acknowledged: true, deletedCount: 1}, + expected: [{_id: 1, x: 11}, {_id: 3, x: 33}] + }); + // DeleteOne when one document matches + deleteOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 2}], + result: {acknowledged: true, deletedCount: 1}, + expected: [{_id: 1, x: 11}, {_id: 3, x: 33}] + }); + // DeleteOne when no documents match + deleteOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}], + result: {acknowledged: true, deletedCount: 0}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // DeleteOne when many documents match, no write concern + deleteOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 3, x: 33}] + }); + + // + // FindOneAndDelete + // + + // FindOneAndDelete when one document matches + findOneAndDeleteExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 2}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 33}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}] + }); + // FindOneAndDelete when one document matches + findOneAndDeleteExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 2}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 22}, + expected: [{_id: 1, x: 11}, {_id: 3, x: 33}] + }); + // FindOneAndDelete when no documents match + findOneAndDeleteExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + + // + // FindOneAndReplace + // + + // FindOneAndReplace when many documents match returning the document before modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 22}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 32}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when many documents match returning the document after modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: {$gt: 1}}, + {x: 32}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: {x: 32}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 32}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when one document matches returning the document before modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 2}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 22}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 32}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when one document matches returning the document after modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 2}, + {x: 32}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: {x: 32}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 32}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when no documents match returning the document before modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when no documents match with upsert returning the document before + // modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}, upsert: true}], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 44}] + }); + // FindOneAndReplace when no documents match returning the document after modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 4}, + {x: 44}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // FindOneAndReplace when no documents match with upsert returning the document after + // modification + findOneAndReplaceExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 4}, + {x: 44}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true, upsert: true} + ], + result: {x: 44}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 44}] + }); + + assert.throws(function() { + coll.findOneAndReplace({a: 1}, {$set: {b: 1}}); + }); + + // + // FindOneAndUpdate + // + + // FindOneAndUpdate when many documents match returning the document before modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 22}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when many documents match returning the document after modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: {$gt: 1}}, + {$inc: {x: 1}}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: {x: 23}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when one document matches returning the document before modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 2}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: {x: 22}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when one document matches returning the document after modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 2}, + {$inc: {x: 1}}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: {x: 23}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when no documents match returning the document before modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when no documents match with upsert returning the document before + // modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: + [{_id: 4}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}, upsert: true}], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // FindOneAndUpdate when no documents match returning the document after modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 4}, + {$inc: {x: 1}}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true} + ], + result: null, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // FindOneAndUpdate when no documents match with upsert returning the document after + // modification + findOneAndUpdateExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [ + {_id: 4}, + {$inc: {x: 1}}, + {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true, upsert: true} + ], + result: {x: 1}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + + assert.throws(function() { + coll.findOneAndUpdate({a: 1}, {}); + }); + + assert.throws(function() { + coll.findOneAndUpdate({a: 1}, {b: 1}); + }); + + // + // InsertMany + // + + // InsertMany with non-existing documents + insertManyExecutor({ + insert: [{_id: 1, x: 11}], + params: [[{_id: 2, x: 22}, {_id: 3, x: 33}]], + result: {acknowledged: true, insertedIds: [2, 3]}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // InsertMany with non-existing documents, no write concern + insertManyExecutor({ + insert: [{_id: 1, x: 11}], + params: [[{_id: 2, x: 22}, {_id: 3, x: 33}], {w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + + // + // InsertOne + // + + // InsertOne with non-existing documents + insertOneExecutor({ + insert: [{_id: 1, x: 11}], + params: [{_id: 2, x: 22}], + result: {acknowledged: true, insertedId: 2}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}] + }); + // InsertOne with non-existing documents, no write concern + insertOneExecutor({ + insert: [{_id: 1, x: 11}], + params: [{_id: 2, x: 22}, {w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}] + }); + + // + // ReplaceOne + // + + // ReplaceOne when many documents match + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {x: 111}], + result: {acknowledged: true, matchedCount: 1, modifiedCount: 1}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 111}, {_id: 3, x: 33}] + }); + // ReplaceOne when one document matches + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 1}, {_id: 1, x: 111}], + result: {acknowledged: true, matchedCount: 1, modifiedCount: 1}, + expected: [{_id: 1, x: 111}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // ReplaceOne when no documents match + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {_id: 4, x: 1}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // ReplaceOne with upsert when no documents match without an id specified + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {x: 1}, {upsert: true}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // ReplaceOne with upsert when no documents match with an id specified + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // ReplaceOne with upsert when no documents match with an id specified, no write concern + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true, w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // ReplaceOne with upsert when no documents match with an id specified, no write concern + replaceOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true, writeConcern: {w: 0}}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + + assert.throws(function() { + coll.replaceOne({a: 1}, {$set: {b: 1}}); + }); + + // + // UpdateMany + // + + // UpdateMany when many documents match + updateManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 2, modifiedCount: 2}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 34}] + }); + // UpdateMany when one document matches + updateManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 1}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 1, modifiedCount: 1}, + expected: [{_id: 1, x: 12}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // UpdateMany when no documents match + updateManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // UpdateMany with upsert when no documents match + updateManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // UpdateMany with upsert when no documents match, no write concern + updateManyExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true, w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + + assert.throws(function() { + coll.updateMany({a: 1}, {}); + }); + + assert.throws(function() { + coll.updateMany({a: 1}, {b: 1}); + }); + + // + // UpdateOne + // + + // UpdateOne when many documents match + updateOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 1, modifiedCount: 1}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + // UpdateOne when one document matches + updateOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 1}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 1, modifiedCount: 1}, + expected: [{_id: 1, x: 12}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // UpdateOne when no documents match + updateOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + + // UpdateOne with upsert when no documents match + updateOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true}], + result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}, {_id: 4, x: 1}] + }); + // UpdateOne when many documents match, no write concern + updateOneExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}, {$inc: {x: 1}}, {w: 0}], + result: {acknowledged: false}, + expected: [{_id: 1, x: 11}, {_id: 2, x: 23}, {_id: 3, x: 33}] + }); + + assert.throws(function() { + coll.updateOne({a: 1}, {}); + }); + + assert.throws(function() { + coll.updateOne({a: 1}, {b: 1}); + }); + + // + // Count + // + + // Simple count of all elements + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{}], + result: 3, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple count no arguments + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [], + result: 3, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple count filtered + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{_id: {$gt: 1}}], + result: 2, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple count of all elements, applying limit + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{}, {limit: 1}], + result: 1, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple count of all elements, applying skip + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{}, {skip: 1}], + result: 2, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple count no arguments, applying hint + countExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: [{}, {hint: {"_id": 1}}], + result: 3, + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + + // + // Distinct + // + + // Simple distinct of field x no filter + distinctExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: ['x'], + result: [11, 22, 33], + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple distinct of field x + distinctExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: ['x', {}], + result: [11, 22, 33], + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple distinct of field x filtered + distinctExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: ['x', {x: {$gt: 11}}], + result: [22, 33], + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + // Simple distinct of field x filtered with maxTimeMS + distinctExecutor({ + insert: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}], + params: ['x', {x: {$gt: 11}}, {maxTimeMS: 100000}], + result: [22, 33], + expected: [{_id: 1, x: 11}, {_id: 2, x: 22}, {_id: 3, x: 33}] + }); + + // + // Find + // + + coll.deleteMany({}); + // Insert all of them + coll.insertMany([{a: 0, b: 0}, {a: 1, b: 1}]); + + // Simple projection + var result = coll.find({}).sort({a: 1}).limit(1).skip(1).projection({_id: 0, a: 1}).toArray(); + assert.docEq([{a: 1}], result); + + // Simple tailable cursor + var cursor = coll.find({}).sort({a: 1}).tailable(); + assert.eq(34, (cursor._options & ~DBQuery.Option.slaveOk)); + var cursor = coll.find({}).sort({a: 1}).tailable(false); + assert.eq(2, (cursor._options & ~DBQuery.Option.slaveOk)); + + // allowPartialResults + var cursor = coll.find({}).allowPartialResults(); + assert.eq(128, (cursor._options & ~DBQuery.Option.slaveOk)); + + // noCursorTimeout + var cursor = coll.find({}).noCursorTimeout(); + assert.eq(16, (cursor._options & ~DBQuery.Option.slaveOk)); + + // + // Aggregation + // + + coll.deleteMany({}); + // Insert all of them + coll.insertMany([{a: 0, b: 0}, {a: 1, b: 1}]); + + // Simple aggregation with useCursor + var result = coll.aggregate([{$match: {}}], {useCursor: true}).toArray(); + assert.eq(2, result.length); + + // Simple aggregation with batchSize + var result = coll.aggregate([{$match: {}}], {batchSize: 2}).toArray(); + assert.eq(2, result.length); + + // Drop collection + coll.drop(); + coll.createIndex({a: 1}, {unique: true}); + + // Should throw duplicate key error + assert.throws(function() { + coll.insertMany([{a: 0, b: 0}, {a: 0, b: 1}]); + }); + + assert(coll.findOne({a: 0, b: 0}) != null); + assert.throws(function() { + coll.insertOne({a: 0, b: 0}); + }); + + assert.throws(function() { + coll.updateOne({b: 2}, {$set: {a: 0}}, {upsert: true}); + }); + + assert.throws(function() { + coll.updateMany({b: 2}, {$set: {a: 0}}, {upsert: true}); + }); + + assert.throws(function() { + coll.deleteOne({$invalidFieldName: {a: 1}}); + }); + + assert.throws(function() { + coll.deleteMany({$set: {a: 1}}); + }); + + assert.throws(function() { + coll.bulkWrite([{insertOne: {document: {_id: 4, a: 0}}}]); + }); +}; + +crudAPISpecTests(); +})(); |