diff options
author | Eddie Louie <eddie.louie@mongodb.com> | 2017-09-12 15:29:51 -0400 |
---|---|---|
committer | Eddie Louie <eddie.louie@mongodb.com> | 2017-09-27 15:20:44 -0400 |
commit | 8f39eb8fdcc9e99e278089894a3b024b2e6c3bc4 (patch) | |
tree | 7d84fc0ae0374e828ccf9f6fe1b4a1a53731373c /jstests/libs | |
parent | 522f7f7d36a4a71059dd2d5219c2a0f074dfd0a1 (diff) | |
download | mongo-8f39eb8fdcc9e99e278089894a3b024b2e6c3bc4.tar.gz |
SERVER-30959 Enforce session is present in session_jscore_passthrough.yml.
Override runCommand() and runCommandWithMetadata() to throw an error if
passed a command object without an lsid property.
Diffstat (limited to 'jstests/libs')
-rw-r--r-- | jstests/libs/override_methods/enable_sessions.js | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/jstests/libs/override_methods/enable_sessions.js b/jstests/libs/override_methods/enable_sessions.js index 026df752090..9e4954013a0 100644 --- a/jstests/libs/override_methods/enable_sessions.js +++ b/jstests/libs/override_methods/enable_sessions.js @@ -4,16 +4,19 @@ (function() { "use strict"; + var runCommandOriginal = Mongo.prototype.runCommand; + var runCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata; + var getDBOriginal = Mongo.prototype.getDB; + var sessionMap = new WeakMap(); + let sessionOptions = {}; if (typeof TestData !== "undefined" && TestData.hasOwnProperty("sessionOptions")) { sessionOptions = TestData.sessionOptions; } - const driverSession = db.getMongo().startSession(sessionOptions); - // Override the endSession function to be a no-op so fuzzer doesn't accidentally end the - // session. - driverSession.endSession = Function.prototype; + const driverSession = startSession(db.getMongo()); db = driverSession.getDatabase(db.getName()); + sessionMap.set(db.getMongo(), driverSession); var originalStartParallelShell = startParallelShell; startParallelShell = function(jsCode, port, noConnect) { @@ -28,4 +31,60 @@ return originalStartParallelShell(newCode, port, noConnect); }; + + function startSession(conn) { + const driverSession = conn.startSession(sessionOptions); + // Override the endSession function to be a no-op so fuzzer doesn't accidentally end the + // session. + driverSession.endSession = Function.prototype; + return driverSession; + } + + // Override the runCommand to check for any command obj that does not contain a logical session + // and throw an error. + function runCommandWithLsidCheck(conn, dbName, cmdObj, func, funcArgs) { + const cmdName = Object.keys(cmdObj)[0]; + + // If the command is in a wrapped form, then we look for the actual command object + // inside the query/$query object. + let cmdObjUnwrapped = cmdObj; + if (cmdName === "query" || cmdName === "$query") { + cmdObj[cmdName] = Object.assign({}, cmdObj[cmdName]); + cmdObjUnwrapped = cmdObj[cmdName]; + } + + if (!cmdObjUnwrapped.hasOwnProperty("lsid")) { + // TODO: SERVER-30848 fixes getMore requests to use a session in the mongo shell. + // Until that happens, we bypass throwing an error for getMore and only throw an error + // for other requests not using sessions. + if (cmdName !== "getMore") { + throw new Error("command object does not have session id: " + tojson(cmdObj)); + } + } + return func.apply(conn, funcArgs); + } + + Mongo.prototype.runCommand = function(dbName, commandObj, options) { + return runCommandWithLsidCheck(this, dbName, commandObj, runCommandOriginal, arguments); + }; + + Mongo.prototype.runCommandWithMetadata = function(dbName, metadata, commandObj) { + return runCommandWithLsidCheck( + this, dbName, commandObj, runCommandWithMetadataOriginal, arguments); + }; + + // Override the getDB to return a db object with the correct driverSession. We use a WeakMap + // to cache the session for each connection instance so we can retrieve the same session on + // subsequent calls to getDB. + Mongo.prototype.getDB = function(dbName) { + if (!sessionMap.has(this)) { + const session = startSession(this); + sessionMap.set(this, session); + } + + const db = getDBOriginal.apply(this, arguments); + db._session = sessionMap.get(this); + return db; + }; + })(); |