mongo/jstests/multiVersion/keystring_index.js

291 lines
9.7 KiB
JavaScript

/**
* Regression test that runs validate to test KeyString changes across 4.2 and the current
* version as specified in SERVER-41908.
*
* - First, start mongod in 4.2.
* - For each index create a new collection in testDb, inserting documents and finally an index is
* created.
* - After all indexes and collections are added, shutdown mongod.
* - Restart the database as the current version.
* - Run Validate.
* - Remove all collections.
* - Recreate all the indexes.
* - Shuwdown mongod.
* - Restart mongod in 4.2.
* - Run Validate.
*
*
* The following index types are tested:
* - btree
* - 2d
* - geoHaystack
* - 2dsphere
* - text
* - *hashed
* - *wildcard
* * these indexes are only created as v2 non-unique because they are not available unique or in v1
*
* For each index type, a v1 unique, v2 unique, v1 non-unique and v2 non-unique index
* is considered except for hashed and wildcard, which only consider the v2 non-unique case.
*/
(function() {
'use strict';
load('jstests/hooks/validate_collections.js');
// ----- Config
// The number of documents created for each collection
const numDocs = 100;
const indexTypes = [
{
// an indicator of what the index is
indexName: "BTreeIndex",
// This function is called to create documents, which are then inserted into the
// collection.
createDoc: i => ({
a: i,
b: {x: i, y: i + 1},
c: [i, i + 1],
}),
// the options given to the .createIndex method
// i.e. collection.createIndex(creationOptions)
creationOptions: {a: 1, b: 1, c: -1},
// This optional parameter specifies extra options to give to createIndex.
// In the code, collection.createIndexes(creationOptions, createIndexOptions)
// is called.
createIndexOptions: {}
},
{indexName: "2d", createDoc: i => ({loc: [i, i]}), creationOptions: {loc: "2d"}},
{
indexName: "hayStack",
createDoc: i => ({
loc: {lng: (i / 2.0) * (i / 2.0), lat: (i / 2.0)},
a: {x: i, y: i + 1, z: [i, i + 1]},
}),
creationOptions: {loc: "geoHaystack", a: 1},
createIndexOptions: {bucketSize: 1}
},
{
indexName: "2dSphere",
createDoc: i => {
if (i == 0)
return {
"loc": {
"type": "Polygon",
"coordinates": [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]]
},
b: {x: i, y: i + 1},
c: [i, i + 1],
};
else
return ({
loc: {type: "Point", coordinates: [(i / 10.0) * (i / 10.0), (i / 10.0)]},
b: {x: i, y: i + 1},
c: [i, i + 1],
});
},
creationOptions: {loc: "2dsphere", b: 1, c: -1}
},
{
indexName: "text",
createDoc: i => ({
a: "a".repeat(i + 1),
b: {x: i, y: i + 1, z: [i, i + 1]},
}),
creationOptions: {a: "text", b: 1}
},
{
indexName: "hashed",
createDoc: i => ({
a: {x: i, y: i + 1, z: [i, i + 1]},
}),
creationOptions: {a: "hashed"}
},
{
indexName: "wildCard",
createDoc: i => {
if (i == 0)
return {};
else if (i == 1)
return {a: null};
else if (i == 2)
return {a: {}};
else
return {
a: i,
b: {x: i, y: i + 1},
c: [i, i + 1],
};
},
creationOptions: {"$**": 1}
}
];
// -----
const dbpath = MongoRunner.dataPath + 'keystring_index';
resetDbpath(dbpath);
const defaultOptions = {
dbpath: dbpath,
noCleanData: true
};
const testCollection = 'testColl';
let mongodOptions42 = Object.extend({binVersion: '4.2'}, defaultOptions);
let mongodOptionsCurrent = Object.extend({binVersion: 'latest'}, defaultOptions);
// We will first start up an old binary version database, populate the database,
// then upgrade and validate.
// Start up an old binary version mongod.
jsTestLog("Starting version: 4.2");
let conn = MongoRunner.runMongod(mongodOptions42);
assert.neq(null, conn, 'mongod was unable able to start with version ' + tojson(mongodOptions42));
let testDb = conn.getDB('test');
assert.neq(null, testDb, 'testDb not found. conn.getDB(\'test\') returned null');
populateDb(testDb);
MongoRunner.stopMongod(conn);
jsTestLog("Starting version: latest");
// Restart the mongod with the latest binary version on the old version's data files.
conn = MongoRunner.runMongod(mongodOptionsCurrent);
assert.neq(null, conn, 'mongod was unable to start with the latest version');
testDb = conn.getDB('test');
assert.neq(null, testDb, 'testDb not found');
jsTestLog("Validating: 4.2 indexes with latest");
// Validate all the indexes.
assert.commandWorked(validateCollections(testDb, {full: true}));
// Next, we will repopulate the database with the latest version then downgrade and run
// validate.
dropAllUserCollections(testDb);
populateDb(testDb);
MongoRunner.stopMongod(conn);
conn = MongoRunner.runMongod(mongodOptions42);
assert.neq(null, conn, 'mongod was unable able to start with version ' + tojson(mongodOptions42));
testDb = conn.getDB('test');
assert.neq(null, testDb, 'testDb not found. conn.getDB(\'test\') returned null');
jsTestLog("Validating: latest indexes with 4.2");
assert.commandWorked(validateCollections(testDb, {full: true}));
MongoRunner.stopMongod(conn);
// ----------------- Utilities
// Populate the database using the config specified by the indexTypes array.
function populateDb(testDb) {
// Create a new collection and index for each indexType in the array.
for (let i = 0; i < indexTypes.length; i++) {
const indexOptions = indexTypes[i];
// Try unique and non-unique.
for (const unique in [true, false]) {
// Try index-version 1 and 2.
for (let indexVersion = 1; indexVersion <= 2; indexVersion++) {
let indexName = indexOptions.indexName;
// We only run V2 non-unique for hashed and wildCard because they don't exist in
// v1.
if ((indexName == "hashed" || indexName == "wildCard") &&
(unique == true || indexVersion == 1))
continue;
indexName += unique == true ? "Unique" : "NotUnique";
indexName += `Version${indexVersion}`;
let collectionName = testCollection + '_' + indexName;
print(`${indexName}: Creating Collection`);
assert.commandWorked(testDb.createCollection(collectionName));
print(`${indexName}: Inserting Documents`);
if (unique)
insertDocumentsUnique(testDb[collectionName], numDocs, indexOptions.createDoc);
else
insertDocumentsNotUnique(
testDb[collectionName], numDocs, indexOptions.createDoc);
let extraCreateIndexOptions = {
name: indexName,
v: indexVersion,
unique: unique == true
};
if ("createIndexOptions" in indexOptions)
extraCreateIndexOptions =
Object.extend(extraCreateIndexOptions, indexOptions.createIndexOptions);
print(JSON.stringify(extraCreateIndexOptions));
print(`${indexName}: Creating Index`);
assert.commandWorked(testDb[collectionName].createIndex(
indexOptions.creationOptions, extraCreateIndexOptions));
// Assert that the correct index type was created.
let indexSpec = getIndexSpecByName(testDb[collectionName], indexName);
assert.eq(indexVersion, indexSpec.v, tojson(indexSpec));
}
}
}
}
// Drop all user created collections in a database.
function dropAllUserCollections(testDb) {
testDb.getCollectionNames().forEach((collName) => {
if (!collName.startsWith("system.")) {
testDb[collName].drop();
}
});
}
function getIndexSpecByName(coll, indexName) {
const indexes = coll.getIndexes();
const indexesFilteredByName = indexes.filter(spec => spec.name === indexName);
assert.eq(
1, indexesFilteredByName.length, "index '" + indexName + "' not found: " + tojson(indexes));
return indexesFilteredByName[0];
}
function fibonacci(num, memo) {
memo = memo || {};
if (memo[num])
return memo[num];
if (num <= 1)
return 1;
memo[num] = fibonacci(num - 1, memo) + fibonacci(num - 2, memo);
return memo[num];
}
// Insert numDocs documents into the collection by calling getDoc.
// NOTE: Documents returned from getDoc are inserted more than once.
function insertDocumentsNotUnique(collection, numDocs, getDoc) {
let fibNum = 0;
// fibonacci numbers are used because the fibonnaci sequence is a
// exponentially growing sequence that allows us to create documents
// that are duplicated X number of times, for many small values of X and
// a few large values of X.
for (let i = 0; i < numDocs; i += fibonacci(fibNum++)) {
let doc = getDoc(i);
for (let j = 0; j < fibonacci(fibNum); j++) {
assert.commandWorked(collection.insert(doc));
}
}
}
// Inserts numDocs into the collection by calling getDoc.
// NOTE: getDoc is called exactly numDocs times.
function insertDocumentsUnique(collection, numDocs, getDoc) {
for (let i = 0; i < numDocs; i++) {
let doc = getDoc(i);
assert.commandWorked(collection.insert(doc));
}
}
})();