summaryrefslogtreecommitdiff
path: root/jstests/serial_run/election_timing.js
blob: 2fe83be02edc0905eb0feff851a905a8ebb5e9f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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 + " Limit: " +
                  tc.electionTimeoutLimitMillis / 1000 + " StdDev: " + resStdDev.toFixed(4));

        allResults.forEach(function(failoverElapsedMillis) {
            assert.lte(failoverElapsedMillis,
                       tc.electionTimeoutLimitMillis / 1000,
                       tc.name + ': failover (' + failoverElapsedMillis +
                           ' sec) took too long. limit: ' + tc.electionTimeoutLimitMillis / 1000 +
                           ' sec');
        });
    });

    jsTestLog("Tests completed in: " + (Date.now() - testStart) / 1000 + " seconds");
}());