summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2020-05-18 09:22:41 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-18 13:36:45 +0000
commit912735588386424712a1525da1574a4554bf1787 (patch)
treea64b6d42969c23082203cbd12bfe2df2f6010af1 /src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp
parentcf46145195c8f3313f76b6c93a413568d9ddba5f (diff)
downloadmongo-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.cpp132
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() {