diff options
author | Benety Goh <benety@mongodb.com> | 2017-03-03 11:23:24 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2017-03-03 13:53:56 -0500 |
commit | 30b80c79081ff98b513c6c61e9dbae82242689ae (patch) | |
tree | e40a7bdd7a896cef8639e0fa1818bea28ab38a08 /jstests | |
parent | 6a6bffee00e95776f7dd50e96aa0b8874ca7a01d (diff) | |
download | mongo-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.js | 224 | ||||
-rw-r--r-- | jstests/serial_run/election_timing.js | 143 |
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"); -}()); |