summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2019-11-08 22:09:36 +0000
committerevergreen <evergreen@mongodb.com>2019-11-08 22:09:36 +0000
commit34cc781e42eabe52c409ad930e87ed785c0db9d5 (patch)
tree95e21169253ca2a4ef03c53c4852d2c42e9b0b1c
parentaeed74375c24c59fb6fb725691fe9ce547a810ab (diff)
downloadmongo-34cc781e42eabe52c409ad930e87ed785c0db9d5.tar.gz
SERVER-44393 add js test for a secondary index build that waits for abort from the primary after a 16746 error
Index spec and test data is based on jstests/core/indexu.js
-rw-r--r--jstests/noPassthrough/index_secondary_wait_for_abort.js92
1 files changed, 92 insertions, 0 deletions
diff --git a/jstests/noPassthrough/index_secondary_wait_for_abort.js b/jstests/noPassthrough/index_secondary_wait_for_abort.js
new file mode 100644
index 00000000000..af33cd4d452
--- /dev/null
+++ b/jstests/noPassthrough/index_secondary_wait_for_abort.js
@@ -0,0 +1,92 @@
+/**
+ * Confirms that index builds on a secondary are aborted when we encounter a document that cannot be
+ * indexed. Since we expect the index build on the primary to fail, the secondary should wait for
+ * the primary's abortIndexBuild oplog entry.
+ * @tags: [
+ * requires_replication,
+ * ]
+ */
+(function() {
+"use strict";
+
+load('jstests/noPassthrough/libs/index_build.js');
+
+const rst = new ReplSetTest({
+ nodes: [
+ {},
+ {
+ // Disallow elections on secondary.
+ rsConfig: {
+ priority: 0,
+ votes: 0,
+ },
+ },
+ ]
+});
+const nodes = rst.startSet();
+rst.initiate();
+
+const primary = rst.getPrimary();
+
+// This test requires index builds to start on the createIndexes oplog entry and expects index
+// builds to be interrupted when the primary steps down.
+if (!IndexBuildTest.supportsTwoPhaseIndexBuild(primary)) {
+ jsTestLog('Two phase index builds not supported, skipping test.');
+ rst.stopSet();
+ return;
+}
+
+const testDB = primary.getDB('test');
+const coll = testDB.getCollection('test');
+
+assert.commandWorked(coll.insert({a: 1}));
+
+// There are two 'a.0' fields in this doc, which prevents us from creating an index on {'a.0': 1}.
+// Inserting this document causes the index build to fail during the collection scan phase.
+const invalidDocForIndex = {
+ a: [
+ {'0': 1},
+ ],
+};
+
+assert.commandWorked(coll.insert(invalidDocForIndex));
+
+// We are using this fail point to pause the index build before it starts the collection scan.
+// This is important for this test because we want to prevent the index build on the primary from
+// observing the invalid document while we block its progress.
+assert.commandWorked(
+ testDB.adminCommand({configureFailPoint: 'hangAfterSettingUpIndexBuild', mode: 'alwaysOn'}));
+
+const createIdx = IndexBuildTest.startIndexBuild(primary, coll.getFullName(), {'a.0': 1});
+
+const secondary = rst.getSecondary();
+try {
+ // Wait for the index build to start on the primary. We cannot check the secondary because it
+ // may have crashed by then due to the invalid document.
+ const opId = IndexBuildTest.waitForIndexBuildToStart(testDB, coll.getName(), 'a.0_1');
+ IndexBuildTest.assertIndexBuildCurrentOpContents(testDB, opId);
+
+ const fassertProcessExitCode = _isWindows() ? MongoRunner.EXIT_ABRUPT : MongoRunner.EXIT_ABORT;
+ rst.stop(secondary, undefined, {allowedExitCode: fassertProcessExitCode});
+ assert(rawMongoProgramOutput().match('Fatal assertion 51101 Location16746: Index build: '),
+ 'Index build should have aborted on error.');
+} finally {
+ testDB.adminCommand({configureFailPoint: 'hangAfterSettingUpIndexBuild', mode: 'off'});
+}
+
+// Wait for the index build to stop.
+IndexBuildTest.waitForIndexBuildToStop(testDB);
+
+const exitCode = createIdx({checkExitSuccess: false});
+assert.neq(0, exitCode, 'expected shell to exit abnormally due to index build failing');
+
+// Check indexes on primary.
+IndexBuildTest.assertIndexes(coll, 1, ['_id_']);
+
+const cmdNs = testDB.getCollection('$cmd').getFullName();
+const ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.abortIndexBuild': coll.getName()});
+assert.eq(1, ops.length, 'primary did not write abortIndexBuild oplog entry: ' + tojson(ops));
+
+TestData.skipCheckDBHashes = true;
+rst.stopSet();
+})();