diff options
author | William Schultz <william.schultz@mongodb.com> | 2020-05-18 09:22:41 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-18 13:36:45 +0000 |
commit | 912735588386424712a1525da1574a4554bf1787 (patch) | |
tree | a64b6d42969c23082203cbd12bfe2df2f6010af1 /src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp | |
parent | cf46145195c8f3313f76b6c93a413568d9ddba5f (diff) | |
download | mongo-912735588386424712a1525da1574a4554bf1787.tar.gz |
SERVER-29030 Announce new primary via heartbeat requests
Diffstat (limited to 'src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp')
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp | 132 |
1 files changed, 125 insertions, 7 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp index 9160e037da7..277b8537863 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp @@ -80,9 +80,12 @@ TEST(ReplSetHeartbeatArgs, AcceptsUnknownField) { class ReplCoordHBV1Test : public ReplCoordTest { protected: void assertMemberState(MemberState expected, std::string msg = ""); - ReplSetHeartbeatResponse receiveHeartbeatFrom(const ReplSetConfig& rsConfig, - int sourceId, - const HostAndPort& source); + ReplSetHeartbeatResponse receiveHeartbeatFrom( + const ReplSetConfig& rsConfig, + int sourceId, + const HostAndPort& source, + const int term = 1, + const boost::optional<int> currentPrimaryId = boost::none); }; void ReplCoordHBV1Test::assertMemberState(const MemberState expected, std::string msg) { @@ -91,16 +94,22 @@ void ReplCoordHBV1Test::assertMemberState(const MemberState expected, std::strin << " but found " << actual.toString() << " - " << msg; } -ReplSetHeartbeatResponse ReplCoordHBV1Test::receiveHeartbeatFrom(const ReplSetConfig& rsConfig, - int sourceId, - const HostAndPort& source) { +ReplSetHeartbeatResponse ReplCoordHBV1Test::receiveHeartbeatFrom( + const ReplSetConfig& rsConfig, + int sourceId, + const HostAndPort& source, + const int term, + const boost::optional<int> currentPrimaryId) { ReplSetHeartbeatArgsV1 hbArgs; hbArgs.setConfigVersion(rsConfig.getConfigVersion()); hbArgs.setConfigTerm(rsConfig.getConfigTerm()); hbArgs.setSetName(rsConfig.getReplSetName()); hbArgs.setSenderHost(source); hbArgs.setSenderId(sourceId); - hbArgs.setTerm(1); + hbArgs.setTerm(term); + if (currentPrimaryId) { + hbArgs.setPrimaryId(*currentPrimaryId); + } ASSERT(hbArgs.isInitialized()); ReplSetHeartbeatResponse response; @@ -177,6 +186,115 @@ TEST_F(ReplCoordHBV1Test, ASSERT_TRUE(getExternalState()->threadsStarted()); } +TEST_F(ReplCoordHBV1Test, + SecondaryReceivesHeartbeatRequestFromPrimaryWithDifferentPrimaryIdRestartsHeartbeats) { + auto replAllSeverityGuard = unittest::MinimumLoggedSeverityGuard{ + logv2::LogComponent::kReplication, logv2::LogSeverity::Debug(3)}; + + auto replConfigBson = BSON("_id" + << "mySet" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "node1:12345") + << BSON("_id" << 2 << "host" + << "node2:12345") + << BSON("_id" << 3 << "host" + << "node3:12345"))); + + assertStartSuccess(replConfigBson, HostAndPort("node1", 12345)); + ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); + + getReplCoord()->updateTerm_forTest(1, nullptr); + ASSERT_EQ(getReplCoord()->getTerm(), 1); + + enterNetwork(); + // Ignore the first 2 messages. + for (int j = 0; j < 2; ++j) { + const auto noi = getNet()->getNextReadyRequest(); + noi->getRequest(); + getNet()->blackHole(noi); + } + ASSERT_FALSE(getNet()->hasReadyRequests()); + exitNetwork(); + + // We're a secondary and we receive a request from node3 saying it's the primary. + receiveHeartbeatFrom(getReplCoord()->getConfig(), + 3 /* senderId */, + HostAndPort("node3", 12345), + 1 /* term */, + 3 /* currentPrimaryId */); + + enterNetwork(); + std::set<std::string> expectedHosts{"node2", "node3"}; + std::set<std::string> actualHosts; + for (size_t i = 0; i < expectedHosts.size(); i++) { + const auto noi = getNet()->getNextReadyRequest(); + // 'request' represents the request sent from self(node1) back to node3 + const RemoteCommandRequest& request = noi->getRequest(); + ReplSetHeartbeatArgsV1 args; + ASSERT_OK(args.initialize(request.cmdObj)); + actualHosts.insert(request.target.host()); + ASSERT_EQ(args.getPrimaryId(), -1); + // We don't need to respond. + getNet()->blackHole(noi); + } + ASSERT(expectedHosts == actualHosts); + ASSERT_FALSE(getNet()->hasReadyRequests()); + exitNetwork(); + + // Heartbeat in a stale term shouldn't re-schedule heartbeats. + receiveHeartbeatFrom(getReplCoord()->getConfig(), + 3 /* senderId */, + HostAndPort("node3", 12345), + 0 /* term */, + 3 /* currentPrimaryId */); + enterNetwork(); + ASSERT_FALSE(getNet()->hasReadyRequests()); + exitNetwork(); +} + +TEST_F( + ReplCoordHBV1Test, + SecondaryReceivesHeartbeatRequestFromSecondaryWithDifferentPrimaryIdDoesNotRestartHeartbeats) { + auto replAllSeverityGuard = unittest::MinimumLoggedSeverityGuard{ + logv2::LogComponent::kReplication, logv2::LogSeverity::Debug(3)}; + auto replConfigBson = BSON("_id" + << "mySet" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "node1:12345") + << BSON("_id" << 2 << "host" + << "node2:12345") + << BSON("_id" << 3 << "host" + << "node3:12345"))); + + assertStartSuccess(replConfigBson, HostAndPort("node1", 12345)); + ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY)); + ASSERT_EQ(getReplCoord()->getTerm(), 0); + + enterNetwork(); + // Ignore the first 2 messages. + for (int j = 0; j < 2; ++j) { + const auto noi = getNet()->getNextReadyRequest(); + noi->getRequest(); + getNet()->blackHole(noi); + } + exitNetwork(); + + // Node 2 thinks 3 is the primary. We don't restart heartbeats for that. + receiveHeartbeatFrom(getReplCoord()->getConfig(), + 2 /* senderId */, + HostAndPort("node3", 12345), + 0 /* term */, + 3 /* currentPrimaryId */); + + { + enterNetwork(); + ASSERT_FALSE(getNet()->hasReadyRequests()); + exitNetwork(); + } +} + class ReplCoordHBV1ReconfigTest : public ReplCoordHBV1Test { public: void setUp() { |