mirror of https://github.com/mongodb/mongo
291 lines
9.7 KiB
JavaScript
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));
|
|
}
|
|
}
|
|
})();
|