SERVER-126387 Extend server_selector_test.cpp tests for Injector tag when configOnly disabled (#53597)

GitOrigin-RevId: 9aa416d614fca4237e94a2f0b1de6a71507e62d8
This commit is contained in:
Igor Praznik 2026-05-21 12:01:50 +02:00 committed by MongoDB Bot
parent 70bba57744
commit ea0c77bbdd

View File

@ -151,6 +151,68 @@ public:
ServerSelector selector = ServerSelector(sdamConfiguration);
static ServerDescriptionPtr makeReplicaSetPrimary(HostAndPort address,
std::initializer_list<HostAndPort> hosts,
std::string processType = "") {
auto builder = ServerDescriptionBuilder()
.withAddress(address)
.withType(ServerType::kRSPrimary)
.withLastUpdateTime(Date_t::now())
.withLastWriteDate(Date_t::now())
.withRtt(Milliseconds{1})
.withSetName(SET_NAME)
.withMinWireVersion(WireVersion::SUPPORTS_OP_MSG)
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.withElectionId(kOidOne)
.withSetVersion(100);
for (const auto& host : hosts) {
builder.withHost(host);
}
if (!processType.empty()) {
builder.withTag(ServerDescription::kProcessTypeTagKey, processType);
}
return builder.instance();
}
static ServerDescriptionPtr makeReplicaSetSecondary(HostAndPort address,
std::string processType = "") {
auto builder = ServerDescriptionBuilder()
.withAddress(address)
.withType(ServerType::kRSSecondary)
.withRtt(Milliseconds{1})
.withSetName(SET_NAME)
.withMinWireVersion(WireVersion::SUPPORTS_OP_MSG)
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.withLastUpdateTime(Date_t::now())
.withLastWriteDate(Date_t::now());
if (!processType.empty()) {
builder.withTag(ServerDescription::kProcessTypeTagKey, processType);
}
return builder.instance();
}
// Topology with a normal primary (s0), an injector-tagged secondary (s1) and a normal
// secondary (s2).
struct InjectorSecondaryTopology {
std::shared_ptr<TopologyDescription> topologyDescription;
TopologyStateMachine stateMachine;
InjectorSecondaryTopology(const SdamConfiguration& config)
: topologyDescription(std::make_shared<TopologyDescription>(config)),
stateMachine(config) {
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetPrimary(HostAndPort("s0"),
{HostAndPort("s0"), HostAndPort("s1"), HostAndPort("s2")}));
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetSecondary(HostAndPort("s1"), ServerDescription::kInjectorTagValue));
stateMachine.onServerDescription(*topologyDescription,
makeReplicaSetSecondary(HostAndPort("s2")));
}
};
// Topology with an injector-tagged primary (s0) and a normal secondary (s1).
struct InjectorPrimaryTopology {
std::shared_ptr<TopologyDescription> topologyDescription;
TopologyStateMachine stateMachine;
@ -158,35 +220,32 @@ public:
InjectorPrimaryTopology(const SdamConfiguration& config)
: topologyDescription(std::make_shared<TopologyDescription>(config)),
stateMachine(config) {
const auto injector = ServerDescriptionBuilder()
.withAddress(HostAndPort("s0"))
.withType(ServerType::kRSPrimary)
.withLastUpdateTime(Date_t::now())
.withLastWriteDate(Date_t::now())
.withRtt(Milliseconds{1})
.withSetName("set")
.withHost(HostAndPort("s0"))
.withHost(HostAndPort("s1"))
.withMinWireVersion(WireVersion::SUPPORTS_OP_MSG)
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.withTag(ServerDescription::kProcessTypeTagKey,
ServerDescription::kInjectorTagValue)
.withElectionId(kOidOne)
.withSetVersion(100)
.instance();
stateMachine.onServerDescription(*topologyDescription, injector);
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetPrimary(HostAndPort("s0"),
{HostAndPort("s0"), HostAndPort("s1")},
ServerDescription::kInjectorTagValue));
stateMachine.onServerDescription(*topologyDescription,
makeReplicaSetSecondary(HostAndPort("s1")));
}
};
const auto secondary = ServerDescriptionBuilder()
.withAddress(HostAndPort("s1"))
.withType(ServerType::kRSSecondary)
.withRtt(Milliseconds{1})
.withSetName("set")
.withMinWireVersion(WireVersion::SUPPORTS_OP_MSG)
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.withLastUpdateTime(Date_t::now())
.withLastWriteDate(Date_t::now())
.instance();
stateMachine.onServerDescription(*topologyDescription, secondary);
// Topology where every node is injector-tagged (s0 primary, s1 secondary).
struct AllInjectorsTopology {
std::shared_ptr<TopologyDescription> topologyDescription;
TopologyStateMachine stateMachine;
AllInjectorsTopology(const SdamConfiguration& config)
: topologyDescription(std::make_shared<TopologyDescription>(config)),
stateMachine(config) {
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetPrimary(HostAndPort("s0"),
{HostAndPort("s0"), HostAndPort("s1")},
ServerDescription::kInjectorTagValue));
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetSecondary(HostAndPort("s1"), ServerDescription::kInjectorTagValue));
}
};
};
@ -1069,32 +1128,154 @@ TEST_F(ConfigOnlyServerSelectorTest, ShouldExcludeInjectorFromPrimaryPreferredSe
TEST_F(ServerSelectorTestFixture, ShouldNotExcludeInjectorWhenNotConfigOnly) {
InjectorPrimaryTopology topo(sdamConfiguration);
auto result = selector.selectServers(
auto primaryOnlyResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::PrimaryOnly), {});
ASSERT(result);
ASSERT_EQ(1, result->size());
ASSERT_EQ(HostAndPort("s0"), (*result)[0]->getAddress());
ASSERT(primaryOnlyResult);
ASSERT_EQ(1, primaryOnlyResult->size());
ASSERT_EQ(HostAndPort("s0"), (*primaryOnlyResult)[0]->getAddress());
auto nearestResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::Nearest), {});
ASSERT(nearestResult);
ASSERT_EQ(2, nearestResult->size());
bool foundInjectorPrimary = false;
bool foundSecondary = false;
for (const auto& server : *nearestResult) {
foundInjectorPrimary |= server->getAddress() == HostAndPort("s0");
foundSecondary |= server->getAddress() == HostAndPort("s1");
}
ASSERT_TRUE(foundInjectorPrimary);
ASSERT_TRUE(foundSecondary);
auto primaryPreferredResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::PrimaryPreferred), {});
ASSERT(primaryPreferredResult);
ASSERT_EQ(1, primaryPreferredResult->size());
ASSERT_EQ(HostAndPort("s0"), (*primaryPreferredResult)[0]->getAddress());
}
TEST_F(ConfigOnlyServerSelectorTest, ShouldExcludeInjectorSecondaryFromSecondaryOnlySelection) {
InjectorSecondaryTopology topo(sdamConfiguration);
std::map<HostAndPort, int> frequencyInfo{
{HostAndPort("s0"), 0}, {HostAndPort("s1"), 0}, {HostAndPort("s2"), 0}};
for (int i = 0; i < NUM_ITERATIONS; i++) {
auto server = selector.selectServer(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::SecondaryOnly), {});
if (server) {
frequencyInfo[(*server)->getAddress()]++;
}
}
ASSERT_FALSE(frequencyInfo[HostAndPort("s0")]);
ASSERT_FALSE(frequencyInfo[HostAndPort("s1")]);
ASSERT_EQ(frequencyInfo[HostAndPort("s2")], NUM_ITERATIONS);
}
TEST_F(ConfigOnlyServerSelectorTest,
ShouldExcludeInjectorSecondaryFromSecondaryPreferredSelection) {
InjectorSecondaryTopology topo(sdamConfiguration);
std::map<HostAndPort, int> frequencyInfo{
{HostAndPort("s0"), 0}, {HostAndPort("s1"), 0}, {HostAndPort("s2"), 0}};
for (int i = 0; i < NUM_ITERATIONS; i++) {
auto server =
selector.selectServer(topo.topologyDescription,
ReadPreferenceSetting(ReadPreference::SecondaryPreferred),
{});
if (server) {
frequencyInfo[(*server)->getAddress()]++;
}
}
ASSERT_FALSE(frequencyInfo[HostAndPort("s0")]);
ASSERT_FALSE(frequencyInfo[HostAndPort("s1")]);
ASSERT_EQ(frequencyInfo[HostAndPort("s2")], NUM_ITERATIONS);
}
TEST_F(ConfigOnlyServerSelectorTest, ShouldExcludeInjectorSecondaryFromNearestSelection) {
InjectorSecondaryTopology topo(sdamConfiguration);
std::map<HostAndPort, int> frequencyInfo{
{HostAndPort("s0"), 0}, {HostAndPort("s1"), 0}, {HostAndPort("s2"), 0}};
for (int i = 0; i < NUM_ITERATIONS; i++) {
auto server = selector.selectServer(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::Nearest), {});
if (server) {
frequencyInfo[(*server)->getAddress()]++;
}
}
ASSERT_FALSE(frequencyInfo[HostAndPort("s1")]);
ASSERT(frequencyInfo[HostAndPort("s0")] || frequencyInfo[HostAndPort("s2")]);
}
TEST_F(ServerSelectorTestFixture, ShouldNotExcludeInjectorSecondaryWhenNotConfigOnly) {
InjectorSecondaryTopology topo(sdamConfiguration);
auto secondaryOnlyResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::SecondaryOnly), {});
ASSERT(secondaryOnlyResult);
ASSERT_EQ(2, secondaryOnlyResult->size());
auto secondaryPreferredResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::SecondaryPreferred), {});
ASSERT(secondaryPreferredResult);
ASSERT_EQ(2, secondaryPreferredResult->size());
auto nearestResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::Nearest), {});
ASSERT(nearestResult);
ASSERT_EQ(3, nearestResult->size());
}
class ConfigOnlyAllInjectorsTest : public ConfigOnlyServerSelectorTest,
public ::testing::WithParamInterface<ReadPreference> {};
TEST_P(ConfigOnlyAllInjectorsTest, ShouldReturnNoneWhenAllNodesAreInjectors) {
AllInjectorsTopology topo(sdamConfiguration);
auto pref = GetParam();
auto result = selector.selectServers(topo.topologyDescription, ReadPreferenceSetting(pref), {});
ASSERT_EQ(adaptForAssert(boost::none), adaptForAssert(result));
}
INSTANTIATE_TEST_SUITE_P(ReadPreferences,
ConfigOnlyAllInjectorsTest,
::testing::Values(ReadPreference::PrimaryOnly,
ReadPreference::SecondaryOnly,
ReadPreference::PrimaryPreferred,
ReadPreference::SecondaryPreferred,
ReadPreference::Nearest));
TEST_F(ServerSelectorTestFixture, ShouldNotExcludeAnyNodesWhenAllInjectorsAndNotConfigOnly) {
AllInjectorsTopology topo(sdamConfiguration);
auto primaryOnlyResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::PrimaryOnly), {});
ASSERT(primaryOnlyResult);
ASSERT_EQ(1, primaryOnlyResult->size());
ASSERT_EQ(HostAndPort("s0"), (*primaryOnlyResult)[0]->getAddress());
auto secondaryOnlyResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::SecondaryOnly), {});
ASSERT(secondaryOnlyResult);
ASSERT_EQ(1, secondaryOnlyResult->size());
ASSERT_EQ(HostAndPort("s1"), (*secondaryOnlyResult)[0]->getAddress());
auto nearestResult = selector.selectServers(
topo.topologyDescription, ReadPreferenceSetting(ReadPreference::Nearest), {});
ASSERT(nearestResult);
ASSERT_EQ(2, nearestResult->size());
}
TEST_F(ServerSelectorTestFixture, ShouldNotExcludeNonInjectorWithOtherTags) {
TopologyStateMachine stateMachine(sdamConfiguration);
auto topologyDescription = std::make_shared<TopologyDescription>(sdamConfiguration);
const auto primary = ServerDescriptionBuilder()
.withAddress(HostAndPort("s0"))
.withType(ServerType::kRSPrimary)
.withLastUpdateTime(Date_t::now())
.withLastWriteDate(Date_t::now())
.withRtt(Milliseconds{1})
.withSetName("set")
.withHost(HostAndPort("s0"))
.withMinWireVersion(WireVersion::SUPPORTS_OP_MSG)
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.withTag(ServerDescription::kProcessTypeTagKey, "NORMAL")
.withElectionId(kOidOne)
.withSetVersion(100)
.instance();
stateMachine.onServerDescription(*topologyDescription, primary);
stateMachine.onServerDescription(
*topologyDescription,
makeReplicaSetPrimary(HostAndPort("s0"), {HostAndPort("s0")}, "NORMAL"));
auto result = selector.selectServers(
topologyDescription, ReadPreferenceSetting(ReadPreference::PrimaryOnly), {});