Files
mongo/jstests/core/mr_killop.js
Max Hirschhorn 9ad8d6335f SERVER-40076 Tag JS tests with reason they're unable to run in Atlas.
There are likely more JavaScript tests which have been added since
r3.6.9 that still need to be tagged.

(cherry picked from commit 05ec08fa62)
2019-03-11 18:17:29 -04:00

200 lines
5.9 KiB
JavaScript

// Cannot implicitly shard accessed collections because the "command" field in the currentOp()
// output is reported as {"mapreduce.shardedfinish": { mapreduce: "jstests_mr_killop", ... }, ... }
// when the "finalize" option to the "mapReduce" command is used on a sharded collection.
// @tags: [
// assumes_unsharded_collection,
// does_not_support_stepdowns,
// uses_multiple_connections,
// ]
// Test killop applied to m/r operations and child ops of m/r operations.
t = db.jstests_mr_killop;
t.drop();
t2 = db.jstests_mr_killop_out;
t2.drop();
db.adminCommand({"configureFailPoint": 'mr_killop_test_fp', "mode": 'alwaysOn'});
function debug(x) {
// printjson( x );
}
/** @return op code for map reduce op created by spawned shell, or that op's child */
function op(childLoop) {
p = db.currentOp().inprog;
debug(p);
let isMapReduce = function(op) {
if (!op.command) {
return false;
}
let cmdBody = op.command;
if (cmdBody.$truncated) {
let stringifiedCmd = cmdBody.$truncated;
print('str: ' + tojson(stringifiedCmd));
return stringifiedCmd.search('mapreduce') >= 0 &&
stringifiedCmd.search('jstests_mr_killop') >= 0;
}
return cmdBody.mapreduce && cmdBody.mapreduce == "jstests_mr_killop";
};
for (var i in p) {
var o = p[i];
// Identify a map/reduce or where distinct operation by its collection, whether or not
// it is currently active.
if (childLoop) {
if ((o.active || o.waitingForLock) && o.command && o.command.query &&
o.command.query.$where && o.command.distinct == "jstests_mr_killop") {
return o.opid;
}
} else {
if ((o.active || o.waitingForLock) && isMapReduce(o)) {
return o.opid;
}
}
}
return -1;
}
/**
* Run one map reduce with the specified parameters in a parallel shell, kill the
* map reduce op or its child op with killOp, and wait for the map reduce op to
* terminate.
* @param childLoop - if true, a distinct $where op is killed rather than the map reduce op.
* This is necessay for a child distinct $where of a map reduce op because child
* ops currently mask parent ops in currentOp.
*/
function testOne(map, reduce, finalize, scope, childLoop, wait) {
debug("testOne - map = " + tojson(map) + "; reduce = " + tojson(reduce) + "; finalize = " +
tojson(finalize) + "; scope = " + tojson(scope) + "; childLoop = " + childLoop +
"; wait = " + wait);
t.drop();
t2.drop();
// Ensure we have 2 documents for the reduce to run
t.save({a: 1});
t.save({a: 1});
spec = {mapreduce: "jstests_mr_killop", out: "jstests_mr_killop_out", map: map, reduce: reduce};
if (finalize) {
spec["finalize"] = finalize;
}
if (scope) {
spec["scope"] = scope;
}
// Windows shell strips all double quotes from command line, so use
// single quotes.
stringifiedSpec = tojson(spec).toString().replace(/\n/g, ' ').replace(/\"/g, "\'");
// The assert below won't be caught by this test script, but it will cause error messages
// to be printed.
var awaitShell =
startParallelShell("assert.commandWorked( db.runCommand( " + stringifiedSpec + " ) );");
if (wait) {
sleep(2000);
}
o = null;
assert.soon(function() {
o = op(childLoop);
return o != -1;
});
res = db.killOp(o);
debug("did kill : " + tojson(res));
// When the map reduce op is killed, the spawned shell will exit
var exitCode = awaitShell({checkExitSuccess: false});
assert.neq(0,
exitCode,
"expected shell to exit abnormally due to map-reduce execution being terminated");
debug("parallel shell completed");
assert.eq(-1, op(childLoop));
}
/** Test using wait and non wait modes */
function test(map, reduce, finalize, scope, childLoop) {
debug(" Non wait mode");
testOne(map, reduce, finalize, scope, childLoop, false);
debug(" Wait mode");
testOne(map, reduce, finalize, scope, childLoop, true);
}
/** Test looping in map and reduce functions */
function runMRTests(loop, childLoop) {
debug(" Running MR test - loop map function. no scope ");
test(loop, // map
function(k, v) {
return v[0];
}, // reduce
null, // finalize
null, // scope
childLoop);
debug(" Running MR test - loop reduce function ");
test(
function() {
emit(this.a, 1);
}, // map
loop, // reduce
null, // finalize
null, // scope
childLoop);
debug(" Running finalization test - loop map function. with scope ");
test(
function() {
loop();
}, // map
function(k, v) {
return v[0];
}, // reduce
null, // finalize
{loop: loop}, // scope
childLoop);
}
/** Test looping in finalize function */
function runFinalizeTests(loop, childLoop) {
debug(" Running finalization test - no scope ");
test(
function() {
emit(this.a, 1);
}, // map
function(k, v) {
return v[0];
}, // reduce
loop, // finalize
null, // scope
childLoop);
debug(" Running finalization test - with scope ");
test(
function() {
emit(this.a, 1);
}, // map
function(k, v) {
return v[0];
}, // reduce
function(a, b) {
loop();
}, // finalize
{loop: loop}, // scope
childLoop);
}
// Run inside server. No access to debug().
var loop = function() {
while (1) {
sleep(1000);
}
};
runMRTests(loop, false);
runFinalizeTests(loop, false);
db.adminCommand({"configureFailPoint": 'mr_killop_test_fp', "mode": 'off'});