diff options
author | Randolph Tan <randolph@10gen.com> | 2021-03-04 23:08:50 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-13 21:20:05 +0000 |
commit | ec6dffd110749232f15e0498e48e4f849cf7e6a0 (patch) | |
tree | 7f071f0f90813aea31af7413858f9ee2caa03dd1 /src/mongo | |
parent | b28b53d23843c0e42e0751673c76088a3e7e60fa (diff) | |
download | mongo-ec6dffd110749232f15e0498e48e4f849cf7e6a0.tar.gz |
SERVER-54292 remove dependency on scanning replica set monitor in tenant_migration_recipient_service_tests
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/client/SConscript | 12 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor_manager.cpp | 6 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor_manager.h | 1 | ||||
-rw-r--r-- | src/mongo/client/streamable_replica_set_monitor_for_testing.cpp | 79 | ||||
-rw-r--r-- | src/mongo/client/streamable_replica_set_monitor_for_testing.h | 65 | ||||
-rw-r--r-- | src/mongo/db/repl/tenant_migration_recipient_service_test.cpp | 140 | ||||
-rw-r--r-- | src/mongo/dbtests/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/dbtests/mock/mock_replica_set.cpp | 163 | ||||
-rw-r--r-- | src/mongo/dbtests/mock/mock_replica_set.h | 14 |
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. */ |