112 lines
4.5 KiB
JavaScript
112 lines
4.5 KiB
JavaScript
/*
|
|
* If a collection does not have an index on the _id field (because of the use of autoIndexId: false
|
|
* in 3.6), the latest version of MongoDB will build the missing index.
|
|
*
|
|
* Ensure that if an index cannot be built, MongoDB shuts down cleanly and allows for any duplicate
|
|
* documents to be deleted in the previous version.
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
load('jstests/libs/get_index_helpers.js');
|
|
|
|
const dbName = 'test';
|
|
const collName = 'collection_autoIndexId_false';
|
|
|
|
// Given a dbpath to a 3.6 server, attempt to upgrade to 4.0.
|
|
function upgrade36To40(dbpath) {
|
|
let conn = MongoRunner.runMongod({binVersion: '4.0', dbpath: dbpath, noCleanData: true});
|
|
assert.neq(null, conn, 'mongod was unable to start with version 4.0');
|
|
let adminDb = conn.getDB('admin');
|
|
assert.commandWorked(adminDb.runCommand({'setFeatureCompatibilityVersion': '4.0'}));
|
|
|
|
MongoRunner.stopMongod(conn);
|
|
}
|
|
|
|
// Given a dbpath to a 3.6 server, attempt to upgrade to latest.
|
|
// shouldPass determines whether or not the upgrade should be successful.
|
|
function upgrade40ToLatest(dbpath, shouldPass) {
|
|
if (shouldPass) {
|
|
let conn =
|
|
MongoRunner.runMongod({binVersion: 'latest', dbpath: dbpath, noCleanData: true});
|
|
assert.neq(null, conn, 'mongod failed to start with latest version');
|
|
|
|
// Ensure the _id index exists.
|
|
let testDb = conn.getDB(dbName);
|
|
let coll = testDb.getCollection(collName);
|
|
let spec = GetIndexHelpers.findByKeyPattern(coll.getIndexes(), {_id: 1});
|
|
assert.neq(null, spec);
|
|
|
|
MongoRunner.stopMongod(conn);
|
|
} else {
|
|
let conn = MongoRunner.runMongod(
|
|
{binVersion: 'latest', dbpath: dbpath, noCleanData: true, waitForConnect: false});
|
|
|
|
// This tests that the server shuts down cleanly despite the inability to build the _id
|
|
// index.
|
|
assert.eq(MongoRunner.EXIT_NEED_DOWNGRADE, waitProgram(conn.pid));
|
|
}
|
|
}
|
|
|
|
// Create a collection with autoIndexId: false on a 3.6 server and assert that an upgrade to
|
|
// latest fails because there are duplicate values for the _id index.
|
|
function cannotUpgradeWithDuplicateIds() {
|
|
let conn = MongoRunner.runMongod({binVersion: '3.6'});
|
|
assert.neq(null, conn, 'mongod was unable able to start with version 3.6');
|
|
|
|
const dbpath = conn.dbpath;
|
|
|
|
// Create a collection with autoIndexId: false.
|
|
let testDb = conn.getDB(dbName);
|
|
let coll = testDb.getCollection(collName);
|
|
assert.commandWorked(coll.runCommand('create', {autoIndexId: false}));
|
|
assert.commandWorked(coll.insert({_id: 0, a: 1}));
|
|
assert.commandWorked(coll.insert({_id: 0, a: 2}));
|
|
MongoRunner.stopMongod(conn);
|
|
|
|
// The upgrade to 4.0 should always succeed because it does not care about the _id index.
|
|
upgrade36To40(dbpath);
|
|
|
|
let shouldPass = false;
|
|
upgrade40ToLatest(dbpath, shouldPass);
|
|
|
|
// Remove the duplicate (now in 4.0) and retry the upgrade to 4.2.
|
|
conn = MongoRunner.runMongod({binVersion: '4.0', dbpath: dbpath, noCleanData: true});
|
|
testDb = conn.getDB(dbName);
|
|
coll = testDb.getCollection(collName);
|
|
assert.commandWorked(coll.remove({_id: 0, a: 2}));
|
|
MongoRunner.stopMongod(conn);
|
|
|
|
shouldPass = true;
|
|
upgrade40ToLatest(dbpath, shouldPass);
|
|
|
|
resetDbpath(dbpath);
|
|
}
|
|
|
|
// Create a collection with autoIndexId: false on a 3.6 server and assert that an upgrade to
|
|
// latest succeeds because the missing _id index is built.
|
|
function canUpgradeWithoutIndex() {
|
|
let conn = MongoRunner.runMongod({binVersion: '3.6'});
|
|
assert.neq(null, conn, 'mongod was unable able to start with version 3.6');
|
|
|
|
const dbpath = conn.dbpath;
|
|
|
|
// Create a collection with autoIndexId: false.
|
|
let testDb = conn.getDB(dbName);
|
|
let coll = testDb.getCollection(collName);
|
|
assert.commandWorked(coll.runCommand('create', {autoIndexId: false}));
|
|
assert.commandWorked(coll.insert({_id: 0, a: 1}));
|
|
MongoRunner.stopMongod(conn);
|
|
|
|
// The upgrade to 4.0 should always succeed because it does not care about the _id index.
|
|
upgrade36To40(dbpath);
|
|
|
|
const shouldPass = true;
|
|
upgrade40ToLatest(dbpath, shouldPass);
|
|
|
|
resetDbpath(dbpath);
|
|
}
|
|
|
|
cannotUpgradeWithDuplicateIds();
|
|
canUpgradeWithoutIndex();
|
|
})();
|