summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp
diff options
context:
space:
mode:
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.cpp99
1 files changed, 92 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 5203980b575..e619276b129 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
@@ -58,6 +58,7 @@ namespace {
using executor::NetworkInterfaceMock;
using executor::RemoteCommandRequest;
using executor::RemoteCommandResponse;
+using InNetworkGuard = NetworkInterfaceMock::InNetworkGuard;
TEST(ReplSetHeartbeatArgs, AcceptsUnknownField) {
ReplSetHeartbeatArgsV1 hbArgs;
@@ -116,7 +117,8 @@ protected:
void processResponseFromPrimary(const ReplSetConfig& config,
long long version = -2,
- long long term = OpTime::kInitialTerm);
+ long long term = OpTime::kInitialTerm,
+ const HostAndPort& target = HostAndPort{"h1", 1});
};
void ReplCoordHBV1Test::assertMemberState(const MemberState expected, std::string msg) {
@@ -160,13 +162,14 @@ ReplCoordHBV1Test::performSyncToFinishReconfigHeartbeat() {
void ReplCoordHBV1Test::processResponseFromPrimary(const ReplSetConfig& config,
long long version,
- long long term) {
+ long long term,
+ const HostAndPort& target) {
NetworkInterfaceMock* net = getNet();
const Date_t startDate = getNet()->now();
NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest();
const RemoteCommandRequest& request = noi->getRequest();
- ASSERT_EQUALS(HostAndPort("h1", 1), request.target);
+ ASSERT_EQUALS(target, request.target);
ReplSetHeartbeatArgsV1 hbArgs;
ASSERT_OK(hbArgs.initialize(request.cmdObj));
ASSERT_EQUALS("mySet", hbArgs.getSetName());
@@ -266,6 +269,85 @@ TEST_F(ReplCoordHBV1Test,
ASSERT_TRUE(getExternalState()->threadsStarted());
}
+TEST_F(ReplCoordHBV1Test, RejectSplitConfigWhenNotInServerlessMode) {
+ auto severityGuard = unittest::MinimumLoggedSeverityGuard{logv2::LogComponent::kDefault,
+ logv2::LogSeverity::Debug(3)};
+
+ // Start up with three nodes, and assume the role of "node2" as a secondary. Notably, the local
+ // node is NOT started in serverless mode. "node2" is configured as having no votes, no
+ // priority, so that we can pass validation for accepting a split config.
+ assertStartSuccess(BSON("_id"
+ << "mySet"
+ << "protocolVersion" << 1 << "version" << 2 << "members"
+ << BSON_ARRAY(BSON("_id" << 1 << "host"
+ << "node1:12345")
+ << BSON("_id" << 2 << "host"
+ << "node2:12345"
+ << "votes" << 0 << "priority" << 0)
+ << BSON("_id" << 3 << "host"
+ << "node3:12345"))),
+ HostAndPort("node2", 12345));
+ ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY));
+ getReplCoord()->updateTerm_forTest(1, nullptr);
+ ASSERT_EQ(getReplCoord()->getTerm(), 1);
+ // respond to initial heartbeat requests
+ for (int j = 0; j < 2; ++j) {
+ replyToReceivedHeartbeatV1();
+ }
+
+ // Verify that there are no further heartbeat requests, since the heartbeat requests should be
+ // scheduled for the future.
+ {
+ InNetworkGuard guard(getNet());
+ assertMemberState(MemberState::RS_SECONDARY);
+ ASSERT_FALSE(getNet()->hasReadyRequests());
+ }
+
+ ReplSetConfig splitConfig =
+ assertMakeRSConfig(BSON("_id"
+ << "mySet"
+ << "version" << 3 << "term" << 1 << "protocolVersion" << 1
+ << "members"
+ << BSON_ARRAY(BSON("_id" << 1 << "host"
+ << "node1:12345")
+ << BSON("_id" << 2 << "host"
+ << "node2:12345")
+ << BSON("_id" << 3 << "host"
+ << "node3:12345"))
+ << "recipientConfig"
+ << BSON("_id"
+ << "recipientSet"
+ << "version" << 1 << "term" << 1 << "members"
+ << BSON_ARRAY(BSON("_id" << 1 << "host"
+ << "node1:12345")
+ << BSON("_id" << 2 << "host"
+ << "node2:12345")
+ << BSON("_id" << 3 << "host"
+ << "node3:12345")))));
+
+ // Accept a heartbeat from `node1` which has a split config. The split config lists this node
+ // ("node2") in the recipient member list, but a node started not in serverless mode should not
+ // accept and install the recipient config.
+ receiveHeartbeatFrom(splitConfig, 1, HostAndPort("node1", 12345));
+
+ {
+ InNetworkGuard guard(getNet());
+ processResponseFromPrimary(splitConfig, 2, 1, HostAndPort{"node1", 12345});
+ assertMemberState(MemberState::RS_SECONDARY);
+ OperationContextNoop opCtx;
+ auto storedConfig = ReplSetConfig::parse(
+ unittest::assertGet(getExternalState()->loadLocalConfigDocument(&opCtx)));
+ ASSERT_OK(storedConfig.validate());
+
+ // Verify that the recipient config was not accepted. A successfully applied splitConfig
+ // will install at version and term {1, 1}.
+ ASSERT_EQUALS(ConfigVersionAndTerm(3, 1), storedConfig.getConfigVersionAndTerm());
+ ASSERT_EQUALS("mySet", storedConfig.getReplSetName());
+ }
+
+ ASSERT_TRUE(getExternalState()->threadsStarted());
+}
+
TEST_F(ReplCoordHBV1Test, NodeRejectsSplitConfigWhenNotInitialized) {
ReplSetConfig rsConfig =
assertMakeRSConfig(BSON("_id"
@@ -556,6 +638,10 @@ TEST_F(
class ReplCoordHBV1SplitConfigTest : public ReplCoordHBV1Test {
public:
void startUp(const std::string& hostAndPort) {
+ ReplSettings settings;
+ settings.setServerlessMode();
+ init(settings);
+
BSONObj configBson =
BSON("_id" << _donorSetName << "version" << _configVersion << "term" << _configTerm
<< "members" << _members << "protocolVersion" << 1);
@@ -740,7 +826,6 @@ TEST_F(ReplCoordHBV1SplitConfigTest, RecipientNodeApplyConfig) {
validateNextRequest("", _recipientSetName, 1, 1);
}
-using InNetworkGuard = NetworkInterfaceMock::InNetworkGuard;
TEST_F(ReplCoordHBV1SplitConfigTest, RejectMismatchedSetNameInHeartbeatResponse) {
startUp(_recipientSecondaryNode);
@@ -813,9 +898,9 @@ TEST_F(ReplCoordHBV1SplitConfigTest, RecipientNodeNonZeroVotes) {
getNet()->runReadyNetworkOperations();
// The node rejected the config as it's a voting node and its version has not changed.
- ASSERT_EQ(getReplCoord()->getConfigVersion(), _configVersion);
- ASSERT_EQ(getReplCoord()->getConfigTerm(), _configTerm);
- ASSERT_EQ(getReplCoord()->getSettings().ourSetName(), _donorSetName);
+ auto config = getReplCoord()->getConfig();
+ ASSERT_EQ(config.getConfigVersionAndTerm(), ConfigVersionAndTerm(_configVersion, _configTerm));
+ ASSERT_EQ(config.getReplSetName(), _donorSetName);
}
class ReplCoordHBV1ReconfigTest : public ReplCoordHBV1Test {