From 5ab5ab20ba5aa78ceb1697eee05ddea8f6e3d94b Mon Sep 17 00:00:00 2001 From: Vesselina Ratcheva Date: Tue, 13 Mar 2018 15:38:09 -0400 Subject: SERVER-32144 Remove test coverage for replication protocol version 0 This reverts commit c5a4250a649ab0afb4ecdf227d4a0400f9e68786. --- .../replication_coordinator_impl_elect_test.cpp | 651 --------------------- 1 file changed, 651 deletions(-) delete mode 100644 src/mongo/db/repl/replication_coordinator_impl_elect_test.cpp (limited to 'src/mongo/db/repl/replication_coordinator_impl_elect_test.cpp') diff --git a/src/mongo/db/repl/replication_coordinator_impl_elect_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_elect_test.cpp deleted file mode 100644 index b7b871cd89f..00000000000 --- a/src/mongo/db/repl/replication_coordinator_impl_elect_test.cpp +++ /dev/null @@ -1,651 +0,0 @@ -/** - * Copyright (C) 2014 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kReplication - -#include "mongo/platform/basic.h" - -#include "mongo/db/jsobj.h" -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/repl/is_master_response.h" -#include "mongo/db/repl/repl_set_config.h" -#include "mongo/db/repl/repl_set_heartbeat_args.h" -#include "mongo/db/repl/repl_set_heartbeat_response.h" -#include "mongo/db/repl/replication_coordinator_external_state_mock.h" -#include "mongo/db/repl/replication_coordinator_impl.h" -#include "mongo/db/repl/replication_coordinator_test_fixture.h" -#include "mongo/db/repl/topology_coordinator.h" -#include "mongo/executor/network_interface_mock.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/fail_point_service.h" -#include "mongo/util/log.h" - -namespace mongo { -namespace repl { -namespace { - -using executor::NetworkInterfaceMock; -using executor::RemoteCommandRequest; -using executor::RemoteCommandResponse; - -class ReplCoordElectTest : public ReplCoordTest { -protected: - void assertStartSuccess(const BSONObj& configDoc, const HostAndPort& selfHost); - void simulateFreshEnoughForElectability(); -}; - -void ReplCoordElectTest::assertStartSuccess(const BSONObj& configDoc, const HostAndPort& selfHost) { - ReplCoordTest::assertStartSuccess(addProtocolVersion(configDoc, 0), selfHost); -} - -void ReplCoordElectTest::simulateFreshEnoughForElectability() { - ReplicationCoordinatorImpl* replCoord = getReplCoord(); - ReplSetConfig rsConfig = replCoord->getReplicaSetConfig_forTest(); - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - for (int i = 0; i < rsConfig.getNumMembers() - 1; ++i) { - const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); - const RemoteCommandRequest& request = noi->getRequest(); - log() << request.target.toString() << " processing " << request.cmdObj; - if (request.cmdObj.firstElement().fieldNameStringData() == "replSetFresh") { - net->scheduleResponse( - noi, - net->now(), - makeResponseStatus(BSON("ok" << 1 << "fresher" << false << "opTime" - << Date_t::fromMillisSinceEpoch(Timestamp(0, 0).asLL()) - << "veto" - << false))); - } else { - error() << "Black holing unexpected request to " << request.target << ": " - << request.cmdObj; - net->blackHole(noi); - } - net->runReadyNetworkOperations(); - } - net->exitNetwork(); -} - -TEST_F(ReplCoordElectTest, StartElectionDoesNotStartAnElectionWhenNodeHasNoOplogEntries) { - logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Debug(3)); - // Election never starts because we haven't set a lastOpTimeApplied value yet, via a - // heartbeat. - startCapturingLogMessages(); - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345"))), - HostAndPort("node1", 12345)); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - simulateEnoughHeartbeatsForAllNodesUp(); - stopCapturingLogMessages(); - ASSERT_EQUALS(1, countLogLinesContaining("node has no applied oplog entries")); -} - -/** - * This test checks that an election can happen when only one node is up, and it has the - * vote(s) to win. - */ -TEST_F(ReplCoordElectTest, ElectionSucceedsWhenNodeIsTheOnlyElectableNode) { - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345" - << "votes" - << 0 - << "hidden" - << true - << "priority" - << 0))), - HostAndPort("node1", 12345)); - - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - // Fake OpTime from initiate, or a write op. - getExternalState()->setLastOpTime(OpTime{{0, 0}, -1}); - - ASSERT(getReplCoord()->getMemberState().secondary()) - << getReplCoord()->getMemberState().toString(); - - getReplCoord()->setMyLastAppliedOpTime(OpTime(Timestamp(10, 0), -1)); - - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); - // blackhole heartbeat - net->scheduleResponse( - noi, net->now(), executor::RemoteCommandResponse(ErrorCodes::OperationFailed, "timeout")); - net->runReadyNetworkOperations(); - // blackhole freshness - const NetworkInterfaceMock::NetworkOperationIterator noi2 = net->getNextReadyRequest(); - net->scheduleResponse( - noi2, net->now(), executor::RemoteCommandResponse(ErrorCodes::OperationFailed, "timeout")); - net->runReadyNetworkOperations(); - net->exitNetwork(); - - ASSERT(getReplCoord()->getMemberState().primary()) - << getReplCoord()->getMemberState().toString(); - ASSERT(getReplCoord()->getApplierState() == ReplicationCoordinator::ApplierState::Draining); - - const auto opCtxPtr = makeOperationContext(); - auto& opCtx = *opCtxPtr; - - // Since we're still in drain mode, expect that we report ismaster: false, issecondary:true. - IsMasterResponse imResponse; - getReplCoord()->fillIsMasterForReplSet(&imResponse); - ASSERT_FALSE(imResponse.isMaster()) << imResponse.toBSON().toString(); - ASSERT_TRUE(imResponse.isSecondary()) << imResponse.toBSON().toString(); - getReplCoord()->signalDrainComplete(&opCtx, getReplCoord()->getTerm()); - getReplCoord()->fillIsMasterForReplSet(&imResponse); - ASSERT_TRUE(imResponse.isMaster()) << imResponse.toBSON().toString(); - ASSERT_FALSE(imResponse.isSecondary()) << imResponse.toBSON().toString(); -} - -TEST_F(ReplCoordElectTest, ElectionSucceedsWhenNodeIsTheOnlyNode) { - startCapturingLogMessages(); - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345"))), - HostAndPort("node1", 12345)); - - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - - // Fake OpTime from initiate, or a write op. - getExternalState()->setLastOpTime(OpTime{{0, 0}, -1}); - - ASSERT(getReplCoord()->getMemberState().primary()) - << getReplCoord()->getMemberState().toString(); - ASSERT(getReplCoord()->getApplierState() == ReplicationCoordinator::ApplierState::Draining); - - const auto opCtxPtr = makeOperationContext(); - auto& opCtx = *opCtxPtr; - - // Since we're still in drain mode, expect that we report ismaster: false, issecondary:true. - IsMasterResponse imResponse; - getReplCoord()->fillIsMasterForReplSet(&imResponse); - ASSERT_FALSE(imResponse.isMaster()) << imResponse.toBSON().toString(); - ASSERT_TRUE(imResponse.isSecondary()) << imResponse.toBSON().toString(); - getReplCoord()->signalDrainComplete(&opCtx, getReplCoord()->getTerm()); - getReplCoord()->fillIsMasterForReplSet(&imResponse); - ASSERT_TRUE(imResponse.isMaster()) << imResponse.toBSON().toString(); - ASSERT_FALSE(imResponse.isSecondary()) << imResponse.toBSON().toString(); -} - -TEST_F(ReplCoordElectTest, ElectionSucceedsWhenAllNodesVoteYea) { - BSONObj configObj = BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345"))); - assertStartSuccess(configObj, HostAndPort("node1", 12345)); - OperationContextNoop opCtx; - getReplCoord()->setMyLastAppliedOpTime(OpTime{{100, 1}, -1}); - getExternalState()->setLastOpTime(OpTime{{100, 1}, -1}); - - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - startCapturingLogMessages(); - simulateSuccessfulElection(); - stopCapturingLogMessages(); - ASSERT_EQUALS(1, countLogLinesContaining("election succeeded")); -} - -TEST_F(ReplCoordElectTest, ElectionFailsWhenOneNodeVotesNay) { - // one responds with -10000 votes, and one doesn't respond, and we are not elected - startCapturingLogMessages(); - BSONObj configObj = BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345"))); - assertStartSuccess(configObj, HostAndPort("node1", 12345)); - ReplSetConfig config = assertMakeRSConfig(configObj); - - OperationContextNoop opCtx; - OpTime time1(Timestamp(100, 1), 0); - getReplCoord()->setMyLastAppliedOpTime(time1); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - - simulateEnoughHeartbeatsForAllNodesUp(); - simulateFreshEnoughForElectability(); - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - while (net->hasReadyRequests()) { - const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); - const RemoteCommandRequest& request = noi->getRequest(); - log() << request.target.toString() << " processing " << request.cmdObj; - if (request.target != HostAndPort("node2", 12345)) { - net->blackHole(noi); - } else if (request.cmdObj.firstElement().fieldNameStringData() != "replSetElect") { - net->blackHole(noi); - } else { - net->scheduleResponse( - noi, - net->now(), - makeResponseStatus(BSON("ok" << 1 << "vote" << -10000 << "round" << OID()))); - } - net->runReadyNetworkOperations(); - } - net->exitNetwork(); - stopCapturingLogMessages(); - ASSERT_EQUALS(1, countLogLinesContaining("couldn't elect self, only received -9999 votes")); -} - -TEST_F(ReplCoordElectTest, VotesWithStringValuesAreNotCountedAsYeas) { - // one responds with a bad 'vote' field, and one doesn't respond, and we are not elected - startCapturingLogMessages(); - BSONObj configObj = BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345"))); - assertStartSuccess(configObj, HostAndPort("node1", 12345)); - ReplSetConfig config = assertMakeRSConfig(configObj); - - OperationContextNoop opCtx; - OpTime time1(Timestamp(100, 1), 0); - getReplCoord()->setMyLastAppliedOpTime(time1); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - - simulateEnoughHeartbeatsForAllNodesUp(); - simulateFreshEnoughForElectability(); - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - while (net->hasReadyRequests()) { - const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); - const RemoteCommandRequest& request = noi->getRequest(); - log() << request.target.toString() << " processing " << request.cmdObj; - if (request.target != HostAndPort("node2", 12345)) { - net->blackHole(noi); - } else if (request.cmdObj.firstElement().fieldNameStringData() != "replSetElect") { - net->blackHole(noi); - } else { - net->scheduleResponse(noi, - net->now(), - makeResponseStatus(BSON("ok" << 1 << "vote" - << "yea" - << "round" - << OID()))); - } - net->runReadyNetworkOperations(); - } - net->exitNetwork(); - stopCapturingLogMessages(); - ASSERT_EQUALS(1, - countLogLinesContaining("wrong type for vote argument in replSetElect command")); -} - -TEST_F(ReplCoordElectTest, TransitionToRollbackFailsWhenElectionInProgress) { - BSONObj configObj = BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345"))); - assertStartSuccess(configObj, HostAndPort("node1", 12345)); - ReplSetConfig config = assertMakeRSConfig(configObj); - - OperationContextNoop opCtx; - OpTime time1(Timestamp(100, 1), 0); - getReplCoord()->setMyLastAppliedOpTime(time1); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - - simulateEnoughHeartbeatsForAllNodesUp(); - simulateFreshEnoughForElectability(); - - ASSERT_EQUALS(ErrorCodes::ElectionInProgress, - getReplCoord()->setFollowerMode(MemberState::RS_ROLLBACK)); - - ASSERT_FALSE(getReplCoord()->getMemberState().rollback()); - - // We do not need to respond to any pending network operations because setFollowerMode() will - // cancel the freshness checker and election command runner. -} - -TEST_F(ReplCoordElectTest, NodeWillNotStandForElectionDuringHeartbeatReconfig) { - // start up, receive reconfig via heartbeat while at the same time, become candidate. - // candidate state should be cleared. - OperationContextNoop opCtx; - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 2 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345") - << BSON("_id" << 4 << "host" - << "node4:12345") - << BSON("_id" << 5 << "host" - << "node5:12345"))), - HostAndPort("node1", 12345)); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - getReplCoord()->setMyLastAppliedOpTime(OpTime(Timestamp(100, 0), 0)); - - getGlobalFailPointRegistry() - ->getFailPoint("blockHeartbeatReconfigFinish") - ->setMode(FailPoint::alwaysOn); - - // hb reconfig - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - ReplSetHeartbeatResponse hbResp2; - ReplSetConfig config; - config - .initialize(BSON("_id" - << "mySet" - << "version" - << 3 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")))) - .transitional_ignore(); - hbResp2.setConfig(config); - hbResp2.setConfigVersion(3); - hbResp2.setSetName("mySet"); - hbResp2.setState(MemberState::RS_SECONDARY); - BSONObjBuilder respObj2; - respObj2 << "ok" << 1; - hbResp2.addToBSON(&respObj2, false); - net->runUntil(net->now() + Seconds(10)); // run until we've sent a heartbeat request - const NetworkInterfaceMock::NetworkOperationIterator noi2 = net->getNextReadyRequest(); - net->scheduleResponse(noi2, net->now(), makeResponseStatus(respObj2.obj())); - net->runReadyNetworkOperations(); - getNet()->exitNetwork(); - - // prepare candidacy - BSONObjBuilder result; - ReplicationCoordinator::ReplSetReconfigArgs args; - args.force = false; - args.newConfigObj = config.toBSON(); - ASSERT_EQUALS(ErrorCodes::ConfigurationInProgress, - getReplCoord()->processReplSetReconfig(&opCtx, args, &result)); - - logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Debug(2)); - startCapturingLogMessages(); - - // receive sufficient heartbeats to trigger an election - ReplicationCoordinatorImpl* replCoord = getReplCoord(); - ReplSetConfig rsConfig = replCoord->getReplicaSetConfig_forTest(); - net->enterNetwork(); - for (int i = 0; i < 2; ++i) { - const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); - const RemoteCommandRequest& request = noi->getRequest(); - log() << request.target.toString() << " processing " << request.cmdObj; - ReplSetHeartbeatArgs hbArgs; - if (hbArgs.initialize(request.cmdObj).isOK()) { - ReplSetHeartbeatResponse hbResp; - hbResp.setSetName(rsConfig.getReplSetName()); - hbResp.setState(MemberState::RS_SECONDARY); - hbResp.setConfigVersion(rsConfig.getConfigVersion()); - BSONObjBuilder respObj; - respObj << "ok" << 1; - hbResp.addToBSON(&respObj, false); - net->scheduleResponse(noi, net->now(), makeResponseStatus(respObj.obj())); - } else { - error() << "Black holing unexpected request to " << request.target << ": " - << request.cmdObj; - net->blackHole(noi); - } - net->runReadyNetworkOperations(); - } - - stopCapturingLogMessages(); - // ensure node does not stand for election - ASSERT_EQUALS(1, - countLogLinesContaining("Not standing for election; processing " - "a configuration change")); - getGlobalFailPointRegistry() - ->getFailPoint("blockHeartbeatReconfigFinish") - ->setMode(FailPoint::off); -} - -TEST_F(ReplCoordElectTest, StepsDownRemoteIfNodeHasHigherPriorityThanCurrentPrimary) { - BSONObj configObj = BSON("_id" - << "mySet" - << "version" - << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345" - << "priority" - << 2) - << BSON("_id" << 2 << "host" - << "node2:12345") - << BSON("_id" << 3 << "host" - << "node3:12345"))); - assertStartSuccess(configObj, HostAndPort("node1", 12345)); - ReplSetConfig config = assertMakeRSConfig(configObj); - - auto replCoord = getReplCoord(); - - OperationContextNoop opCtx; - OpTime time1(Timestamp(100, 1), 0); - getReplCoord()->setMyLastAppliedOpTime(time1); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - - auto net = getNet(); - net->enterNetwork(); - while (net->hasReadyRequests()) { - auto noi = net->getNextReadyRequest(); - auto&& request = noi->getRequest(); - log() << request.target << " processing " << request.cmdObj; - ASSERT_EQUALS("replSetHeartbeat", request.cmdObj.firstElement().fieldNameStringData()); - ReplSetHeartbeatArgs hbArgs; - if (hbArgs.initialize(request.cmdObj).isOK()) { - ReplSetHeartbeatResponse hbResp; - Date_t responseDate = net->now(); - hbResp.setSetName(config.getReplSetName()); - if (request.target == HostAndPort("node2", 12345)) { - hbResp.setState(MemberState::RS_PRIMARY); - } else { - hbResp.setState(MemberState::RS_SECONDARY); - responseDate += Milliseconds{1}; - } - hbResp.setConfigVersion(config.getConfigVersion()); - auto response = makeResponseStatus(hbResp.toBSON(replCoord->isV1ElectionProtocol())); - net->scheduleResponse(noi, responseDate, response); - } else { - error() << "Black holing unexpected request to " << request.target << ": " - << request.cmdObj; - net->blackHole(noi); - } - } - const auto afterHeartbeatsProcessed = net->now() + Milliseconds{1}; - net->runUntil(afterHeartbeatsProcessed); - ASSERT_EQ(afterHeartbeatsProcessed, net->now()); - - ASSERT_TRUE(net->hasReadyRequests()); - auto noi = net->getNextReadyRequest(); - auto&& request = noi->getRequest(); - log() << request.target << " processing " << request.cmdObj; - ASSERT_EQUALS("replSetStepDown", request.cmdObj.firstElement().fieldNameStringData()); - ASSERT_EQUALS(1LL, request.cmdObj["secondaryCatchUpPeriodSecs"].safeNumberLong()); - auto target = request.target; - ASSERT_EQUALS(HostAndPort("node2", 12345), target); - auto response = makeResponseStatus(BSON("ok" << 1)); - net->scheduleResponse(noi, net->now(), response); - logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Debug(1)); - startCapturingLogMessages(); - net->runReadyNetworkOperations(); - stopCapturingLogMessages(); - logger::globalLogDomain()->setMinimumLoggedSeverity(logger::LogSeverity::Log()); - net->exitNetwork(); - ASSERT_EQUALS(1, - countLogLinesContaining(str::stream() << "stepdown of primary(" - << target.toString() - << ") succeeded")); -} - -TEST_F(ReplCoordElectTest, NodeCancelsElectionUponReceivingANewConfigDuringFreshnessCheckingPhase) { - // Start up and become electable. - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 2 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 3 << "host" - << "node3:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")) - << "settings" - << BSON("heartbeatIntervalMillis" << 100)), - HostAndPort("node1", 12345)); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - getReplCoord()->setMyLastAppliedOpTime(OpTime(Timestamp(100, 0), 0)); - getReplCoord()->setMyLastDurableOpTime(OpTime(Timestamp(100, 0), 0)); - simulateEnoughHeartbeatsForAllNodesUp(); - simulateFreshEnoughForElectability(); - ASSERT(TopologyCoordinator::Role::kCandidate == getTopoCoord().getRole()); - - // Advance to freshness checker request phase. - NetworkInterfaceMock* net = getNet(); - net->enterNetwork(); - while (TopologyCoordinator::Role::kCandidate != getTopoCoord().getRole()) { - net->runUntil(net->now() + Seconds(1)); - if (!net->hasReadyRequests()) { - continue; - } - net->blackHole(net->getNextReadyRequest()); - } - net->exitNetwork(); - ASSERT(TopologyCoordinator::Role::kCandidate == getTopoCoord().getRole()); - - // Submit a reconfig and confirm it cancels the election. - ReplicationCoordinatorImpl::ReplSetReconfigArgs config = { - BSON("_id" - << "mySet" - << "version" - << 4 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345"))), - true}; - - BSONObjBuilder result; - const auto opCtx = makeOperationContext(); - ASSERT_OK(getReplCoord()->processReplSetReconfig(opCtx.get(), config, &result)); - // Wait until election cancels. - net->enterNetwork(); - net->runReadyNetworkOperations(); - net->exitNetwork(); - ASSERT(TopologyCoordinator::Role::kFollower == getTopoCoord().getRole()); -} - -TEST_F(ReplCoordElectTest, NodeCancelsElectionUponReceivingANewConfigDuringElectionPhase) { - // Start up and become electable. - assertStartSuccess(BSON("_id" - << "mySet" - << "version" - << 2 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 3 << "host" - << "node3:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")) - << "settings" - << BSON("heartbeatIntervalMillis" << 100)), - HostAndPort("node1", 12345)); - ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); - getReplCoord()->setMyLastAppliedOpTime(OpTime(Timestamp(100, 0), 0)); - getReplCoord()->setMyLastDurableOpTime(OpTime(Timestamp(100, 0), 0)); - simulateEnoughHeartbeatsForAllNodesUp(); - simulateFreshEnoughForElectability(); - ASSERT(TopologyCoordinator::Role::kCandidate == getTopoCoord().getRole()); - - // Submit a reconfig and confirm it cancels the election. - ReplicationCoordinatorImpl::ReplSetReconfigArgs config = { - BSON("_id" - << "mySet" - << "version" - << 4 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345"))), - true}; - - BSONObjBuilder result; - const auto opCtx = makeOperationContext(); - ASSERT_OK(getReplCoord()->processReplSetReconfig(opCtx.get(), config, &result)); - // Wait until election cancels. - getNet()->enterNetwork(); - getNet()->runReadyNetworkOperations(); - getNet()->exitNetwork(); - ASSERT(TopologyCoordinator::Role::kFollower == getTopoCoord().getRole()); -} - -} // namespace -} // namespace repl -} // namespace mongo -- cgit v1.2.1