summaryrefslogtreecommitdiff
path: root/jstests/core
diff options
context:
space:
mode:
authorMartin Neupauer <martin.neupauer@mongodb.com>2018-01-18 12:04:01 -0500
committerMartin Neupauer <martin.neupauer@mongodb.com>2018-01-31 15:05:08 -0500
commit15a7ac9ca54f2d580e2b1d1ab01fe095be1233db (patch)
treec3628b0d5be60aa6bd911c8c351daa9606f6b060 /jstests/core
parent3c349c50d8d5a55fa80c1d7ae3ac6a6f6cc82b5e (diff)
downloadmongo-15a7ac9ca54f2d580e2b1d1ab01fe095be1233db.tar.gz
SERVER-31484 separate the operation deadline from awaitData deadline in sharded queries.
The deadline has been been already separated for non-sharded queries.
Diffstat (limited to 'jstests/core')
-rw-r--r--jstests/core/awaitdata_getmore_cmd.js193
1 files changed, 193 insertions, 0 deletions
diff --git a/jstests/core/awaitdata_getmore_cmd.js b/jstests/core/awaitdata_getmore_cmd.js
new file mode 100644
index 00000000000..a4c577c7f68
--- /dev/null
+++ b/jstests/core/awaitdata_getmore_cmd.js
@@ -0,0 +1,193 @@
+// Test the awaitData flag for the find/getMore commands.
+// @tags: [requires_replication, requires_getmore]
+(function() {
+ 'use strict';
+
+ load("jstests/libs/fixture_helpers.js");
+
+ var cmdRes;
+ var cursorId;
+ var defaultBatchSize = 101;
+ var collName = 'await_data';
+ var coll = db[collName];
+
+ // Create a non-capped collection with 10 documents.
+ coll.drop();
+ for (var i = 0; i < 10; i++) {
+ assert.writeOK(coll.insert({a: i}));
+ }
+
+ // Find with tailable flag set should fail for a non-capped collection.
+ cmdRes = db.runCommand({find: collName, tailable: true});
+ assert.commandFailed(cmdRes);
+
+ // Should also fail in the non-capped case if both the tailable and awaitData flags are set.
+ cmdRes = db.runCommand({find: collName, tailable: true, awaitData: true});
+ assert.commandFailed(cmdRes);
+
+ // With a non-existent collection, should succeed but return no data and a closed cursor.
+ coll.drop();
+ cmdRes = assert.commandWorked(db.runCommand({find: collName, tailable: true}));
+ assert.eq(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.firstBatch.length, 0);
+
+ // Create a capped collection with 10 documents.
+ assert.commandWorked(db.createCollection(collName, {capped: true, size: 2048}));
+ for (var i = 0; i < 10; i++) {
+ assert.writeOK(coll.insert({a: i}));
+ }
+
+ // GetMore should succeed if query has awaitData but no maxTimeMS is supplied.
+ cmdRes = db.runCommand({find: collName, batchSize: 2, awaitData: true, tailable: true});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 2);
+ cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+
+ // Should also succeed if maxTimeMS is supplied on the original find.
+ cmdRes = db.runCommand(
+ {find: collName, batchSize: 2, awaitData: true, tailable: true, maxTimeMS: 2000});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 2);
+ cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+
+ // Check that we can set up a tailable cursor over the capped collection.
+ cmdRes = db.runCommand({find: collName, batchSize: 5, awaitData: true, tailable: true});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 5);
+
+ // Check that tailing the capped collection with awaitData eventually ends up returning an empty
+ // batch after hitting the timeout.
+ cmdRes = db.runCommand({find: collName, batchSize: 2, awaitData: true, tailable: true});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 2);
+
+ // Issue getMore until we get an empty batch of results.
+ cmdRes = db.runCommand({
+ getMore: cmdRes.cursor.id,
+ collection: coll.getName(),
+ batchSize: NumberInt(2),
+ maxTimeMS: 4000
+ });
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+
+ // Keep issuing getMore until we get an empty batch after the timeout expires.
+ while (cmdRes.cursor.nextBatch.length > 0) {
+ var now = new Date();
+ cmdRes = db.runCommand({
+ getMore: cmdRes.cursor.id,
+ collection: coll.getName(),
+ batchSize: NumberInt(2),
+ maxTimeMS: 4000
+ });
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ }
+ assert.gte((new Date()) - now, 2000);
+
+ // Repeat the test, this time tailing the oplog rather than a user-created capped collection.
+ // The oplog tailing in not possible on mongos.
+ if (FixtureHelpers.isReplSet(db)) {
+ var localDB = db.getSiblingDB("local");
+ var oplogColl = localDB.oplog.$main;
+
+ cmdRes = localDB.runCommand(
+ {find: oplogColl.getName(), batchSize: 2, awaitData: true, tailable: true});
+ assert.commandWorked(cmdRes);
+ if (cmdRes.cursor.id > NumberLong(0)) {
+ assert.eq(cmdRes.cursor.ns, oplogColl.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 2);
+
+ cmdRes = localDB.runCommand(
+ {getMore: cmdRes.cursor.id, collection: oplogColl.getName(), maxTimeMS: 1000});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, oplogColl.getFullName());
+
+ while (cmdRes.cursor.nextBatch.length > 0) {
+ now = new Date();
+ cmdRes = localDB.runCommand(
+ {getMore: cmdRes.cursor.id, collection: oplogColl.getName(), maxTimeMS: 4000});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, oplogColl.getFullName());
+ }
+ assert.gte((new Date()) - now, 2000);
+ }
+ }
+
+ // Test filtered inserts while writing to a capped collection.
+ // Find with a filter which doesn't match any documents in the collection.
+ cmdRes = assert.commandWorked(db.runCommand({
+ find: collName,
+ batchSize: 2,
+ filter: {x: 1},
+ awaitData: true,
+ tailable: true,
+ comment: "uniquifier_comment"
+ }));
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.firstBatch.length, 0);
+
+ // getMore should time out if we insert a non-matching document.
+ let insertshell = startParallelShell(function() {
+ assert.soon(
+ function() {
+ return db.currentOp({
+ op: "getmore",
+ "command.collection": "await_data",
+ "originatingCommand.comment": "uniquifier_comment"
+ }).inprog.length == 1;
+ },
+ function() {
+ return tojson(db.currentOp().inprog);
+ });
+ assert.writeOK(db.await_data.insert({x: 0}));
+ });
+
+ now = new Date();
+ cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: 4000});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.nextBatch.length, 0);
+ assert.gte((new Date()) - now,
+ // SERVER-31502 Add some leniency here since our server-side wait may be woken up
+ // spuriously.
+ 3900,
+ "Insert not matching filter caused awaitData getMore to return prematurely.");
+ insertshell();
+
+ // getMore should succeed if we insert a non-matching document followed by a matching one.
+ insertshell = startParallelShell(function() {
+ assert.writeOK(db.await_data.insert({x: 0}));
+ assert.writeOK(db.await_data.insert({_id: "match", x: 1}));
+ jsTestLog("Written");
+ });
+
+ cmdRes =
+ db.runCommand({getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: 5 * 60 * 1000});
+ assert.commandWorked(cmdRes);
+ assert.gt(cmdRes.cursor.id, NumberLong(0));
+ assert.eq(cmdRes.cursor.ns, coll.getFullName());
+ assert.eq(cmdRes.cursor.nextBatch.length, 1);
+ assert.docEq(cmdRes.cursor.nextBatch[0], {_id: "match", x: 1});
+ insertshell();
+})();