diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2018-01-04 17:32:21 -0500 |
---|---|---|
committer | Tess Avitabile <tess.avitabile@mongodb.com> | 2018-01-23 09:57:56 -0500 |
commit | a98d497c957dc2da7d29c37be9809ace992ef946 (patch) | |
tree | 17191166815defa371bfead2ddeb022b752f03a6 /jstests | |
parent | ad0ab27807a29e025b36a82ede139c975ad65cfb (diff) | |
download | mongo-a98d497c957dc2da7d29c37be9809ace992ef946.tar.gz |
SERVER-32517 Parse readConcern snapshot and atClusterTime
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/noPassthrough/agg_explain_read_concern.js | 9 | ||||
-rw-r--r-- | jstests/noPassthrough/readConcern_atClusterTime.js | 85 | ||||
-rw-r--r-- | jstests/noPassthrough/readConcern_snapshot.js | 157 |
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(); +}()); |