summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2018-01-04 17:32:21 -0500
committerTess Avitabile <tess.avitabile@mongodb.com>2018-01-23 09:57:56 -0500
commita98d497c957dc2da7d29c37be9809ace992ef946 (patch)
tree17191166815defa371bfead2ddeb022b752f03a6 /jstests
parentad0ab27807a29e025b36a82ede139c975ad65cfb (diff)
downloadmongo-a98d497c957dc2da7d29c37be9809ace992ef946.tar.gz
SERVER-32517 Parse readConcern snapshot and atClusterTime
Diffstat (limited to 'jstests')
-rw-r--r--jstests/noPassthrough/agg_explain_read_concern.js9
-rw-r--r--jstests/noPassthrough/readConcern_atClusterTime.js85
-rw-r--r--jstests/noPassthrough/readConcern_snapshot.js157
3 files changed, 249 insertions, 2 deletions
diff --git a/jstests/noPassthrough/agg_explain_read_concern.js b/jstests/noPassthrough/agg_explain_read_concern.js
index 4e2f6ec4333..d88eb21ec7e 100644
--- a/jstests/noPassthrough/agg_explain_read_concern.js
+++ b/jstests/noPassthrough/agg_explain_read_concern.js
@@ -30,8 +30,13 @@
}));
// Test that explain is illegal with other readConcern levels.
- let nonLocalReadConcerns = ["majority", "available", "linearizable"];
+ let nonLocalReadConcerns = ["majority", "available", "linearizable", "snapshot"];
nonLocalReadConcerns.forEach(function(readConcernLevel) {
+ if (readConcernLevel === "snapshot" &&
+ !testDB.serverStatus().storageEngine.supportsSnapshotReadConcern) {
+ return;
+ }
+
assert.throws(() => coll.explain().aggregate([], {readConcern: {level: readConcernLevel}}));
let cmdRes = testDB.runCommand({
@@ -49,7 +54,7 @@
readConcern: {level: readConcernLevel}
});
assert.commandFailedWithCode(cmdRes, ErrorCodes.InvalidOptions, tojson(cmdRes));
- expectedErrStr = "Command does not support non local";
+ expectedErrStr = "Command does not support read concern";
assert.neq(cmdRes.errmsg.indexOf(expectedErrStr), -1, tojson(cmdRes));
});
}());
diff --git a/jstests/noPassthrough/readConcern_atClusterTime.js b/jstests/noPassthrough/readConcern_atClusterTime.js
new file mode 100644
index 00000000000..47ccf983d54
--- /dev/null
+++ b/jstests/noPassthrough/readConcern_atClusterTime.js
@@ -0,0 +1,85 @@
+// Test parsing of readConcern option 'atClusterTime'.
+//
+// Only run this test with the WiredTiger storage engine, since we expect other storage engines to
+// return early because they do not support snapshot read concern.
+// @tags: [requires_wiredtiger]
+(function() {
+ "use strict";
+
+ const dbName = "test";
+ const collName = "coll";
+
+ const rst = new ReplSetTest({nodes: 1});
+ rst.startSet();
+ rst.initiate();
+ const testDB = rst.getPrimary().getDB(dbName);
+
+ if (!testDB.serverStatus().storageEngine.supportsSnapshotReadConcern) {
+ rst.stopSet();
+ return;
+ }
+
+ const pingRes = assert.commandWorked(rst.getPrimary().adminCommand({ping: 1}));
+ assert(pingRes.hasOwnProperty("$clusterTime"), tojson(pingRes));
+ assert(pingRes.$clusterTime.hasOwnProperty("clusterTime"), tojson(pingRes));
+ const clusterTime = pingRes.$clusterTime.clusterTime;
+
+ // 'atClusterTime' can be used with readConcern level 'snapshot'.
+ assert.commandWorked(testDB.runCommand(
+ {find: collName, readConcern: {level: "snapshot", atClusterTime: clusterTime}}));
+
+ // 'atClusterTime' must have type Timestamp.
+ assert.commandFailedWithCode(
+ testDB.runCommand({find: collName, readConcern: {level: "snapshot", atClusterTime: "bad"}}),
+ ErrorCodes.TypeMismatch);
+
+ // 'atClusterTime' cannot be used with readConcern level 'majority'.
+ assert.commandFailedWithCode(
+ testDB.runCommand(
+ {find: collName, readConcern: {level: "majority", atClusterTime: clusterTime}}),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used with readConcern level 'local'.
+ assert.commandFailedWithCode(
+ testDB.runCommand(
+ {find: collName, readConcern: {level: "local", atClusterTime: clusterTime}}),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used with readConcern level 'available'.
+ assert.commandFailedWithCode(
+ testDB.runCommand(
+ {find: collName, readConcern: {level: "available", atClusterTime: clusterTime}}),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used with readConcern level 'linearizable'.
+ assert.commandFailedWithCode(
+ testDB.runCommand(
+ {find: collName, readConcern: {level: "linearizable", atClusterTime: clusterTime}}),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used without readConcern level (level is 'local' by default).
+ assert.commandFailedWithCode(
+ testDB.runCommand({find: collName, readConcern: {atClusterTime: clusterTime}}),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used with 'afterOpTime'.
+ assert.commandFailedWithCode(testDB.runCommand({
+ find: collName,
+ readConcern: {
+ level: "snapshot",
+ atClusterTime: clusterTime,
+ afterOpTime: {ts: Timestamp(1, 2), t: 1}
+ }
+ }),
+ ErrorCodes.InvalidOptions);
+
+ // 'atClusterTime' cannot be used with 'afterClusterTime'.
+ assert.commandFailedWithCode(testDB.runCommand({
+ find: collName,
+ readConcern:
+ {level: "snapshot", atClusterTime: clusterTime, afterClusterTime: clusterTime}
+ }),
+ ErrorCodes.InvalidOptions);
+
+ rst.stopSet();
+}());
diff --git a/jstests/noPassthrough/readConcern_snapshot.js b/jstests/noPassthrough/readConcern_snapshot.js
new file mode 100644
index 00000000000..3f2e06885b3
--- /dev/null
+++ b/jstests/noPassthrough/readConcern_snapshot.js
@@ -0,0 +1,157 @@
+// Test parsing of readConcern level 'snapshot'.
+(function() {
+ "use strict";
+
+ const dbName = "test";
+ const collName = "coll";
+
+ //
+ // Configurations.
+ //
+
+ // readConcern 'snapshot' should fail on storage engines that do not support it.
+ let rst = new ReplSetTest({nodes: 1});
+ rst.startSet();
+ rst.initiate();
+ if (!rst.getPrimary().getDB(dbName).serverStatus().storageEngine.supportsSnapshotReadConcern) {
+ assert.commandFailedWithCode(rst.getPrimary().getDB(dbName).runCommand(
+ {find: collName, readConcern: {level: "snapshot"}}),
+ ErrorCodes.InvalidOptions);
+ rst.stopSet();
+ return;
+ }
+ rst.stopSet();
+
+ // readConcern 'snapshot' is not allowed on a standalone.
+ const conn = MongoRunner.runMongod();
+ assert.neq(null, conn, "mongod was unable to start up");
+ assert.commandFailedWithCode(
+ conn.getDB(dbName).runCommand({find: collName, readConcern: {level: "snapshot"}}),
+ ErrorCodes.NotAReplicaSet);
+ MongoRunner.stopMongod(conn);
+
+ // readConcern 'snapshot' is not allowed on mongos.
+ const st = new ShardingTest({shards: 1, rs: {nodes: 1}});
+ assert.commandFailedWithCode(
+ st.getDB(dbName).runCommand({find: collName, readConcern: {level: "snapshot"}}),
+ ErrorCodes.InvalidOptions);
+ st.stop();
+
+ // readConcern 'snapshot' is not allowed with protocol version 0.
+ rst = new ReplSetTest({nodes: 1, protocolVersion: 0});
+ rst.startSet();
+ rst.initiate();
+ assert.commandFailedWithCode(rst.getPrimary().getDB(dbName).runCommand(
+ {find: collName, readConcern: {level: "snapshot"}}),
+ ErrorCodes.IncompatibleElectionProtocol);
+ rst.stopSet();
+
+ // readConcern 'snapshot' is allowed on a replica set primary.
+ rst = new ReplSetTest({nodes: 2});
+ rst.startSet();
+ rst.initiate();
+ assert.commandWorked(rst.getPrimary().getDB(dbName).runCommand(
+ {find: collName, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is allowed on a replica set secondary.
+ assert.commandWorked(rst.getSecondary().getDB(dbName).runCommand(
+ {find: collName, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is allowed with 'afterClusterTime'.
+ const pingRes = assert.commandWorked(rst.getPrimary().adminCommand({ping: 1}));
+ assert(pingRes.hasOwnProperty("$clusterTime"), tojson(pingRes));
+ assert(pingRes.$clusterTime.hasOwnProperty("clusterTime"), tojson(pingRes));
+ assert.commandWorked(rst.getPrimary().getDB(dbName).runCommand({
+ find: collName,
+ readConcern: {level: "snapshot", afterClusterTime: pingRes.$clusterTime.clusterTime}
+ }));
+
+ // readConcern 'snapshot' is not allowed with 'afterOpTime'.
+ assert.commandFailedWithCode(rst.getPrimary().getDB(dbName).runCommand({
+ find: collName,
+ readConcern: {level: "snapshot", afterOpTime: {ts: Timestamp(1, 2), t: 1}}
+ }),
+ ErrorCodes.InvalidOptions);
+ rst.stopSet();
+
+ //
+ // Commands.
+ //
+
+ rst = new ReplSetTest({nodes: 1});
+ rst.startSet();
+ rst.initiate();
+ let testDB = rst.getPrimary().getDB(dbName);
+ let coll = testDB.coll;
+ assert.commandWorked(coll.createIndex({geo: "2d"}));
+ assert.commandWorked(coll.createIndex({haystack: "geoHaystack", a: 1}, {bucketSize: 1}));
+
+ // readConcern 'snapshot' is supported by aggregate.
+ assert.commandWorked(testDB.runCommand(
+ {aggregate: collName, pipeline: [], cursor: {}, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by count.
+ assert.commandWorked(testDB.runCommand({count: collName, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by distinct.
+ assert.commandWorked(testDB.runCommand({count: collName, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by find.
+ assert.commandWorked(testDB.runCommand({find: collName, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by geoNear.
+ assert.commandWorked(
+ testDB.runCommand({geoNear: collName, near: [0, 0], readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by geoSearch.
+ assert.commandWorked(testDB.runCommand({
+ geoSearch: collName,
+ near: [0, 0],
+ maxDistance: 1,
+ search: {a: 1},
+ readConcern: {level: "snapshot"}
+ }));
+
+ // readConcern 'snapshot' is supported by group.
+ assert.commandWorked(testDB.runCommand({
+ group: {ns: collName, key: {_id: 1}, $reduce: function(curr, result) {}, initial: {}},
+ readConcern: {level: "snapshot"}
+ }));
+
+ // readConcern 'snapshot' is supported by insert.
+ assert.commandWorked(
+ testDB.runCommand({insert: collName, documents: [{}], readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by update.
+ assert.commandWorked(testDB.runCommand({
+ update: collName,
+ updates: [{q: {}, u: {$set: {a: 1}}}],
+ readConcern: {level: "snapshot"}
+ }));
+
+ // readConcern 'snapshot' is supported by delete.
+ assert.commandWorked(testDB.runCommand(
+ {delete: collName, deletes: [{q: {}, limit: 1}], readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is supported by findAndModify.
+ assert.commandWorked(testDB.runCommand({
+ findAndModify: collName,
+ filter: {},
+ update: {$set: {a: 1}},
+ readConcern: {level: "snapshot"}
+ }));
+
+ // readConcern 'snapshot' is supported by parallelCollectionScan.
+ assert.commandWorked(testDB.runCommand(
+ {parallelCollectionScan: collName, numCursors: 1, readConcern: {level: "snapshot"}}));
+
+ // readConcern 'snapshot' is not supported by non-CRUD commands.
+ assert.commandFailedWithCode(testDB.runCommand({
+ createIndexes: collName,
+ indexes: [{key: {a: 1}, name: "a_1"}],
+ readConcern: {level: "snapshot"}
+ }),
+ ErrorCodes.InvalidOptions);
+
+ rst.stopSet();
+}());