summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2021-03-04 23:08:50 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-13 21:20:05 +0000
commitec6dffd110749232f15e0498e48e4f849cf7e6a0 (patch)
tree7f071f0f90813aea31af7413858f9ee2caa03dd1
parentb28b53d23843c0e42e0751673c76088a3e7e60fa (diff)
downloadmongo-ec6dffd110749232f15e0498e48e4f849cf7e6a0.tar.gz
SERVER-54292 remove dependency on scanning replica set monitor in tenant_migration_recipient_service_tests
-rw-r--r--src/mongo/client/SConscript12
-rw-r--r--src/mongo/client/replica_set_monitor_manager.cpp6
-rw-r--r--src/mongo/client/replica_set_monitor_manager.h1
-rw-r--r--src/mongo/client/streamable_replica_set_monitor_for_testing.cpp79
-rw-r--r--src/mongo/client/streamable_replica_set_monitor_for_testing.h65
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service_test.cpp140
-rw-r--r--src/mongo/dbtests/SConscript1
-rw-r--r--src/mongo/dbtests/mock/mock_replica_set.cpp163
-rw-r--r--src/mongo/dbtests/mock/mock_replica_set.h14
9 files changed, 349 insertions, 132 deletions
diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript
index e120354b79c..589c74df1af 100644
--- a/src/mongo/client/SConscript
+++ b/src/mongo/client/SConscript
@@ -315,6 +315,18 @@ env.Library(
)
env.Library(
+ target='replica_set_monitor_test_helper',
+ source=[
+ 'streamable_replica_set_monitor_for_testing.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/client/clientdriver_network',
+ '$BUILD_DIR/mongo/client/sdam/sdam_test',
+ '$BUILD_DIR/mongo/util/net/network',
+ ],
+)
+
+env.Library(
target='fetcher',
source=[
'fetcher.cpp',
diff --git a/src/mongo/client/replica_set_monitor_manager.cpp b/src/mongo/client/replica_set_monitor_manager.cpp
index 0d1d434734e..a21fc832d35 100644
--- a/src/mongo/client/replica_set_monitor_manager.cpp
+++ b/src/mongo/client/replica_set_monitor_manager.cpp
@@ -342,4 +342,10 @@ bool ReplicaSetMonitorManager::isShutdown() const {
void ReplicaSetMonitorConnectionManager::dropConnections(const HostAndPort& hostAndPort) {
_network->dropConnections(hostAndPort);
}
+
+void ReplicaSetMonitorManager::installMonitor_forTests(std::shared_ptr<ReplicaSetMonitor> monitor) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _monitors[monitor->getName()] = monitor;
+}
+
} // namespace mongo
diff --git a/src/mongo/client/replica_set_monitor_manager.h b/src/mongo/client/replica_set_monitor_manager.h
index bde3e41f815..9ce98024c76 100644
--- a/src/mongo/client/replica_set_monitor_manager.h
+++ b/src/mongo/client/replica_set_monitor_manager.h
@@ -156,6 +156,7 @@ public:
bool isShutdown() const;
+ void installMonitor_forTests(std::shared_ptr<ReplicaSetMonitor> monitor);
private:
/**
diff --git a/src/mongo/client/streamable_replica_set_monitor_for_testing.cpp b/src/mongo/client/streamable_replica_set_monitor_for_testing.cpp
new file mode 100644
index 00000000000..e0f582beed6
--- /dev/null
+++ b/src/mongo/client/streamable_replica_set_monitor_for_testing.cpp
@@ -0,0 +1,79 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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.
+ */
+
+#include "mongo/client/streamable_replica_set_monitor_for_testing.h"
+
+#include "mongo/executor/network_interface_factory.h"
+#include "mongo/executor/network_interface_thread_pool.h"
+#include "mongo/executor/thread_pool_task_executor.h"
+#include "mongo/rpc/metadata/egress_metadata_hook_list.h"
+
+namespace mongo {
+
+StreamableReplicaSetMonitorForTesting::~StreamableReplicaSetMonitorForTesting() {
+ if (_taskExecutor) {
+ _taskExecutor->shutdown();
+ _taskExecutor->join();
+ }
+
+ if (_replSetMonitor) {
+ ReplicaSetMonitorManager::get()->removeMonitor(_replSetMonitor->getName());
+ }
+}
+
+void StreamableReplicaSetMonitorForTesting::setup(const MongoURI& uri) {
+ auto hookList = std::make_unique<rpc::EgressMetadataHookList>();
+ auto networkConnectionHook = std::make_unique<ReplicaSetMonitorManagerNetworkConnectionHook>();
+
+ std::shared_ptr<executor::NetworkInterface> networkInterface =
+ executor::makeNetworkInterface("ReplicaSetMonitor-TestTaskExecutor",
+ std::move(networkConnectionHook),
+ std::move(hookList));
+ _connectionManager = std::make_unique<ReplicaSetMonitorConnectionManager>(networkInterface);
+
+ auto pool = std::make_unique<executor::NetworkInterfaceThreadPool>(networkInterface.get());
+
+ _taskExecutor =
+ std::make_shared<executor::ThreadPoolTaskExecutor>(std::move(pool), networkInterface);
+ _taskExecutor->startup();
+
+ _replSetMonitor = std::make_shared<StreamableReplicaSetMonitor>(
+ uri, _taskExecutor, _connectionManager, [] {});
+ auto topologyManager = std::make_unique<sdam::MockTopologyManager>();
+ _topologyManagerPtr = topologyManager.get();
+
+ _replSetMonitor->initForTesting(std::move(topologyManager));
+ ReplicaSetMonitorManager::get()->installMonitor_forTests(_replSetMonitor);
+}
+
+sdam::MockTopologyManager* StreamableReplicaSetMonitorForTesting::getTopologyManager() {
+ return _topologyManagerPtr;
+}
+
+} // namespace mongo
diff --git a/src/mongo/client/streamable_replica_set_monitor_for_testing.h b/src/mongo/client/streamable_replica_set_monitor_for_testing.h
new file mode 100644
index 00000000000..bc481ad735e
--- /dev/null
+++ b/src/mongo/client/streamable_replica_set_monitor_for_testing.h
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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.
+ */
+
+#pragma once
+
+#include "mongo/client/replica_set_monitor_manager.h"
+#include "mongo/client/sdam/mock_topology_manager.h"
+#include "mongo/client/streamable_replica_set_monitor.h"
+
+namespace mongo {
+
+/**
+ * Sets up a streamable replica set monitor for testing that does not automatically refresh on its
+ * own, and with configurable topology.
+ */
+class StreamableReplicaSetMonitorForTesting {
+public:
+ ~StreamableReplicaSetMonitorForTesting();
+
+ void setup(const MongoURI& uri);
+
+ sdam::MockTopologyManager* getTopologyManager();
+
+private:
+ // Executor for monitoring replica sets.
+ std::shared_ptr<executor::TaskExecutor> _taskExecutor;
+
+ // Allows closing connections established by the network interface associated with the
+ // _taskExecutor instance
+ std::shared_ptr<ReplicaSetMonitorConnectionManager> _connectionManager;
+
+ // Allows changing replica set topology for mocking replica set targetter response.
+ sdam::MockTopologyManager* _topologyManagerPtr;
+
+ // ReplicaSetMonitorManager only stores weak_ptrs, so we need to keep the monitor alive.
+ std::shared_ptr<StreamableReplicaSetMonitor> _replSetMonitor;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
index d07efa4226a..554504fce12 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/client/connpool.h"
#include "mongo/client/replica_set_monitor.h"
#include "mongo/client/replica_set_monitor_protocol_test_util.h"
+#include "mongo/client/streamable_replica_set_monitor_for_testing.h"
#include "mongo/config.h"
#include "mongo/db/client.h"
#include "mongo/db/commands/feature_compatibility_version_document_gen.h"
@@ -171,8 +172,10 @@ public:
ServiceContextMongoDTest::setUp();
auto serviceContext = getServiceContext();
- // Only the ReplicaSetMonitor scanning protocol supports mock connections.
- ReplicaSetMonitorProtocolTestUtil::setRSMProtocol(ReplicaSetMonitorProtocol::kScanning);
+ // Fake replSet just for creating consistent URI for monitor
+ MockReplicaSet replSet("donorSet", 1, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ _rsmMonitor.setup(replSet.getURI());
+
ConnectionString::setConnectionHook(mongo::MockConnRegistry::get()->getConnStrHook());
// Set up clocks.
@@ -402,6 +405,10 @@ protected:
return instance->_stateDoc;
}
+ sdam::MockTopologyManager* getTopologyManager() {
+ return _rsmMonitor.getTopologyManager();
+ }
+
/**
* Advance the time by millis on both clock source mocks.
*/
@@ -445,6 +452,10 @@ protected:
client->insert(NamespaceString::kServerConfigurationNamespace.ns(), fcvDoc.toBSON());
}
+ ClockSource* clock() {
+ return _clkSource.get();
+ }
+
private:
std::shared_ptr<ClockSourceMock> _clkSource = std::make_shared<ClockSourceMock>();
@@ -452,6 +463,8 @@ private:
logv2::LogComponent::kReplication, logv2::LogSeverity::Debug(1)};
unittest::MinimumLoggedSeverityGuard _tenantMigrationSeverityGuard{
logv2::LogComponent::kTenantMigration, logv2::LogSeverity::Debug(1)};
+
+ StreamableReplicaSetMonitorForTesting _rsmMonitor;
};
#ifdef MONGO_CONFIG_SSL
@@ -517,7 +530,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -568,7 +581,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_S
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -620,7 +633,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -651,25 +664,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
auto now = opCtx->getServiceContext()->getFastClockSource()->now();
instance->excludeDonorHost_forTest(hosts.at(0), now + Milliseconds(500));
- AtomicWord<bool> runReplMonitor{true};
- // Keep scanning the replica set while waiting to reach the failpoint. This would normally
- // be automatic but that doesn't work with mock replica sets.
- stdx::thread replMonitorThread([&] {
- Client::initThread("replMonitorThread");
- while (runReplMonitor.load()) {
- auto monitor = ReplicaSetMonitor::get(replSet.getSetName());
- // Monitor may not have been created yet.
- if (monitor) {
- monitor->runScanForMockReplicaSet();
- }
- mongo::sleepmillis(100);
- }
- });
-
hangFp->setMode(FailPoint::off);
taskFp->waitForTimesEntered(taskFpInitialTimesEntered + 1);
- runReplMonitor.store(false);
- replMonitorThread.join();
auto* client = getClient(instance.get());
auto* oplogFetcherClient = getOplogFetcherClient(instance.get());
@@ -695,7 +691,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -767,7 +763,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -801,25 +797,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
instance->excludeDonorHost_forTest(host, now + Milliseconds(500));
}
- AtomicWord<bool> runReplMonitor{true};
- // Keep scanning the replica set while waiting to reach the failpoint. This would normally
- // be automatic but that doesn't work with mock replica sets.
- stdx::thread replMonitorThread([&] {
- Client::initThread("replMonitorThread");
- while (runReplMonitor.load()) {
- auto monitor = ReplicaSetMonitor::get(replSet.getSetName());
- // Monitor may not have been created yet.
- if (monitor) {
- monitor->runScanForMockReplicaSet();
- }
- mongo::sleepmillis(100);
- }
- });
-
hangFp->setMode(FailPoint::off);
taskFp->waitForTimesEntered(taskFpInitialTimesEntered + 1);
- runReplMonitor.store(false);
- replMonitorThread.join();
auto* client = getClient(instance.get());
auto* oplogFetcherClient = getOplogFetcherClient(instance.get());
@@ -845,7 +824,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -914,7 +893,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -986,7 +965,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -1018,26 +997,10 @@ TEST_F(TenantMigrationRecipientServiceTest,
auto now = opCtx->getServiceContext()->getFastClockSource()->now();
auto excludeTime = Milliseconds(500);
instance->excludeDonorHost_forTest(hosts.at(2), now + excludeTime);
-
- AtomicWord<bool> runReplMonitor{true};
- // Keep scanning the replica set while waiting to reach the failpoint. This would normally
- // be automatic but that doesn't work with mock replica sets.
- stdx::thread replMonitorThread([&] {
- Client::initThread("replMonitorThread");
- while (runReplMonitor.load()) {
- auto monitor = ReplicaSetMonitor::get(replSet.getSetName());
- // Monitor may not have been created yet.
- if (monitor) {
- monitor->runScanForMockReplicaSet();
- }
- mongo::sleepmillis(100);
- }
- });
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
hangFp->setMode(FailPoint::off);
taskFp->waitForTimesEntered(taskFpInitialTimesEntered + 1);
- runReplMonitor.store(false);
- replMonitorThread.join();
auto* client = getClient(instance.get());
auto* oplogFetcherClient = getOplogFetcherClient(instance.get());
@@ -1063,7 +1026,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -1096,6 +1059,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
auto now = opCtx->getServiceContext()->getFastClockSource()->now();
auto excludeTime = Milliseconds(500);
instance->excludeDonorHost_forTest(hosts.at(2), now + excludeTime);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
hangFp->setMode(FailPoint::off);
taskFp->waitForTimesEntered(taskFpInitialTimesEntered + 1);
@@ -1136,6 +1100,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
// Insert the remote majority optime into the oplogs of the first two hosts.
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
+
const auto hosts = replSet.getHosts();
const std::vector<HostAndPort> advancedOpTimeHosts = {hosts.begin(), hosts.begin() + 2};
@@ -1192,6 +1158,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
// Insert the remote majority optime into the oplogs of the first two hosts.
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
+
const auto hosts = replSet.getHosts();
const std::vector<HostAndPort> advancedOpTimeHosts = {hosts[0], hosts[1]};
@@ -1252,11 +1220,12 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 2, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
// Primary is unavailable.
replSet.kill(replSet.getHosts()[0].toString());
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
@@ -1347,6 +1316,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1385,6 +1355,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const OpTime newTopOfOplogOpTime(Timestamp(6, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1423,7 +1394,9 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
+
SessionTxnRecord lastTxn(makeLogicalSessionIdForTest(), 100, txnLastWriteOpTime, Date_t());
lastTxn.setStartOpTime(txnStartOpTime);
lastTxn.setState(DurableTxnStateEnum::kInProgress);
@@ -1468,7 +1441,9 @@ TEST_F(TenantMigrationRecipientServiceTest,
const OpTime newTopOfOplogOpTime(Timestamp(6, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
+
SessionTxnRecord lastTxn(makeLogicalSessionIdForTest(), 100, txnLastWriteOpTime, Date_t());
lastTxn.setStartOpTime(txnStartOpTime);
lastTxn.setState(DurableTxnStateEnum::kInProgress);
@@ -1509,6 +1484,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
@@ -1542,6 +1518,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartOplogFe
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1590,6 +1567,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartsCloner
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
// Skip the cloners in this test, so we provide an empty list of databases.
@@ -1650,6 +1628,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherFailsDuringOplogApplicat
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1705,6 +1684,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherResumesFromTopOfOplogBuf
const OpTime dataConsistentOpTime(Timestamp(4, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, initialOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1811,6 +1791,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherNoDocInBufferToResumeFro
const OpTime dataConsistentOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, startFetchingOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -1919,6 +1900,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromLastNoOpOplog
const OpTime dataConsistentOpTime(Timestamp(4, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, clonerFinishedOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2043,6 +2025,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const OpTime dataConsistentOpTime(Timestamp(4, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, startApplyingOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2207,6 +2190,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromStartDonorApp
const OpTime dataConsistentOpTime(Timestamp(4, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, startApplyingOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2351,6 +2335,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const OpTime dataConsistentOpTime(Timestamp(4, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, startFetchingOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2456,6 +2441,7 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierFails) {
const OpTime injectedEntryOpTime(Timestamp(6, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2521,6 +2507,7 @@ TEST_F(TenantMigrationRecipientServiceTest, StoppingApplierAllowsCompletion) {
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2575,6 +2562,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientAddResumeTok
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /*dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2678,6 +2666,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientAddResumeTok
TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_BeforeRun) {
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
@@ -2714,6 +2704,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToIniti
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
@@ -2745,6 +2737,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_WaitUntilSt
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2828,6 +2821,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterStartO
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2890,6 +2884,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterConsis
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -2977,6 +2972,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterFail)
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3059,6 +3055,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToMarkG
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
+
TenantMigrationRecipientDocument initialStateDocument(
migrationUUID,
replSet.getConnectionString(),
@@ -3108,7 +3106,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientServiceRecor
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -3143,7 +3141,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -3182,7 +3180,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -3230,7 +3228,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const UUID migrationUUID = UUID::gen();
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
-
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, OpTime(kDefaultStartMigrationTimestamp, 1));
TenantMigrationRecipientDocument initialStateDocument(
@@ -3265,6 +3263,7 @@ TEST_F(TenantMigrationRecipientServiceTest, WaitUntilMigrationReachesReturnAfter
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3324,6 +3323,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesRetriableFetcherErr
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3387,6 +3387,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesNonRetriableFetcher
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3445,6 +3446,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientWillNotRetryOnExternalInter
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3502,6 +3504,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesRetriableClonerErro
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3567,6 +3570,7 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientReceivesNonRetriableClonerE
const OpTime topOfOplogOpTime(Timestamp(5, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3614,6 +3618,7 @@ TEST_F(TenantMigrationRecipientServiceTest, IncrementNumRestartsDueToRecipientFa
const OpTime topOfOplogOpTime(Timestamp(1, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
@@ -3664,6 +3669,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
const OpTime topOfOplogOpTime(Timestamp(1, 1), 1);
MockReplicaSet replSet("donorSet", 3, true /* hasPrimary */, true /* dollarPrefixHosts */);
+ getTopologyManager()->setTopologyDescription(replSet.getTopologyDescription(clock()));
insertTopOfOplog(&replSet, topOfOplogOpTime);
TenantMigrationRecipientDocument initialStateDocument(
diff --git a/src/mongo/dbtests/SConscript b/src/mongo/dbtests/SConscript
index a6f5f42328b..09bc1e576d3 100644
--- a/src/mongo/dbtests/SConscript
+++ b/src/mongo/dbtests/SConscript
@@ -57,6 +57,7 @@ env.Library(
LIBDEPS=[
'$BUILD_DIR/mongo/client/clientdriver_network',
'$BUILD_DIR/mongo/client/dbclient_mockcursor',
+ '$BUILD_DIR/mongo/client/replica_set_monitor_test_helper',
'$BUILD_DIR/mongo/db/repl/replica_set_messages'
],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/dbtests/mock/mock_replica_set.cpp b/src/mongo/dbtests/mock/mock_replica_set.cpp
index 358c880de45..add43163b36 100644
--- a/src/mongo/dbtests/mock/mock_replica_set.cpp
+++ b/src/mongo/dbtests/mock/mock_replica_set.cpp
@@ -31,6 +31,7 @@
#include "mongo/dbtests/mock/mock_replica_set.h"
+#include "mongo/client/sdam/topology_description_builder.h"
#include "mongo/db/repl/member_state.h"
#include "mongo/dbtests/mock/mock_conn_registry.h"
#include "mongo/dbtests/mock/mock_dbclient_connection.h"
@@ -199,90 +200,96 @@ void MockReplicaSet::restore(const string& hostAndPort) {
_nodeMap[hostAndPort]->reboot();
}
-void MockReplicaSet::mockIsMasterCmd() {
- for (ReplNodeMap::iterator nodeIter = _nodeMap.begin(); nodeIter != _nodeMap.end();
- ++nodeIter) {
- const string& hostAndPort = nodeIter->first;
+BSONObj MockReplicaSet::mockHelloResponseFor(const MockRemoteDBServer& server) const {
+ const auto hostAndPort = server.getServerHostAndPort();
- BSONObjBuilder builder;
- builder.append("setName", _setName);
+ BSONObjBuilder builder;
+ builder.append("setName", _setName);
- const MemberConfig* member = _replConfig.findMemberByHostAndPort(HostAndPort(hostAndPort));
- if (!member) {
- builder.append("ismaster", false);
- builder.append("secondary", false);
+ const MemberConfig* member = _replConfig.findMemberByHostAndPort(hostAndPort);
+ if (!member) {
+ builder.append("ismaster", false);
+ builder.append("secondary", false);
- vector<string> hostList;
- builder.append("hosts", hostList);
- } else {
- const bool isPrimary = hostAndPort == getPrimary();
- builder.append("ismaster", isPrimary);
- builder.append("secondary", !isPrimary);
-
- {
- // TODO: add passives & arbiters
- vector<string> hostList;
- if (hasPrimary()) {
- hostList.push_back(getPrimary());
- }
-
- const vector<string> secondaries = getSecondaries();
- for (vector<string>::const_iterator secIter = secondaries.begin();
- secIter != secondaries.end();
- ++secIter) {
- hostList.push_back(*secIter);
- }
-
- builder.append("hosts", hostList);
- }
+ vector<string> hostList;
+ builder.append("hosts", hostList);
+ } else {
+ const bool isPrimary = hostAndPort.toString() == getPrimary();
+ builder.append("ismaster", isPrimary);
+ builder.append("secondary", !isPrimary);
+ {
+ // TODO: add passives & arbiters
+ vector<string> hostList;
if (hasPrimary()) {
- builder.append("primary", getPrimary());
+ hostList.push_back(getPrimary());
}
- if (member->isArbiter()) {
- builder.append("arbiterOnly", true);
+ const vector<string> secondaries = getSecondaries();
+ for (vector<string>::const_iterator secIter = secondaries.begin();
+ secIter != secondaries.end();
+ ++secIter) {
+ hostList.push_back(*secIter);
}
- if (member->getPriority() == 0 && !member->isArbiter()) {
- builder.append("passive", true);
- }
+ builder.append("hosts", hostList);
+ }
- if (member->getSecondaryDelay().count()) {
- builder.appendNumber("secondaryDelaySecs",
- durationCount<Seconds>(member->getSecondaryDelay()));
- }
+ if (hasPrimary()) {
+ builder.append("primary", getPrimary());
+ }
- if (member->isHidden()) {
- builder.append("hidden", true);
- }
+ if (member->isArbiter()) {
+ builder.append("arbiterOnly", true);
+ }
- if (!member->shouldBuildIndexes()) {
- builder.append("buildIndexes", false);
- }
+ if (member->getPriority() == 0 && !member->isArbiter()) {
+ builder.append("passive", true);
+ }
+
+ if (member->getSecondaryDelay().count()) {
+ builder.appendNumber("secondaryDelaySecs",
+ durationCount<Seconds>(member->getSecondaryDelay()));
+ }
- const ReplSetTagConfig tagConfig = _replConfig.getTagConfig();
- if (member->hasTags()) {
- BSONObjBuilder tagBuilder;
- for (MemberConfig::TagIterator tag = member->tagsBegin(); tag != member->tagsEnd();
- ++tag) {
- std::string tagKey = tagConfig.getTagKey(*tag);
- if (tagKey[0] == '$') {
- // Filter out internal tags
- continue;
- }
- tagBuilder.append(tagKey, tagConfig.getTagValue(*tag));
+ if (member->isHidden()) {
+ builder.append("hidden", true);
+ }
+
+ if (!member->shouldBuildIndexes()) {
+ builder.append("buildIndexes", false);
+ }
+
+ const ReplSetTagConfig tagConfig = _replConfig.getTagConfig();
+ if (member->hasTags()) {
+ BSONObjBuilder tagBuilder;
+ for (MemberConfig::TagIterator tag = member->tagsBegin(); tag != member->tagsEnd();
+ ++tag) {
+ std::string tagKey = tagConfig.getTagKey(*tag);
+ if (tagKey[0] == '$') {
+ // Filter out internal tags
+ continue;
}
- builder.append("tags", tagBuilder.done());
+ tagBuilder.append(tagKey, tagConfig.getTagValue(*tag));
}
+ builder.append("tags", tagBuilder.done());
}
+ }
- builder.append("me", hostAndPort);
- builder.append("ok", true);
+ builder.append("me", hostAndPort.toString());
+ builder.append("ok", 1);
+
+ return builder.obj();
+}
+
+void MockReplicaSet::mockIsMasterCmd() {
+ for (ReplNodeMap::iterator nodeIter = _nodeMap.begin(); nodeIter != _nodeMap.end();
+ ++nodeIter) {
+ auto isMaster = mockHelloResponseFor(*nodeIter->second);
// DBClientBase::isMaster() sends "ismaster", but ReplicaSetMonitor sends "isMaster".
- nodeIter->second->setCommandReply("ismaster", builder.done());
- nodeIter->second->setCommandReply("isMaster", builder.done());
+ nodeIter->second->setCommandReply("ismaster", isMaster);
+ nodeIter->second->setCommandReply("isMaster", isMaster);
}
}
@@ -354,4 +361,30 @@ void MockReplicaSet::mockReplSetGetStatusCmd() {
node->setCommandReply("replSetGetStatus", fullStatBuilder.done());
}
}
+
+sdam::TopologyDescriptionPtr MockReplicaSet::getTopologyDescription(
+ ClockSource* clockSource) const {
+ sdam::TopologyDescriptionBuilder builder;
+
+ builder.withSetName(_setName);
+ builder.withTopologyType(hasPrimary() ? sdam::TopologyType::kReplicaSetWithPrimary
+ : sdam::TopologyType::kReplicaSetNoPrimary);
+
+ std::vector<sdam::ServerDescriptionPtr> servers;
+ for (const auto& nodeEntry : _nodeMap) {
+ const auto& server = *nodeEntry.second;
+ if (server.isRunning()) {
+ auto helloBSON = mockHelloResponseFor(server);
+ sdam::HelloOutcome hello(server.getServerHostAndPort(), helloBSON);
+ servers.push_back(std::make_shared<sdam::ServerDescription>(clockSource, hello));
+ } else {
+ sdam::HelloOutcome hello(server.getServerHostAndPort(), {}, "mock server unreachable");
+ servers.push_back(std::make_shared<sdam::ServerDescription>(clockSource, hello));
+ }
+ }
+
+ builder.withServers(servers);
+ return builder.instance();
+}
+
} // namespace mongo
diff --git a/src/mongo/dbtests/mock/mock_replica_set.h b/src/mongo/dbtests/mock/mock_replica_set.h
index 01929b0e203..7d87afce62a 100644
--- a/src/mongo/dbtests/mock/mock_replica_set.h
+++ b/src/mongo/dbtests/mock/mock_replica_set.h
@@ -29,6 +29,7 @@
#pragma once
+#include "mongo/client/sdam/sdam_datatypes.h"
#include "mongo/db/repl/member_config.h"
#include "mongo/db/repl/repl_set_config.h"
#include "mongo/dbtests/mock/mock_remote_db_server.h"
@@ -38,6 +39,9 @@
#include <vector>
namespace mongo {
+
+class ClockSource;
+
/**
* This is a helper class for managing a replica set consisting of
* MockRemoteDBServer instances.
@@ -124,6 +128,11 @@ public:
*/
void restore(const std::string& hostName);
+ /**
+ * Returns a topology description reflecting the current state of this replica set.
+ */
+ sdam::TopologyDescriptionPtr getTopologyDescription(ClockSource* clockSource) const;
+
private:
typedef std::map<std::string, MockRemoteDBServer*> ReplNodeMap;
@@ -134,6 +143,11 @@ private:
void mockIsMasterCmd();
/**
+ * Mock the hello response for the given server.
+ */
+ BSONObj mockHelloResponseFor(const MockRemoteDBServer& server) const;
+
+ /**
* Mocks the replSetGetStatus command based on the current states of the
* mocked servers.
*/