summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-03-03 11:23:24 -0500
committerBenety Goh <benety@mongodb.com>2017-03-03 13:53:56 -0500
commit30b80c79081ff98b513c6c61e9dbae82242689ae (patch)
treee40a7bdd7a896cef8639e0fa1818bea28ab38a08 /jstests
parent6a6bffee00e95776f7dd50e96aa0b8874ca7a01d (diff)
downloadmongo-30b80c79081ff98b513c6c61e9dbae82242689ae.tar.gz
SERVER-28184 removed election_timing.js
Also removed jstests/libs/election_timing_test.js Since disabling the timing checks in SERVER-26142, election_timing.js is reduced to a series of test cases that trigger elections by stepping down or stopping the primary under various election configurations (protocol version 0 or 1). A typical election_timing.js test run typically takes longer than 10 minutes which is a little excessive compared to existing replica set tests. This makes election_timing.js redundant with existing C++ unit tests and JS tests in jstests/replsets.
Diffstat (limited to 'jstests')
-rw-r--r--jstests/libs/election_timing_test.js224
-rw-r--r--jstests/serial_run/election_timing.js143
2 files changed, 0 insertions, 367 deletions
diff --git a/jstests/libs/election_timing_test.js b/jstests/libs/election_timing_test.js
deleted file mode 100644
index a6d574926e5..00000000000
--- a/jstests/libs/election_timing_test.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
- * ElectionTimingTest - set up a ReplSetTest and use default or provided functions to
- * trigger an election. The time it takes to discover a new primary is recorded.
- */
-var ElectionTimingTest = function(opts) {
- // How many times do we start a new ReplSetTest.
- this.testRuns = opts.testRuns || 1;
-
- // How many times do we step down during a ReplSetTest"s lifetime.
- this.testCycles = opts.testCycles || 1;
-
- // The config is set to two electable nodes since we use waitForMemberState
- // to wait for the electable secondary to become primary.
- this.nodes = opts.nodes || [{}, {}, {rsConfig: {arbiterOnly: true}}];
-
- // The name of the replica set and of the collection.
- this.name = opts.name || "election_timing";
-
- // Pass additional replicaSet config options.
- this.settings = opts.settings || {};
-
- // pv1 is the default in master and here.
- this.protocolVersion = opts.hasOwnProperty("protocolVersion") ? opts.protocolVersion : 1;
-
- // A function that runs after the ReplSetTest is initialized.
- this.testSetup = opts.testSetup || Function.prototype;
-
- // A function that triggers election, default is to kill the mongod process.
- this.electionTrigger = opts.electionTrigger || this.stopPrimary;
-
- // A function that waits for new primary to be elected.
- this.waitForNewPrimary = opts.waitForNewPrimary || this.waitForNewPrimary;
-
- // A function that cleans up after the election trigger.
- this.testReset = opts.testReset || this.stopPrimaryReset;
-
- // The interval passed to stepdown that primaries may not seek re-election.
- // We also have to wait out this interval before allowing another stepdown.
- this.stepDownGuardTime = opts.stepDownGuardTime || 60;
-
- // Test results will be stored in these arrays.
- this.testResults = [];
- this.testErrors = [];
-
- this._runTimingTest();
-};
-
-ElectionTimingTest.prototype._runTimingTest = function() {
- for (var run = 0; run < this.testRuns; run++) {
- var collectionName = "test." + this.name;
- var cycleData = {testRun: run, results: []};
-
- jsTestLog("Starting ReplSetTest for test " + this.name + " run: " + run);
- this.rst =
- new ReplSetTest({name: this.name, nodes: this.nodes, nodeOptions: {verbose: ""}});
- this.rst.startSet();
-
- // Get the replset config and apply the settings object.
- var conf = this.rst.getReplSetConfig();
- conf.settings = conf.settings || {};
- conf.settings = Object.merge(conf.settings, this.settings);
-
- // Explicitly setting protocolVersion.
- conf.protocolVersion = this.protocolVersion;
- this.rst.initiate(conf);
-
- // Run the user supplied testSetup() method. Typical uses would be to set up
- // bridging, or wait for a particular state after initiate().
- try {
- this.testSetup();
- } catch (e) {
- // If testSetup() fails, we are in an unknown state, log and return.
- this.testErrors.push({testRun: run, status: "testSetup() failed", error: e});
- this.rst.stopSet();
- return;
- }
-
- // Create and populate a collection.
- var primary = this.rst.getPrimary();
-
- this.electionTimeoutLimitMillis =
- ElectionTimingTest.calculateElectionTimeoutLimitMillis(primary);
- jsTestLog('Election timeout limit: ' + this.electionTimeoutLimitMillis + ' ms');
-
- var coll = primary.getCollection(collectionName);
- for (var i = 0; i < 100; i++) {
- assert.writeOK(coll.insert({_id: i, x: i * 3, arbitraryStr: "this is a string"}));
- }
-
- // Run the election tests on this ReplSetTest instance.
- var secondary;
- for (var cycle = 0; cycle < this.testCycles; cycle++) {
- // Wait for replication.
- this.rst.awaitSecondaryNodes();
- this.rst.awaitReplication();
- primary = this.rst.getPrimary();
- secondary = this.rst.getSecondary();
-
- jsTestLog("Starting test: " + this.name + " run: " + run + " cycle: " + cycle);
- var isMasterResult = primary.getDB("admin").isMaster();
- assert.commandWorked(isMasterResult, "isMaster() failed");
- var oldElectionId = isMasterResult.electionId;
- assert.neq(undefined, oldElectionId, "isMaster() failed to return a valid electionId");
-
- // Time the new election.
- var stepDownTime = Date.now();
-
- // Run the specified election trigger method. Default is to sigstop the primary.
- try {
- this.electionTrigger();
- } catch (e) {
- // Left empty on purpose.
- }
-
- // Wait for the electable secondary to become primary.
- try {
- this.waitForNewPrimary(this.rst, secondary);
- } catch (e) {
- // If we didn"t find a primary, save the error, break so this
- // ReplSetTest is stopped. We can"t continue from a flaky state.
- this.testErrors.push(
- {testRun: run, cycle: cycle, status: "new primary not elected", error: e});
- break;
- }
-
- var electionCompleteTime = Date.now();
-
- // Verify we had an election and we have a new primary.
- var newPrimary = this.rst.getPrimary();
- isMasterResult = newPrimary.getDB("admin").isMaster();
- assert.commandWorked(isMasterResult, "isMaster() failed");
- var newElectionId = isMasterResult.electionId;
- assert.neq(undefined, newElectionId, "isMaster() failed to return a valid electionId");
-
- if (bsonWoCompare(oldElectionId, newElectionId) !== 0) {
- this.testErrors.push({
- testRun: run,
- cycle: cycle,
- status: "electionId not changed, no election was triggered"
- });
- break;
- }
-
- if (primary.host === newPrimary.host) {
- this.testErrors.push(
- {testRun: run, cycle: cycle, status: "Previous primary was re-elected"});
- break;
- }
-
- cycleData.results.push((electionCompleteTime - stepDownTime) / 1000);
-
- // If we are running another test on this ReplSetTest, call the reset function.
- if (cycle + 1 < this.testCycles) {
- try {
- this.testReset();
- } catch (e) {
- this.testErrors.push(
- {testRun: run, cycle: cycle, status: "testReset() failed", error: e});
- break;
- }
- }
- }
- this.testResults.push(cycleData);
- this.rst.stopSet();
- }
-};
-
-ElectionTimingTest.prototype.stopPrimary = function() {
- this.originalPrimary = this.rst.getNodeId(this.rst.getPrimary());
- this.rst.stop(this.originalPrimary);
-};
-
-ElectionTimingTest.prototype.stopPrimaryReset = function() {
- this.rst.restart(this.originalPrimary);
-};
-
-ElectionTimingTest.prototype.stepDownPrimary = function() {
- var adminDB = this.rst.getPrimary().getDB("admin");
- adminDB.runCommand({replSetStepDown: this.stepDownGuardTime, force: true});
-};
-
-ElectionTimingTest.prototype.stepDownPrimaryReset = function() {
- sleep(this.stepDownGuardTime * 1000);
-};
-
-ElectionTimingTest.prototype.waitForNewPrimary = function(rst, secondary) {
- assert.commandWorked(secondary.adminCommand({
- replSetTest: 1,
- waitForMemberState: ReplSetTest.State.PRIMARY,
- timeoutMillis: 60 * 1000
- }),
- "node " + secondary.host + " failed to become primary");
-};
-
-/**
- * Calculates upper limit for actual failover time in milliseconds.
- */
-ElectionTimingTest.calculateElectionTimeoutLimitMillis = function(primary) {
- var configResult = assert.commandWorked(primary.adminCommand({replSetGetConfig: 1}));
- var config = configResult.config;
- // Protocol version is 0 if missing from config.
- var protocolVersion = config.hasOwnProperty("protocolVersion") ? config.protocolVersion : 0;
- var electionTimeoutMillis = 0;
- var electionTimeoutOffsetLimitFraction = 0;
- if (protocolVersion === 0) {
- electionTimeoutMillis = 30000; // from TopologyCoordinatorImpl::VoteLease::leaseTime
- electionTimeoutOffsetLimitFraction = 0;
- } else {
- electionTimeoutMillis = config.settings.electionTimeoutMillis;
- var getParameterResult = assert.commandWorked(primary.adminCommand({
- getParameter: 1,
- replElectionTimeoutOffsetLimitFraction: 1,
- }));
- electionTimeoutOffsetLimitFraction =
- getParameterResult.replElectionTimeoutOffsetLimitFraction;
- }
- var assertSoonIntervalMillis = 200; // from assert.js
- var applierDrainWaitMillis = 1000; // from SyncTail::tryPopAndWaitForMore()
- var padding = 5000; // extra padding for slow hosts
- var electionTimeoutLimitMillis =
- (1 + electionTimeoutOffsetLimitFraction) * electionTimeoutMillis + applierDrainWaitMillis +
- assertSoonIntervalMillis + padding;
- return electionTimeoutLimitMillis;
-};
diff --git a/jstests/serial_run/election_timing.js b/jstests/serial_run/election_timing.js
deleted file mode 100644
index 2d17aee5f4e..00000000000
--- a/jstests/serial_run/election_timing.js
+++ /dev/null
@@ -1,143 +0,0 @@
-// Run a small set of tests using the ElectionTimingTest framework. While this
-// reports the timing of the election, we are using it to check if any errors happen
-// during different election cycles.
-(function() {
- "use strict";
- load("jstests/libs/election_timing_test.js");
- var testStart = Date.now();
-
- var testCases = [
- {
- name: "testV1Stop",
- description: "protocolVersion 1, primary is stopped",
- protocolVersion: 1,
- // testRuns is the number of times a new ReplSetTest will be used.
- testRuns: 1,
- // testCycles is the number of election cycles that will be run per ReplSetTest lifespan.
- testCycles: 5,
- // testSetup is run after the replSet is initiated.
- // Function.prototype is the default.
- testSetup: Function.prototype,
- // Trigger an election by stepping down, stopping, or partitioning the primary.
- // stopPrimary is the default.
- electionTrigger: ElectionTimingTest.prototype.stopPrimary,
- // After the election has completed, make the old primary available again.
- // stopPrimaryReset is the default.
- testReset: ElectionTimingTest.prototype.stopPrimaryReset
- },
-
- /*
- This test case is flakey since waiting for the old primary to shutdown can take longer than
- the
- allowed timeout, even if a new primary was elected during the shutdown time.
-
- {
- name: "testV1StopTimeout1500",
- description: "protocolVersion 1, primary is stopped, electionTimeoutMillis set to 1500",
- protocolVersion: 1,
- testRuns: 1,
- testCycles: 5,
- // The settings object is merged into the replset config settings object.
- settings: {electionTimeoutMillis: 1500}
- },
- */
-
- {
- name: "testV1StepDown",
- description: "protocolVersion 1, primary is stepped down",
- protocolVersion: 1,
- testRuns: 1,
- testCycles: 5,
- electionTrigger: ElectionTimingTest.prototype.stepDownPrimary,
- testReset: ElectionTimingTest.prototype.stepDownPrimaryReset,
- },
-
- {
- name: "testV1StepDown1500",
- description: "protocolVersion 1, primary is stepped down",
- protocolVersion: 1,
- testRuns: 1,
- testCycles: 5,
- electionTrigger: ElectionTimingTest.prototype.stepDownPrimary,
- testReset: ElectionTimingTest.prototype.stepDownPrimaryReset,
- // The settings object is merged into the replset config settings object.
- settings: {electionTimeoutMillis: 1500}
- },
-
- {
- name: "testV1StepDownLargeCluster",
- description: "protocolVersion 1, primary is stepped down, 7 electable nodes",
- protocolVersion: 1,
- nodes: 7,
- testRuns: 1,
- testCycles: 5,
- electionTrigger: ElectionTimingTest.prototype.stepDownPrimary,
- testReset: function() {},
- waitForNewPrimary: function(rst, secondary) {
- rst.getPrimary();
- }
- },
-
- {
- name: "testV0Stop",
- description: "protocolVersion 0, primary is stopped",
- protocolVersion: 0,
- testRuns: 1,
- testCycles: 1
- },
-
- {
- name: "testV0StepDown",
- description: "protocolVersion 0, primary is stepped down",
- protocolVersion: 0,
- testRuns: 1,
- testCycles: 2,
- stepDownGuardTime: 30,
- // There is a guard time in pv0 that prevents an election right
- // after initiating.
- testSetup: function() {
- sleep(30 * 1000);
- },
- electionTrigger: ElectionTimingTest.prototype.stepDownPrimary,
- testReset: ElectionTimingTest.prototype.stepDownPrimaryReset
- },
-
- ];
-
- testCases.forEach(function(tc) {
- var testRun = new ElectionTimingTest(tc);
- tc.testResults = testRun.testResults;
- tc.electionTimeoutLimitMillis = testRun.electionTimeoutLimitMillis;
-
- if (testRun.testErrors.length) {
- // Stop tests if we encounter an error.
- // Dump available information for debugging.
- jsTestLog("Errors from: " + tc.name);
- printjson(tc);
- printjson(testRun.testErrors);
- throw new Error(testRun.testErrors[0].status);
- }
- // Print results of current test in case
- // we need to analyze a failed test later.
- jsTestLog("Raw Results: " + tc.name);
- printjson(tc.testResults);
- });
-
- testCases.forEach(function(tc) {
- var allResults = [];
- tc.testResults.forEach(function(tr) {
- allResults = allResults.concat(tr.results);
- });
-
- var resAvg = Array.avg(allResults);
- var resMin = Math.min(...allResults);
- var resMax = Math.max(...allResults);
- var resStdDev = Array.stdDev(allResults);
-
- jsTestLog("Results: " + tc.name + " Average over " + allResults.length + " runs: " +
- resAvg + " Min: " + resMin + " Max: " + resMax + " StdDev: " +
- resStdDev.toFixed(4));
- });
-
- jsTestLog("Tests completed in: " + (Date.now() - testStart) / 1000 + " seconds");
-}());