Files
mongo/jstests/multiVersion/libs/dumprestore_helpers.js

251 lines
9.6 KiB
JavaScript

// dumprestore_helpers.js
load( './jstests/multiVersion/libs/verify_collection_data.js' )
// Given a "test spec" object, runs the specified test.
//
// The "test spec" object has the format:
//
// {
// 'serverSourceVersion' : "latest",
// 'serverDestVersion' : "2.4",
// 'mongoDumpVersion' : "2.2",
// 'mongoRestoreVersion' : "latest",
// 'dumpDir' : dumpDir,
// 'testDbpath' : testDbpath,
// 'dumpType' : "mongos",
// 'restoreType' : "mongod" // "mongos" also supported
// }
//
// The first four fields are which versions of the various binaries to use in the test.
//
// The "dumpDir" field is the external directory to use as scratch space for database dumps.
//
// The "testDbpath" is the external directory to use as the server dbpath directory.
//
// For the "dumpType" and "restoreType" fields, the following values are supported:
// - "mongod" - Do the dump or restore by connecting to a single mongod node
// - "mongos" - Do the dump or restore by connecting to a sharded cluster
//
function multiVersionDumpRestoreTest(configObj) {
// First sanity check the arguments in our configObj
var requiredKeys = [
'serverSourceVersion',
'serverDestVersion',
'mongoDumpVersion',
'mongoRestoreVersion',
'dumpDir',
'testDbpath',
'dumpType',
'restoreType'
]
var i;
for (i = 0; i < requiredKeys.length; i++) {
assert(configObj.hasOwnProperty(requiredKeys[i]),
"Missing required key: " + requiredKeys[i] + " in config object");
}
resetDbpath(configObj.dumpDir);
resetDbpath(configObj.testDbpath);
if (configObj.dumpType === "mongos") {
var shardingTestConfig = {
sync: true, // Mixed version clusters can't use replsets for config servers
name : testBaseName + "_sharded_source",
mongos : [{ binVersion : configObj.serverSourceVersion }],
shards : [{ binVersion : configObj.serverSourceVersion,
setParameter : "textSearchEnabled=true" }],
config : [{ binVersion : configObj.serverSourceVersion }]
}
var shardingTest = new ShardingTest(shardingTestConfig);
var serverSource = shardingTest.s;
}
else {
var serverSource = MongoRunner.runMongod({ binVersion : configObj.serverSourceVersion,
setParameter : "textSearchEnabled=true",
dbpath : configObj.testDbpath });
}
var sourceDB = serverSource.getDB(testBaseName);
// Create generators to create collections with our seed data
// Testing with both a capped collection and a normal collection
var cappedCollGen = new CollectionDataGenerator({ "capped" : true });
var collGen = new CollectionDataGenerator({ "capped" : false });
// Create collections using the different generators
var sourceCollCapped = createCollectionWithData(sourceDB, "cappedColl", cappedCollGen);
var sourceColl = createCollectionWithData(sourceDB, "coll", collGen);
// Record the current collection states for later validation
var cappedCollValid = new CollectionDataValidator();
cappedCollValid.recordCollectionData(sourceCollCapped);
var collValid = new CollectionDataValidator();
collValid.recordCollectionData(sourceColl);
// Dump using the specified version of mongodump from the running mongod or mongos instance.
if (configObj.dumpType === "mongod") {
MongoRunner.runMongoTool("mongodump", { out : configObj.dumpDir,
binVersion : configObj.mongoDumpVersion,
host : serverSource.host,
db : testBaseName });
MongoRunner.stopMongod(serverSource.port);
}
else { /* "mongos" */
MongoRunner.runMongoTool("mongodump", { out : configObj.dumpDir,
binVersion : configObj.mongoDumpVersion,
host : serverSource.host,
db : testBaseName });
shardingTest.stop();
}
// Restore using the specified version of mongorestore
if (configObj.restoreType === "mongod") {
var serverDest = MongoRunner.runMongod({ binVersion : configObj.serverDestVersion,
setParameter : "textSearchEnabled=true" });
MongoRunner.runMongoTool("mongorestore", { dir : configObj.dumpDir + "/" + testBaseName,
binVersion : configObj.mongoRestoreVersion,
host : serverDest.host,
db : testBaseName });
}
else { /* "mongos" */
var shardingTestConfig = {
sync: true, // Mixed version clusters can't use replsets for config servers
name : testBaseName + "_sharded_dest",
mongos : [{ binVersion : configObj.serverDestVersion }],
shards : [{ binVersion : configObj.serverDestVersion,
setParameter : "textSearchEnabled=true" }],
config : [{ binVersion : configObj.serverDestVersion }]
}
var shardingTest = new ShardingTest(shardingTestConfig);
serverDest = shardingTest.s;
MongoRunner.runMongoTool("mongorestore", { dir : configObj.dumpDir + "/" + testBaseName,
binVersion : configObj.mongoRestoreVersion,
host : serverDest.host,
db : testBaseName });
}
var destDB = serverDest.getDB(testBaseName);
// Get references to our destinations collections
// XXX: These are in the global scope (no "var"), but they need to be global to be in scope for
// the "assert.soon" calls below.
destColl = destDB.getCollection("coll");
destCollCapped = destDB.getCollection("cappedColl");
// Wait until we actually have data or timeout
assert.soon("destColl.findOne()", "no data after sleep");
assert.soon("destCollCapped.findOne()", "no data after sleep");
// Validate that our collections were properly restored
assert(collValid.validateCollectionData(destColl));
assert(cappedCollValid.validateCollectionData(destCollCapped));
if (configObj.restoreType === "mongos") {
shardingTest.stop();
}
else {
MongoRunner.stopMongod(serverDest.port);
}
}
// Given an object with list values, returns a cursor that returns an object for every combination
// of selections of the values in the lists.
//
// Usage:
// var permutationCursor = getPermutationIterator({"a":[0,1], "b":[2,3]});
// while (permutationCursor.hasNext()) {
// var permutation = permutationCursor.next();
// printjson(permutation);
// }
//
// This will print:
//
// { "a" : 0, "b" : 2 }
// { "a" : 1, "b" : 2 }
// { "a" : 0, "b" : 3 }
// { "a" : 1, "b" : 3 }
function getPermutationIterator(permsObj) {
function getAllPermutations(permsObj) {
// Split our permutations object into "first" and "rest"
var gotFirst = false;
var firstKey;
var firstValues;
var restObj = {};
for (var key in permsObj) {
if (permsObj.hasOwnProperty(key)) {
if (gotFirst) {
restObj[key] = permsObj[key];
}
else {
firstKey = key;
firstValues = permsObj[key];
gotFirst = true;
}
}
}
// Our base case is an empty object, which just has a single permutation, "{}"
if (!gotFirst) {
return [{}];
}
// Iterate the possibilities for "first" and for each one recursively get all the
// permutations for "rest"
var resultPermObjs = [];
var i = 0;
var j = 0;
for (i = 0; i < firstValues.length; i++) {
var subPermObjs = getAllPermutations(restObj);
for (j = 0; j < subPermObjs.length; j++) {
subPermObjs[j][firstKey] = firstValues[i];
resultPermObjs.push(subPermObjs[j]);
}
}
return resultPermObjs;
}
var allPermutations = getAllPermutations(permsObj);
var currentPermutation = 0;
return {
"next" : function () {
return allPermutations[currentPermutation++];
},
"hasNext" : function () {
return currentPermutation < allPermutations.length;
}
}
}
// Given a "test spec" object, runs all test combinations.
//
// The "test spec" object has the format:
//
// {
// 'serverSourceVersion' : [ "latest", "2.4" ],
// 'serverDestVersion' :[ "latest", "2.4" ],
// 'mongoDumpVersion' :[ "latest", "2.4" ],
// 'mongoRestoreVersion' :[ "latest", "2.4" ],
// 'dumpDir' : [ dumpDir ],
// 'testDbpath' : [ testDbpath ],
// 'dumpType' : [ "mongod", "mongos" ],
// 'restoreType' : [ "mongod", "mongos" ]
// }
//
// This function will run a test for each possible combination of the parameters. See comments on
// "getPermutationIterator" above.
function runAllDumpRestoreTests(testCasePermutations) {
var testCaseCursor = getPermutationIterator(testCasePermutations);
while (testCaseCursor.hasNext()) {
var testCase = testCaseCursor.next();
print("Running multiversion mongodump mongorestore test:");
printjson(testCase);
multiVersionDumpRestoreTest(testCase);
}
}