diff options
Diffstat (limited to 'jstests/sharding/libs/mongos_api_params_util.js')
-rw-r--r-- | jstests/sharding/libs/mongos_api_params_util.js | 1496 |
1 files changed, 0 insertions, 1496 deletions
diff --git a/jstests/sharding/libs/mongos_api_params_util.js b/jstests/sharding/libs/mongos_api_params_util.js deleted file mode 100644 index 1da16ff8d52..00000000000 --- a/jstests/sharding/libs/mongos_api_params_util.js +++ /dev/null @@ -1,1496 +0,0 @@ -/* - * Utilities for checking that mongos commands forward their API version parameters to config - * servers and shards. - */ - -let MongosAPIParametersUtil = (function() { - 'use strict'; - - load('jstests/replsets/rslib.js'); - load('jstests/sharding/libs/last_lts_mongos_commands.js'); - load('jstests/sharding/libs/sharded_transactions_helpers.js'); - - function validateTestCase(testCase) { - assert(testCase.skip || testCase.run, - "must specify exactly one of 'skip' or 'run' for test case " + tojson(testCase)); - - if (testCase.skip) { - for (let key of Object.keys(testCase)) { - assert( - key === "commandName" || key === "skip" || key === "conditional", - `if a test case specifies 'skip', it must not specify any other fields besides` + - ` 'commandName' and 'conditional': ${key}: ${tojson(testCase)}`); - } - return; - } - - validateCommandTestCase(testCase.run); - - if (testCase.explain) { - validateCommandTestCase(testCase.explain); - } - } - - function validateCommandTestCase(testCase) { - assert(testCase.command, "must specify 'command' for test case " + tojson(testCase)); - - // Check that required fields are present. - assert(testCase.hasOwnProperty("inAPIVersion1"), - "must specify 'inAPIVersion1' for test case " + tojson(testCase)); - - // Check that all present fields are of the correct type. - assert(typeof (testCase.command) === "function"); - assert(typeof (testCase.inAPIVersion1) === "boolean"); - - for (const [propertyName, defaultValue] of [["runsAgainstAdminDb", false], - ["permittedInTxn", true], - ["permittedOnShardedCollection", true], - ["requiresShardedCollection", false]]) { - if (testCase.hasOwnProperty(propertyName)) { - assert(typeof testCase[propertyName] === "boolean", - `${propertyName} must be a boolean: ${tojson(testCase)}`); - } else { - testCase[propertyName] = defaultValue; - } - } - - assert(testCase.shardCommandName ? typeof (testCase.shardCommandName) === "string" : true); - assert(testCase.configServerCommandName - ? typeof (testCase.configServerCommandName) === "string" - : true); - assert(testCase.shardCommandName || testCase.configServerCommandName, - "must specify shardCommandName and/or configServerCommandName: " + tojson(testCase)); - assert(testCase.setUp ? typeof (testCase.setUp) === "function" : true, - "setUp must be a function: " + tojson(testCase)); - assert(testCase.cleanUp ? typeof (testCase.cleanUp) === "function" : true, - "cleanUp must be a function: " + tojson(testCase)); - } - - function awaitRemoveShard(shardName) { - assert.commandWorked(st.startBalancer()); - st.waitForBalancer(true, 60000); - assert.soon(() => { - const res = st.s.adminCommand({removeShard: shardName}); - jsTestLog(`removeShard result: ${tojson(res)}`); - if (!res.ok && res.code === ErrorCodes.ShardNotFound) { - return true; - } - - return 'completed' === res.state; - }, "removeShard never completed for shard " + shardName, 10 * 60 * 1000, 1000); - assert.commandWorked(st.stopBalancer()); - } - - // Each test case is potentially run with any combination of API parameters, in - // sharded/unsharded collection, inside or outside of a multi-document transaction. The "db" - // database is dropped and recreated between test cases, so most tests don't need custom setUp - // or cleanUp. Test cases are not 1-1 with commands, e.g. "count" has two cases. - let testCases = [ - { - commandName: "_hashBSONElement", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "_isSelf", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "_killOperations", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "_mergeAuthzCollections", skip: "internal API"}, - {commandName: "abortTransaction", skip: "prohibits API parameters"}, - { - commandName: "addShard", - run: { - inAPIVersion1: false, - runsAgainstAdminDb: true, - configServerCommandName: "_configsvrAddShard", - shardCommandName: "_addShard", - permittedInTxn: false, - setUp: () => { - // Remove shard0 so we can add it back. - assert.commandWorked(st.s0.getDB("db").dropDatabase()); - awaitRemoveShard(st.shard0.shardName); - }, - command: () => ({addShard: st.rs0.getURL()}) - } - }, - { - commandName: "addShardToZone", - run: { - inAPIVersion1: false, - runsAgainstAdminDb: true, - configServerCommandName: "_configsvrAddShardToZone", - permittedInTxn: false, - command: () => ({addShardToZone: st.shard0.shardName, zone: "foo"}), - cleanUp: () => assert.commandWorked(st.s0.getDB("admin").runCommand( - {removeShardFromZone: st.shard0.shardName, zone: "foo"})) - } - }, - { - commandName: "aggregate", - run: { - inAPIVersion1: true, - shardCommandName: "aggregate", - command: () => ({aggregate: "collection", pipeline: [], cursor: {}}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({explain: {aggregate: "collection", pipeline: [], cursor: {}}}) - } - }, - { - commandName: "authenticate", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "availableQueryOptions", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "balancerCollectionStatus", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "balancerStart", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "balancerStatus", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "balancerStop", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "buildInfo", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "clearJumboFlag", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "clearLog", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "collMod", - run: { - inAPIVersion1: true, - shardCommandName: "collMod", - permittedInTxn: false, - command: () => ({collMod: "collection"}), - } - }, - { - commandName: "collStats", - run: { - inAPIVersion1: false, - shardCommandName: "collStats", - permittedInTxn: false, - command: () => ({collStats: "collection"}), - } - }, - {commandName: "commitTransaction", skip: "prohibits API parameters"}, - {commandName: "compact", skip: "not allowed through mongos"}, - { - commandName: "configureFailPoint", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "connPoolStats", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "connPoolSync", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "connectionStatus", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "convertToCapped", - run: { - inAPIVersion1: false, - shardCommandName: "convertToCapped", - permittedOnShardedCollection: false, - permittedInTxn: false, - command: () => ({convertToCapped: "collection", size: 8192}), - } - }, - // The count command behaves differently if it has a query or no query. - { - commandName: "count", - run: { - inAPIVersion1: true, - shardCommandName: "count", - permittedInTxn: false, - command: () => ({count: "collection"}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({explain: {count: "collection"}}) - } - }, - { - commandName: "count", - run: { - inAPIVersion1: true, - shardCommandName: "count", - permittedInTxn: false, - command: () => ({count: "collection", query: {x: 1}}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({explain: {count: "collection", query: {x: 1}}}) - } - }, - { - commandName: "create", - run: { - inAPIVersion1: true, - shardCommandName: "create", - command: () => ({create: "collection2"}) - } - }, - { - commandName: "createIndexes", - run: { - inAPIVersion1: true, - shardCommandName: "createIndexes", - permittedInTxn: false, - command: () => - ({createIndexes: "collection", indexes: [{key: {a: 1}, name: "index"}]}) - } - }, - { - commandName: "createRole", - run: { - inAPIVersion1: false, - configServerCommandName: "createRole", - permittedInTxn: false, - command: () => ({createRole: "foo", privileges: [], roles: []}), - cleanUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})) - } - }, - { - commandName: "createUser", - run: { - inAPIVersion1: false, - configServerCommandName: "createUser", - permittedInTxn: false, - command: () => ({createUser: "foo", pwd: "bar", roles: []}), - cleanUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"})) - } - }, - { - commandName: "currentOp", - run: { - inAPIVersion1: false, - shardCommandName: "aggregate", - permittedInTxn: false, - runsAgainstAdminDb: true, - command: () => ({currentOp: 1}) - } - }, - { - commandName: "dataSize", - run: { - inAPIVersion1: false, - shardCommandName: "dataSize", - permittedInTxn: false, - command: () => ({dataSize: "db.collection"}), - } - }, - { - commandName: "dbStats", - run: { - inAPIVersion1: false, - shardCommandName: "dbStats", - permittedInTxn: false, - command: () => ({dbStats: 1, scale: 1}) - } - }, - { - commandName: "delete", - run: { - inAPIVersion1: true, - shardCommandName: "delete", - command: () => ({delete: "collection", deletes: [{q: {_id: 1}, limit: 1}]}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => - ({explain: {delete: "collection", deletes: [{q: {_id: 1}, limit: 1}]}}) - } - }, - { - commandName: "distinct", - run: { - inAPIVersion1: false, - shardCommandName: "distinct", - permittedInTxn: false, - command: () => ({distinct: "collection", key: "x"}) - }, - explain: { - inAPIVersion1: false, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({explain: {distinct: "collection", key: "x"}}) - }, - }, - { - commandName: "drop", - run: { - inAPIVersion1: true, - shardCommandName: "drop", - permittedInTxn: false, - command: () => ({drop: "collection"}) - } - }, - { - commandName: "dropAllRolesFromDatabase", - run: { - inAPIVersion1: false, - configServerCommandName: "dropAllRolesFromDatabase", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})), - command: () => ({dropAllRolesFromDatabase: 1}) - } - }, - { - commandName: "dropAllUsersFromDatabase", - run: { - inAPIVersion1: false, - configServerCommandName: "dropAllUsersFromDatabase", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})), - command: () => ({dropAllUsersFromDatabase: 1}) - } - }, - { - commandName: "dropConnections", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "dropDatabase", - run: { - inAPIVersion1: true, - configServerCommandName: "_configsvrDropDatabase", - shardCommandName: "dropDatabase", - permittedInTxn: false, - command: () => ({dropDatabase: 1}) - } - }, - { - commandName: "dropIndexes", - run: { - inAPIVersion1: true, - shardCommandName: "dropIndexes", - permittedInTxn: false, - command: () => ({dropIndexes: "collection", index: "*"}), - } - }, - { - commandName: "dropRole", - run: { - inAPIVersion1: false, - configServerCommandName: "dropRole", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})), - command: () => ({dropRole: "foo"}) - } - }, - { - commandName: "dropUser", - run: { - inAPIVersion1: false, - configServerCommandName: "dropUser", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})), - command: () => ({dropUser: "foo"}) - } - }, - {commandName: "echo", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "enableSharding", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "endSessions", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "explain", skip: "tested by other means"}, - {commandName: "features", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "filemd5", - run: { - inAPIVersion1: false, - shardCommandName: "filemd5", - permittedInTxn: false, - command: () => ({filemd5: ObjectId(), root: "collection"}) - } - }, - { - commandName: "find", - run: { - inAPIVersion1: true, - shardCommandName: "find", - command: () => ({find: "collection", filter: {x: 1}}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({explain: {find: "collection", filter: {x: 1}}}) - } - }, - { - commandName: "findAndModify", - run: { - inAPIVersion1: true, - shardCommandName: "findAndModify", - command: () => ({findAndModify: "collection", query: {_id: 0}, remove: true}) - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => - ({explain: {findAndModify: "collection", query: {_id: 0}, remove: true}}) - } - }, - { - commandName: "flushRouterConfig", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "fsync", - run: { - inAPIVersion1: false, - shardCommandName: "fsync", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({fsync: 1}) - } - }, - { - commandName: "getCmdLineOpts", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "getDefaultRWConcern", - run: { - inAPIVersion1: false, - configServerCommandName: "getDefaultRWConcern", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({getDefaultRWConcern: 1}) - } - }, - { - commandName: "getDiagnosticData", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "getLastError", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "getLog", skip: "executes locally on mongos (not sent to any remote node)"}, - {commandName: "getMore", skip: "prohibits API parameters"}, - { - commandName: "getParameter", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "getShardMap", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "getShardVersion", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "getnonce", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "grantPrivilegesToRole", - run: { - inAPIVersion1: false, - configServerCommandName: "grantPrivilegesToRole", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})), - command: () => ({ - grantPrivilegesToRole: "foo", - privileges: - [{resource: {db: "db", collection: "collection"}, actions: ["find"]}] - }), - cleanUp: () => - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})), - } - }, - { - commandName: "grantRolesToRole", - run: { - inAPIVersion1: false, - configServerCommandName: "grantRolesToRole", - permittedInTxn: false, - setUp: function() { - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "bar", privileges: [], roles: [], writeConcern: {w: 1}})); - }, - command: () => ({grantRolesToRole: "foo", roles: [{role: "bar", db: "db"}]}), - cleanUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})); - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "bar"})); - } - } - }, - { - commandName: "grantRolesToUser", - run: { - inAPIVersion1: false, - configServerCommandName: "grantRolesToUser", - permittedInTxn: false, - setUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand( - {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})); - }, - command: () => ({grantRolesToUser: "foo", roles: [{role: "foo", db: "db"}]}), - cleanUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"})); - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})); - } - } - }, - {commandName: "hello", skip: "executes locally on mongos (not sent to any remote node)"}, - {commandName: "hostInfo", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "insert", - run: { - inAPIVersion1: true, - shardCommandName: "insert", - command: () => ({insert: "collection", documents: [{_id: 1}]}), - } - }, - { - commandName: "invalidateUserCache", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "isdbgrid", skip: "executes locally on mongos (not sent to any remote node)"}, - {commandName: "isMaster", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "killCursors", - run: - { - inAPIVersion1: true, - shardCommandName: "killCursors", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {insert: "collection", documents: [{}, {}, {}]})), - command: - () => { - const res = assert.commandWorked( - st.s0.getDB("db").runCommand({find: "collection", batchSize: 1})); - jsTestLog(`res: ${res}`); - const cursorId = res.cursor.id; - return {killCursors: "collection", cursors: [cursorId]}; - } - } - }, - { - commandName: "killAllSessions", - run: { - inAPIVersion1: false, - shardCommandName: "killAllSessionsByPattern", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({killAllSessions: []}) - } - }, - { - commandName: "killAllSessionsByPattern", - run: { - inAPIVersion1: false, - shardCommandName: "killAllSessionsByPattern", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({killAllSessionsByPattern: []}) - } - }, - { - commandName: "killOp", - run: { - inAPIVersion1: false, - shardCommandName: "killOp", - permittedInTxn: false, - runsAgainstAdminDb: true, - setUp: (context) => { - function threadRoutine({connStr}) { - const client = new Mongo(connStr); - jsTestLog(`Calling find on "${connStr}" from thread`); - const res = client.getDB("db").runCommand({ - find: "collection", - filter: {$where: "sleep(99999999); return true;"}, - comment: "foo" - }); - jsTestLog(`Called find command: ${tojson(res)}`); - } - - context.thread = new Thread(threadRoutine, {connStr: st.s0.host}); - context.thread.start(); - const adminDb = st.s0.getDB("admin"); - - assert.soon(() => { - const inprog = adminDb.currentOp({"command.comment": "foo"}).inprog; - if (inprog.length === 1) { - context.findOpId = inprog[0].opid; - return true; - } - }); - }, - command: (context) => ({killOp: 1, op: context.findOpId}), - cleanUp: (context) => { - context.thread.join(); - } - } - }, - { - commandName: "killSessions", - run: { - inAPIVersion1: false, - shardCommandName: "killAllSessionsByPattern", - runsAgainstAdminDb: true, - permittedInTxn: false, - setUp: (context) => { - const session = st.s0.startSession(); - context.lsid = session.getSessionId(); - }, - command: (context) => ({killSessions: [context.lsid]}) - } - }, - { - commandName: "listCollections", - run: { - inAPIVersion1: true, - shardCommandName: "listCollections", - permittedInTxn: false, - command: () => ({listCollections: 1}) - } - }, - { - commandName: "listCommands", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "listDatabases", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "listIndexes", - run: { - inAPIVersion1: true, - shardCommandName: "listIndexes", - permittedInTxn: false, - command: () => ({listIndexes: "collection"}), - } - }, - { - commandName: "listShards", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "logApplicationMessage", - skip: "executes locally on mongos (not sent to any remote node)", - conditional: true - }, - { - commandName: "logMessage", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "logRotate", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "logout", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "mapReduce", - run: { - inAPIVersion1: false, - permittedInTxn: false, - shardCommandName: "aggregate", - command: () => ({ - mapReduce: "collection", - map: function mapFunc() { - emit(this.x, 1); - }, - reduce: function reduceFunc(key, values) { - return Array.sum(values); - }, - out: "inline" - }), - }, - explain: { - inAPIVersion1: false, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({ - explain: { - mapReduce: "collection", - map: function mapFunc() { - emit(this.x, 1); - }, - reduce: function reduceFunc(key, values) { - return Array.sum(values); - }, - out: "inline" - } - }), - } - }, - { - commandName: "mergeChunks", - run: { - inAPIVersion1: false, - shardCommandName: "mergeChunks", - configServerCommandName: "_configsvrCommitChunkMerge", - runsAgainstAdminDb: true, - permittedInTxn: false, - requiresShardedCollection: true, - setUp: () => { - // Collection is already split into chunks [MinKey, 10], (10, MaxKey]. - assert.commandWorked( - st.s.adminCommand({split: "db.collection", middle: {_id: -5}})); - // Now the chunks are: [MinKey, -5], (-5, 10], (10, MaxKey]. - }, - command: () => ({mergeChunks: "db.collection", bounds: [{_id: MinKey}, {_id: 10}]}) - } - }, - { - commandName: "moveChunk", - run: { - inAPIVersion1: false, - shardCommandName: "moveChunk", - configServerCommandName: "_configsvrMoveChunk", - runsAgainstAdminDb: true, - permittedInTxn: false, - requiresShardedCollection: true, - command: () => ({ - moveChunk: "db.collection", - find: {_id: 1}, - to: st.shard1.shardName, - // Don't interfere with the next test case. - _waitForDelete: true - }) - } - }, - { - commandName: "movePrimary", - run: { - inAPIVersion1: false, - configServerCommandName: "_configsvrMovePrimary", - shardCommandName: "_shardsvrMovePrimary", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({movePrimary: "db", to: st.shard1.shardName}) - } - }, - { - commandName: "multicast", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "netstat", skip: "executes locally on mongos (not sent to any remote node)"}, - {commandName: "ping", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "planCacheClear", - run: { - inAPIVersion1: false, - shardCommandName: "planCacheClear", - permittedInTxn: false, - command: () => ({planCacheClear: "collection"}) - } - }, - { - commandName: "planCacheClearFilters", - run: { - inAPIVersion1: false, - shardCommandName: "planCacheClearFilters", - permittedInTxn: false, - command: () => ({planCacheClearFilters: "collection"}) - } - }, - { - commandName: "planCacheListFilters", - run: { - inAPIVersion1: false, - shardCommandName: "planCacheListFilters", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {planCacheSetFilter: "collection", query: {_id: 1}, indexes: [{_id: 1}]})), - command: () => ({planCacheListFilters: "collection"}) - } - }, - { - commandName: "planCacheSetFilter", - run: { - inAPIVersion1: false, - shardCommandName: "planCacheSetFilter", - permittedInTxn: false, - command: () => - ({planCacheSetFilter: "collection", query: {_id: 1}, indexes: [{_id: 1}]}), - } - }, - {commandName: "profile", skip: "not supported in mongos"}, - {commandName: "reapLogicalSessionCacheNow", skip: "is a no-op on mongos"}, - { - commandName: "refineCollectionShardKey", - run: { - inAPIVersion1: false, - configServerCommandName: "_configsvrRefineCollectionShardKey", - runsAgainstAdminDb: true, - permittedInTxn: false, - requiresShardedCollection: true, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({ - createIndexes: "collection", - indexes: [{key: {_id: 1, x: 1}, name: "_id-1-x-1"}] - })), - command: () => ({refineCollectionShardKey: "db.collection", key: {_id: 1, x: 1}}) - } - }, - { - commandName: "refreshLogicalSessionCacheNow", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "refreshSessions", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "removeShard", - run: { - inAPIVersion1: false, - runsAgainstAdminDb: true, - configServerCommandName: "_configsvrRemoveShard", - permittedInTxn: false, - command: () => ({removeShard: st.shard0.shardName}), - cleanUp: () => { - // Wait for the shard to be removed completely before re-adding it. - awaitRemoveShard(st.shard0.shardName); - assert.commandWorked(st.s0.getDB("admin").runCommand( - {addShard: st.rs0.getURL(), name: st.shard0.shardName})); - } - } - }, - { - commandName: "removeShardFromZone", - run: { - inAPIVersion1: false, - runsAgainstAdminDb: true, - configServerCommandName: "_configsvrRemoveShardFromZone", - permittedInTxn: false, - setup: () => - assert.commandWorked({addShardToZone: st.shard0.shardName, zone: "foo"}), - command: () => ({removeShardFromZone: st.shard0.shardName, zone: "foo"}) - } - }, - { - commandName: "renameCollection", - run: { - inAPIVersion1: false, - shardCommandName: "renameCollection", - permittedOnShardedCollection: false, - permittedInTxn: false, - runsAgainstAdminDb: true, - command: () => ({renameCollection: "db.collection", to: "db.collection_renamed"}) - } - }, - {commandName: "replSetGetStatus", skip: "not supported in mongos"}, - { - commandName: "resetError", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "reshardCollection", - run: { - inAPIVersion1: false, - permittedInTxn: false, - configServerCommandName: "_configsvrReshardCollection", - requiresShardedCollection: true, - runsAgainstAdminDb: true, - command: () => ({reshardCollection: "db.collection", key: {_id: 1}}) - } - }, - { - commandName: "revokePrivilegesFromRole", - run: { - inAPIVersion1: false, - permittedInTxn: false, - configServerCommandName: "revokePrivilegesFromRole", - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({ - createRole: "foo", - privileges: - [{resource: {db: "db", collection: "collection"}, actions: ["find"]}], - roles: [], - writeConcern: {w: 1} - })), - command: () => ({ - revokePrivilegesFromRole: "foo", - privileges: - [{resource: {db: "db", collection: "collection"}, actions: ["find"]}] - }), - cleanUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})); - } - } - }, - { - commandName: "revokeRolesFromRole", - run: { - inAPIVersion1: false, - permittedInTxn: false, - configServerCommandName: "revokeRolesFromRole", - setUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "bar", privileges: [], roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {grantRolesToRole: "foo", roles: [{role: "bar", db: "db"}]})); - }, - command: () => ({revokeRolesFromRole: "foo", roles: [{role: "bar", db: "db"}]}), - cleanUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})); - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "bar"})); - } - } - }, - { - commandName: "revokeRolesFromUser", - run: { - inAPIVersion1: false, - configServerCommandName: "revokeRolesFromUser", - permittedInTxn: false, - setUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand( - {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})); - assert.commandWorked(st.s0.getDB("db").runCommand( - {grantRolesToUser: "foo", roles: [{role: "foo", db: "db"}]})); - }, - command: () => ({revokeRolesFromUser: "foo", roles: [{role: "foo", db: "db"}]}), - cleanUp: () => { - assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"})); - assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})); - } - } - }, - { - commandName: "rolesInfo", - run: { - inAPIVersion1: false, - configServerCommandName: "rolesInfo", - permittedInTxn: false, - command: () => ({rolesInfo: 1}) - } - }, - { - commandName: "rotateCertificates", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "saslContinue", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "saslStart", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "serverStatus", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "setDefaultRWConcern", - run: { - inAPIVersion1: false, - configServerCommandName: "setDefaultRWConcern", - runsAgainstAdminDb: true, - permittedInTxn: false, - command: () => ({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}}) - } - }, - { - commandName: "setIndexCommitQuorum", - run: { - inAPIVersion1: false, - shardCommandName: "setIndexCommitQuorum", - permittedInTxn: false, - command: () => ({ - setIndexCommitQuorum: "collection", - indexNames: ["index"], - commitQuorum: "majority" - }), - } - }, - { - commandName: "setFeatureCompatibilityVersion", - run: { - inAPIVersion1: false, - configServerCommandName: "setFeatureCompatibilityVersion", - permittedInTxn: false, - runsAgainstAdminDb: true, - command: () => ({setFeatureCompatibilityVersion: latestFCV}) - } - }, - { - commandName: "setFreeMonitoring", - skip: "explicitly fails for mongos, primary mongod only", - conditional: true - }, - { - commandName: "setParameter", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "shardCollection", - run: { - inAPIVersion1: false, - configServerCommandName: "_configsvrShardCollection", - shardCommandName: "_shardsvrShardCollection", - runsAgainstAdminDb: true, - permittedInTxn: false, - permittedOnShardedCollection: false, - setUp: () => { - assert.commandWorked(st.s.adminCommand({enableSharding: "db"})); - st.ensurePrimaryShard("db", st.shard0.shardName); - }, - command: () => ({shardCollection: "db.collection", key: {_id: 1}}) - } - }, - { - commandName: "shardConnPoolStats", - skip: "executes locally on mongos (not sent to any remote node)" - }, - {commandName: "shutdown", skip: "executes locally on mongos (not sent to any remote node)"}, - { - commandName: "split", - run: { - inAPIVersion1: false, - configServerCommandName: "_configsvrCommitChunkSplit", - shardCommandName: "splitChunk", - runsAgainstAdminDb: true, - permittedInTxn: false, - requiresShardedCollection: true, - command: () => ({split: "db.collection", middle: {_id: 5}}) - } - }, - { - commandName: "splitVector", - run: { - inAPIVersion1: false, - shardCommandName: "splitVector", - permittedInTxn: false, - permittedOnShardedCollection: false, - command: () => ({ - splitVector: "db.collection", - keyPattern: {_id: 1}, - min: {_id: 0}, - max: {_id: MaxKey}, - maxChunkSizeBytes: 1024 - }) - } - }, - { - commandName: "startRecordingTraffic", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "startSession", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "stopRecordingTraffic", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "testDeprecation", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "testDeprecationInVersion2", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "testRemoval", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "testVersion2", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "testVersions1And2", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "update", - run: { - inAPIVersion1: true, - shardCommandName: "update", - command: () => ({ - update: "collection", - updates: [{q: {_id: 2}, u: {_id: 2}, upsert: true, multi: false}] - }), - }, - explain: { - inAPIVersion1: true, - shardCommandName: "explain", - permittedInTxn: false, - command: () => ({ - explain: { - update: "collection", - updates: [{q: {_id: 2}, u: {_id: 2}, upsert: true, multi: false}] - } - }), - } - }, - { - commandName: "updateRole", - run: { - inAPIVersion1: false, - configServerCommandName: "updateRole", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})), - command: () => ({updateRole: "foo", authenticationRestrictions: []}), - cleanUp: () => assert.commandWorked( - st.s0.getDB("db").runCommand({dropAllRolesFromDatabase: 1})) - } - }, - { - commandName: "updateUser", - run: { - inAPIVersion1: false, - configServerCommandName: "updateUser", - permittedInTxn: false, - setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand( - {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})), - command: () => ({updateUser: "foo", authenticationRestrictions: []}), - cleanUp: () => assert.commandWorked( - st.s0.getDB("db").runCommand({dropAllUsersFromDatabase: 1})) - } - }, - { - commandName: "updateZoneKeyRange", - run: { - inAPIVersion1: false, - configServerCommandName: "_configsvrUpdateZoneKeyRange", - permittedInTxn: false, - runsAgainstAdminDb: true, - setUp: () => assert.commandWorked(st.s0.getDB("admin").runCommand( - {addShardToZone: st.shard0.shardName, zone: "foo"})), - command: () => ({ - updateZoneKeyRange: "db.collection", - min: {_id: 1}, - max: {_id: 5}, - zone: "foo" - }), - cleanUp: () => { - // Remove zone key range. - assert.commandWorked(st.s0.getDB("admin").runCommand({ - updateZoneKeyRange: "db.collection", - min: {_id: 1}, - max: {_id: 5}, - zone: null - })); - assert.commandWorked(st.s0.getDB("admin").runCommand( - {removeShardFromZone: st.shard0.shardName, zone: "foo"})); - } - } - }, - { - commandName: "usersInfo", - run: { - inAPIVersion1: false, - configServerCommandName: "usersInfo", - permittedInTxn: false, - command: () => ({usersInfo: 1}) - } - }, - { - commandName: "validate", - run: { - inAPIVersion1: false, - shardCommandName: "validate", - permittedInTxn: false, - command: () => ({validate: "collection"}), - } - }, - { - commandName: "waitForFailPoint", - skip: "executes locally on mongos (not sent to any remote node)" - }, - { - commandName: "whatsmyuri", - skip: "executes locally on mongos (not sent to any remote node)" - }, - ]; - - commandsRemovedFromMongosSinceLastLTS.forEach(function(cmd) { - testCases[cmd] = { - skip: "must define test coverage for latest version backwards compatibility" - }; - }); - - const st = new ShardingTest({mongos: 1, shards: 2, rs: {nodes: 1}}); - const listCommandsRes = st.s0.adminCommand({listCommands: 1}); - assert.commandWorked(listCommandsRes); - - (() => { - // Validate test cases for all commands. Ensure there is at least one test case for every - // mongos command, and that the test cases are well formed. - for (const command of Object.keys(listCommandsRes.commands)) { - const matchingCases = testCases.filter(elem => elem.commandName === command); - assert(matchingCases !== [], - "coverage failure: must define a test case for " + command); - for (const testCase of matchingCases) { - validateTestCase(testCase); - testCase.validated = true; - } - } - - // After iterating through all the existing commands, ensure there were no additional test - // cases that did not correspond to any mongos command. - for (const testCase of testCases) { - // We have defined real test cases for commands added since the last LTS version so that - // the test cases are exercised in the regular suites, but because these test cases - // can't run in the last stable suite, we skip processing them here to avoid failing the - // below assertion. We have defined "skip" test cases for commands removed since the - // last LTS version so the test case is defined in last stable suites (in which these - // commands still exist on the mongos), but these test cases won't be run in regular - // suites, so we skip processing them below as well. - if (commandsAddedToMongosSinceLastLTS.includes(testCase.commandName) || - commandsRemovedFromMongosSinceLastLTS.includes(testCase.commandName)) - continue; - assert(testCase.validated || testCase.conditional, - "you defined a test case for a command '" + testCase.commandName + - "' that does not exist on mongos: " + tojson(testCase)); - } - })(); - - function checkPrimaryLog(conn, commandName, apiVersion, apiStrict, apiDeprecationErrors) { - const logs = checkLog.getGlobalLog(conn); - let lastCommandInvocation; - - for (let logMsg of logs) { - const obj = JSON.parse(logMsg); - // Search for "About to run the command" logs. - if (obj.id !== 21965) - continue; - - const args = obj.attr.commandArgs; - if (commandName !== Object.keys(args)[0]) - continue; - - lastCommandInvocation = args; - if (args.apiVersion !== apiVersion || args.apiStrict !== apiStrict || - args.apiDeprecationErrors !== apiDeprecationErrors) - continue; - - // Found a match. - return; - } - - if (lastCommandInvocation === undefined) { - doassert(`Primary didn't log ${commandName}`); - return; - } - - doassert(`Primary didn't log ${commandName} with apiVersion ${apiVersion},` + - ` apiStrict ${apiStrict},` + - ` apiDeprecationErrors ${apiDeprecationErrors}.` + - ` Last invocation of ${commandName} was` + - ` ${tojson(lastCommandInvocation)}`); - } - - function runTests({inTransaction, shardedCollection}) { - // For each combination of config parameters and test case, create a test instance. Do this - // before executing the test instances so we can count the number of instances and log - // progress. - let testInstances = []; - - for (const [apiVersion, apiStrict, apiDeprecationErrors] of [ - [undefined, undefined, undefined], - ["1", undefined, undefined], - ["1", undefined, false], - ["1", undefined, true], - ["1", false, undefined], - ["1", false, false], - ["1", false, true], - ["1", true, undefined], - ["1", true, false], - ["1", true, true], - ]) { - for (const testCase of testCases) { - if (testCase.skip) - continue; - - for (let runOrExplain of [testCase.run, testCase.explain]) { - if (runOrExplain === undefined) - continue; - - if (inTransaction && !runOrExplain.permittedInTxn) - continue; - - if (shardedCollection && !runOrExplain.permittedOnShardedCollection) - continue; - - if (!shardedCollection && runOrExplain.requiresShardedCollection) - continue; - - if (apiStrict && !runOrExplain.inAPIVersion1) - continue; - - testInstances.push({ - apiVersion: apiVersion, - apiStrict: apiStrict, - apiDeprecationErrors: apiDeprecationErrors, - commandName: testCase.commandName, - runOrExplain: runOrExplain - }); - } - } - } - - for (let i = 0; i < testInstances.length; ++i) { - const {apiVersion, apiStrict, apiDeprecationErrors, commandName, runOrExplain} = - testInstances[i]; - - if (shardedCollection) { - jsTestLog("Sharded setup"); - assert.commandWorked(st.s.getDB("db")["collection"].insert( - {_id: 0}, {writeConcern: {w: "majority"}})); - assert.commandWorked(st.s.getDB("db")["collection"].insert( - {_id: 20}, {writeConcern: {w: "majority"}})); - - assert.commandWorked(st.s.adminCommand({enableSharding: "db"})); - st.ensurePrimaryShard("db", st.shard0.shardName); - assert.commandWorked( - st.s.adminCommand({shardCollection: "db.collection", key: {_id: 1}})); - - // The chunk with _id 1 is on shard 0. - assert.commandWorked( - st.s.adminCommand({split: "db.collection", middle: {_id: 10}})); - assert.commandWorked(st.s.adminCommand({ - moveChunk: "db.collection", - find: {_id: 20}, - to: st.shard1.shardName, - _waitForDelete: true - })); - } else { - jsTestLog("Unsharded setup"); - assert.commandWorked(st.s.getDB("db")["collection"].insert( - {_id: 0}, {writeConcern: {w: "majority"}})); - st.ensurePrimaryShard("db", st.shard0.shardName); - } - - const configPrimary = st.configRS.getPrimary(); - const shardZeroPrimary = st.rs0.getPrimary(); - const context = {}; - - if (runOrExplain.setUp) { - jsTestLog(`setUp function for ${commandName}`); - runOrExplain.setUp(context); - jsTestLog(`setUp function for ${commandName} completed`); - } - - // Make a copy of the test's command body, and set its API parameters. - const commandDbName = runOrExplain.runsAgainstAdminDb ? "admin" : "db"; - const commandBody = runOrExplain.command(context); - const commandWithAPIParams = Object.assign({}, commandBody); - if (apiVersion !== undefined) { - commandWithAPIParams.apiVersion = apiVersion; - } - - if (apiStrict !== undefined) { - commandWithAPIParams.apiStrict = apiStrict; - } - - if (apiDeprecationErrors !== undefined) { - commandWithAPIParams.apiDeprecationErrors = apiDeprecationErrors; - } - - assert.commandWorked(configPrimary.adminCommand({clearLog: "global"})); - assert.commandWorked(shardZeroPrimary.adminCommand({clearLog: "global"})); - const message = - `[${i + 1} of ${testInstances.length}]: command ${tojson(commandWithAPIParams)}` + - ` ${shardedCollection ? "sharded" : "unsharded"},` + - ` ${inTransaction ? "in" : "outside"} transaction` + - ` on "${commandDbName}" database`; - - flushRoutersAndRefreshShardMetadata(st, {ns: "db.collection"}); - - jsTestLog(`Running ${message}`); - setLogVerbosity([configPrimary, shardZeroPrimary], {"command": {"verbosity": 2}}); - - if (inTransaction) { - const session = st.s0.startSession(); - const sessionDb = session.getDatabase(commandDbName); - session.startTransaction(); - assert.commandWorked(sessionDb.runCommand(commandWithAPIParams)); - assert.commandWorked(session.commitTransaction_forTesting()); - } else { - const db = st.s0.getDB(commandDbName); - assert.commandWorked(db.runCommand(commandWithAPIParams)); - } - - setLogVerbosity([configPrimary, shardZeroPrimary], {"command": {"verbosity": 0}}); - - const configServerCommandName = runOrExplain.configServerCommandName; - const shardCommandName = runOrExplain.shardCommandName; - - if (configServerCommandName) { - jsTestLog(`Check for ${configServerCommandName} in config server's log`); - checkPrimaryLog(configPrimary, - configServerCommandName, - apiVersion, - apiStrict, - apiDeprecationErrors); - } - - if (shardCommandName) { - jsTestLog(`Check for ${shardCommandName} in shard server's log`); - checkPrimaryLog(shardZeroPrimary, - shardCommandName, - apiVersion, - apiStrict, - apiDeprecationErrors); - } - - st.s0.getDB("db").runCommand({dropDatabase: 1}); - if (runOrExplain.cleanUp) { - jsTestLog(`cleanUp function for ${commandName}`); - runOrExplain.cleanUp(context); - jsTestLog(`cleanUp function for ${commandName} completed`); - } - } - - st.stop(); - } - - return {runTests: runTests}; -})(); |