0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/jstests/disk/repair_duplicate_keys.js

260 lines
8.5 KiB
JavaScript

/**
* Tests that --repair deletes documents containing duplicate unique keys and inserts them into a
* local lost and found collection.
*
* @tags: [requires_wiredtiger]
*/
(function() {
load('jstests/disk/libs/wt_file_helper.js');
load("jstests/libs/uuid_util.js");
const baseName = "repair_duplicate_keys";
const localBaseName = "local";
const collName = "test";
const lostAndFoundCollBaseName = "lost_and_found.";
const dbpath = MongoRunner.dataPath + baseName + "/";
const indexName = "a_1";
const doc1 = {
a: 1,
};
const doc2 = {
a: 10,
};
const doc3 = {
a: 100,
};
const docWithId = {
a: 1,
_id: 1
};
const dupDocWithId = {
a: 1,
_id: 1
};
resetDbpath(dbpath);
let port;
// Initializes test collection for tests 1-3.
let createIndexedCollWithDocs = function(coll) {
assert.commandWorked(coll.insert(doc1));
assert.commandWorked(coll.createIndex({a: 1}, {name: indexName, unique: true}));
assert.commandWorked(coll.insert(doc2));
assert.commandWorked(coll.insert(doc3));
assertQueryUsesIndex(coll, doc1, indexName);
assertQueryUsesIndex(coll, doc2, indexName);
assertQueryUsesIndex(coll, doc3, indexName);
return coll;
};
// Bypasses DuplicateKey insertion error for testing via failpoint.
let addDuplicateDocumentToCol = function(db, coll, doc) {
jsTestLog("Insert document without index entries.");
assert.commandWorked(
db.adminCommand({configureFailPoint: "skipIndexNewRecords", mode: "alwaysOn"}));
assert.commandWorked(coll.insert(doc));
assert.commandWorked(db.adminCommand({configureFailPoint: "skipIndexNewRecords", mode: "off"}));
};
// Runs repair on collection with possible duplicate keys and verifies original documents in
// collection initialized with "createIndexedCollWithDocs" are still present.
let runRepairAndVerifyCollectionDocs = function() {
jsTestLog("Entering runRepairAndVerifyCollectionDocs...");
assertRepairSucceeds(dbpath, port);
let mongod = startMongodOnExistingPath(dbpath);
let testColl = mongod.getDB(baseName)[collName];
assert.eq(testColl.find(doc1).itcount(), 1);
assert.eq(testColl.find(doc2).itcount(), 1);
assert.eq(testColl.find(doc3).itcount(), 1);
assert.eq(testColl.count(), 3);
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting runRepairAndVerifyCollectionDocs.");
};
/* Test 1: Insert unique documents and verify that no local database is generated. */
(function startStandaloneWithNoDup() {
jsTestLog("Entering startStandaloneWithNoDup...");
let mongod = startMongodOnExistingPath(dbpath);
port = mongod.port;
let testColl = mongod.getDB(baseName)[collName];
testColl = createIndexedCollWithDocs(testColl);
assert.commandFailedWithCode(testColl.insert(doc1), [ErrorCodes.DuplicateKey]);
assert.commandFailedWithCode(testColl.insert(doc2), [ErrorCodes.DuplicateKey]);
assert.commandFailedWithCode(testColl.insert(doc3), [ErrorCodes.DuplicateKey]);
assert.eq(testColl.count(), 3);
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting startStandaloneWithNoDup.");
})();
runRepairAndVerifyCollectionDocs();
(function checkLostAndFoundCollForNoDup() {
jsTestLog("Entering checkLostAndFoundCollForNoDup...");
let mongod = startMongodOnExistingPath(dbpath);
const uuid_obj = getUUIDFromListCollections(mongod.getDB(baseName), collName);
const uuid = extractUUIDFromObject(uuid_obj);
let localColl = mongod.getDB(localBaseName)[lostAndFoundCollBaseName + uuid];
assert.isnull(localColl.exists());
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting checkLostAndFoundCollForNoDup.");
})();
/* Test 2: Insert one duplicate document into test collection and verify that repair deletes the
* document from the collection, generates a "local.lost_and_found" collection and inserts
* duplicate document into it. */
(function startStandaloneWithOneDup() {
jsTestLog("Entering startStandaloneWithOneDup...");
resetDbpath(dbpath);
let mongod = startMongodOnExistingPath(dbpath);
port = mongod.port;
let db = mongod.getDB(baseName);
let testColl = mongod.getDB(baseName)[collName];
testColl = createIndexedCollWithDocs(testColl);
assert.commandFailedWithCode(testColl.insert(doc1), [ErrorCodes.DuplicateKey]);
addDuplicateDocumentToCol(db, testColl, doc1);
assert.eq(testColl.count(), 4);
MongoRunner.stopMongod(mongod, undefined, {skipValidation: true});
jsTestLog("Exiting startStandaloneWithOneDup.");
})();
runRepairAndVerifyCollectionDocs();
(function checkLostAndFoundCollForOneDup() {
jsTestLog("Entering checkLostAndFoundCollForOneDup...");
let mongod = startMongodOnExistingPath(dbpath);
const uuid_obj = getUUIDFromListCollections(mongod.getDB(baseName), collName);
const uuid = extractUUIDFromObject(uuid_obj);
let localColl = mongod.getDB(localBaseName)[lostAndFoundCollBaseName + uuid];
assert.eq(localColl.find(doc1).itcount(), 1);
assert.eq(localColl.count(), 1);
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting checkLostAndFoundCollForOneDup.");
})();
/* Test 3: Insert multiple duplicate documents into the test collection and verify that repair
* deletes the documents from the collection, generates a "local.lost_and_found" collection and
* inserts duplicate document into it.
*/
(function startStandaloneWithMultipleDups() {
jsTestLog("Entering startStandaloneWithMultipleDups...");
resetDbpath(dbpath);
let mongod = startMongodOnExistingPath(dbpath);
port = mongod.port;
let db = mongod.getDB(baseName);
let testColl = mongod.getDB(baseName)[collName];
testColl = createIndexedCollWithDocs(testColl);
assert.commandFailedWithCode(testColl.insert(doc1), [ErrorCodes.DuplicateKey]);
addDuplicateDocumentToCol(db, testColl, doc1);
addDuplicateDocumentToCol(db, testColl, doc2);
addDuplicateDocumentToCol(db, testColl, doc3);
assert.eq(testColl.count(), 6);
MongoRunner.stopMongod(mongod, undefined, {skipValidation: true});
jsTestLog("Exiting startStandaloneWithMultipleDups.");
})();
runRepairAndVerifyCollectionDocs();
(function checkLostAndFoundCollForDups() {
jsTestLog("Entering checkLostAndFoundCollForDups...");
let mongod = startMongodOnExistingPath(dbpath);
const uuid_obj = getUUIDFromListCollections(mongod.getDB(baseName), collName);
const uuid = extractUUIDFromObject(uuid_obj);
let localColl = mongod.getDB(localBaseName)[lostAndFoundCollBaseName + uuid];
assert.eq(localColl.find(doc1).itcount(), 1);
assert.eq(localColl.find(doc2).itcount(), 1);
assert.eq(localColl.find(doc3).itcount(), 1);
assert.eq(localColl.count(), 3);
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting checkLostAndFoundCollForDups.");
})();
/* Test 4: Insert document with both duplicate "a" field and duplicate _id field. Verify that repair
* deletes the duplicate document from test collection, generates a "local.lost_and_found"
* collection and inserts duplicate document into it.
*/
(function startStandaloneWithDoubleDup() {
jsTestLog("Entering startStandaloneWithDoubleDup...");
resetDbpath(dbpath);
let mongod = startMongodOnExistingPath(dbpath);
port = mongod.port;
let db = mongod.getDB(baseName);
let testColl = mongod.getDB(baseName)[collName];
assert.commandWorked(testColl.insert(docWithId));
assert.commandWorked(testColl.createIndex({a: 1}, {name: indexName, unique: true}));
addDuplicateDocumentToCol(db, testColl, dupDocWithId);
assert.eq(testColl.count(), 2);
MongoRunner.stopMongod(mongod, undefined, {skipValidation: true});
jsTestLog("Exiting startStandaloneWithDoubleDup.");
})();
(function runRepairAndVerifyCollectionDoc() {
jsTestLog("Running repair...");
assertRepairSucceeds(dbpath, port);
let mongod = startMongodOnExistingPath(dbpath);
let testColl = mongod.getDB(baseName)[collName];
assert.eq(testColl.find(docWithId).itcount(), 1);
assert.eq(testColl.count(), 1);
MongoRunner.stopMongod(mongod);
jsTestLog("Finished repairing.");
})();
(function checkLostAndFoundCollForDoubleDup() {
jsTestLog("Entering checkLostAndFoundCollForDoubleDup...");
let mongod = startMongodOnExistingPath(dbpath);
const uuid_obj = getUUIDFromListCollections(mongod.getDB(baseName), collName);
const uuid = extractUUIDFromObject(uuid_obj);
let localColl = mongod.getDB(localBaseName)[lostAndFoundCollBaseName + uuid];
assert.eq(localColl.find(docWithId).itcount(), 1);
assert.eq(localColl.count(), 1);
MongoRunner.stopMongod(mongod);
jsTestLog("Exiting checkLostAndFoundCollForDoubleDup.");
})();
})();