summaryrefslogtreecommitdiff
path: root/jstests/replsets/election_participant_new_term_metrics.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/replsets/election_participant_new_term_metrics.js')
-rw-r--r--jstests/replsets/election_participant_new_term_metrics.js109
1 files changed, 109 insertions, 0 deletions
diff --git a/jstests/replsets/election_participant_new_term_metrics.js b/jstests/replsets/election_participant_new_term_metrics.js
new file mode 100644
index 00000000000..aa76bdf4546
--- /dev/null
+++ b/jstests/replsets/election_participant_new_term_metrics.js
@@ -0,0 +1,109 @@
+/**
+ * This test checks that the 'newTermStartDate' and 'newTermAppliedDate' metrics in
+ * 'electionParticipantMetrics' are set and updated correctly. We test this with a three node
+ * replica set by successfully stepping up one of the secondaries, then failing to step up the
+ * original primary. We check that the metrics are appropriately set or unset after each election.
+ */
+
+(function() {
+"use strict";
+
+const testName = jsTestName();
+const rst = ReplSetTest({name: testName, nodes: [{}, {}, {rsConfig: {priority: 0}}]});
+rst.startSet();
+
+// Make sure there are no election timeouts firing for the duration of the test. This helps
+// ensure that the test will only pass if the election succeeds.
+rst.initiateWithHighElectionTimeout();
+
+const originalPrimary = rst.getPrimary();
+const newPrimary = rst.getSecondaries()[0];
+const testNode = rst.getSecondaries()[1];
+
+// Set up a failpoint that forces the original primary to vote no in this election. This guarantees
+// that 'testNode' will be a participant in this election, since its vote will be needed for the new
+// primary to win.
+assert.commandWorked(
+ originalPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
+
+// Step up the new primary.
+assert.commandWorked(newPrimary.adminCommand({replSetStepUp: 1}));
+rst.awaitNodesAgreeOnPrimary();
+assert.eq(newPrimary, rst.getPrimary());
+
+// Since the new term oplog entry needs to be replicated onto testNode for the metrics to be set, we
+// must await replication before checking the metrics.
+rst.awaitReplication();
+
+let testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
+let testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
+
+const originalNewTermStartDate = testNodeElectionParticipantMetrics.newTermStartDate;
+const originalNewTermAppliedDate = testNodeElectionParticipantMetrics.newTermAppliedDate;
+
+// These fields should be set, since testNode has received and applied the new term oplog entry
+// after the election.
+assert(originalNewTermStartDate,
+ () => "Response should have an 'electionParticipantMetrics.newTermStartDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+assert(originalNewTermAppliedDate,
+ () => "Response should have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+
+// Set up a failpoint that forces newPrimary and testNode to vote no in the election, in addition to
+// the new primary above. This will cause the dry run to fail for the original primary.
+assert.commandWorked(
+ newPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
+assert.commandWorked(
+ testNode.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
+
+// Attempt to step up the original primary.
+assert.commandFailedWithCode(originalPrimary.adminCommand({replSetStepUp: 1}),
+ ErrorCodes.CommandFailed);
+
+testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
+testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
+
+// The 'newTermStartDate' and 'newTermAppliedDate' fields should not be cleared, since the term is
+// not incremented when a dry run election is initiated.
+assert(testNodeElectionParticipantMetrics.newTermStartDate,
+ () => "Response should have an 'electionParticipantMetrics.newTermStartDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+assert(testNodeElectionParticipantMetrics.newTermAppliedDate,
+ () => "Response should have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+
+// The fields should store the same dates, since a new term oplog entry was not received.
+assert.eq(originalNewTermStartDate, testNodeElectionParticipantMetrics.newTermStartDate);
+assert.eq(originalNewTermAppliedDate, testNodeElectionParticipantMetrics.newTermAppliedDate);
+
+// Clear the previous failpoint and set up a new one that forces the two current secondaries to vote
+// yes for the candidate in the dry run election and no in the real election. This will cause the
+// real election to fail.
+assert.commandWorked(
+ newPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "off"}));
+assert.commandWorked(newPrimary.adminCommand(
+ {configureFailPoint: "voteYesInDryRunButNoInRealElection", mode: "alwaysOn"}));
+assert.commandWorked(testNode.adminCommand({configureFailPoint: "voteNoInElection", mode: "off"}));
+assert.commandWorked(testNode.adminCommand(
+ {configureFailPoint: "voteYesInDryRunButNoInRealElection", mode: "alwaysOn"}));
+
+// Attempt to step up the original primary.
+assert.commandFailedWithCode(originalPrimary.adminCommand({replSetStepUp: 1}),
+ ErrorCodes.CommandFailed);
+
+testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
+testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
+
+// Since the election succeeded in the dry run, a new term was encountered by the secondary.
+// However, because the real election failed, there was no new term oplog entry, so these fields
+// should not be set.
+assert(!testNodeElectionParticipantMetrics.newTermStartDate,
+ () => "Response should not have an 'electionParticipantMetrics.newTermStartDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+assert(!testNodeElectionParticipantMetrics.newTermAppliedDate,
+ () => "Response should not have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
+ tojson(testNodeElectionParticipantMetrics));
+
+rst.stopSet();
+})(); \ No newline at end of file