SERVER-111031 Cluster wide default read/write concerns are not honored during promotion to sharded (#45362)

GitOrigin-RevId: c2d3cf79d6a24bbc97c3e1e21c859cba56b66448
This commit is contained in:
Allison Easton 2025-12-22 15:10:58 +01:00 committed by MongoDB Bot
parent 1b2b610f43
commit 5f19c11ae9
18 changed files with 316 additions and 53 deletions

1
.github/CODEOWNERS vendored
View File

@ -1648,6 +1648,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/jstests/sharding/**/remove_shard_*.js @10gen/server-catalog-and-routing-routing-and-topology @svc-auto-approve-bot
/jstests/sharding/**/reporting_compound_wildcard_index_prefixed_by_shard_key.js @10gen/server-catalog-and-routing-ddl @svc-auto-approve-bot
/jstests/sharding/**/index_commands_shard_targeting.js @10gen/server-catalog-and-routing-ddl @svc-auto-approve-bot
/jstests/sharding/**/shard_identity_rollback.js @10gen/server-catalog-and-routing @svc-auto-approve-bot
# The following patterns are parsed from ./jstests/sharding/analyze_shard_key/OWNERS.yml
/jstests/sharding/analyze_shard_key/**/* @10gen/server-cluster-scalability @svc-auto-approve-bot

View File

@ -698,6 +698,8 @@ const internalCommandsMap = {
testname: "_shardsvrDropDatabase",
command: {
_shardsvrDropDatabase: 1,
// This test relies on failing due to write concern not being majority since running this command on the admin database will hang.
writeConcern: {w: 1},
},
},
_shardsvrDropDatabaseParticipant: {

View File

@ -0,0 +1,240 @@
/* Tests default read/write concern value consistency before, during, and after promotion to sharded.
* @tags: [
* requires_persistence,
* ]
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {describe, beforeEach, afterEach, it} from "jstests/libs/mochalite.js";
import {stopReplicationOnSecondaries, restartReplicationOnSecondaries} from "jstests/libs/write_concern_util.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
describe("Read/write concern defaults directly against shard servers", function () {
beforeEach(() => {
let verbosity = {replication: 2, command: 2};
this.replSet = new ReplSetTest({
nodes: 2,
nodeOptions: {
setParameter: {logComponentVerbosity: verbosity},
},
});
this.replSet.startSet();
this.replSet.initiate();
this.cluster = undefined;
this.mongos = undefined;
this.dbName = "test";
this.collName = "foo";
this.counter = 1;
assert.commandWorked(this.replSet.getPrimary().getDB(this.dbName).createCollection(this.collName));
// This function expects the implicit defaults to be:
// defaultWriteConcern: {w: "majority", wtimeout: 0}
// defaultReadConcern: {level: "local"}
this.checkImplicitDefaults = function () {
jsTest.log.info("Stop replication on secondaries");
stopReplicationOnSecondaries(this.replSet, false);
jsTest.log.info("Do a write, it should time out due to missing majority");
assert.commandFailedWithCode(
this.replSet
.getPrimary()
.getDB(this.dbName)
.runCommand({insert: this.collName, documents: [{x: this.counter}], maxTimeMS: 500}),
ErrorCodes.MaxTimeMSExpired,
);
jsTest.log.info("Do a read, it should return the document anyways since the default is local");
let docFound = this.replSet
.getPrimary()
.getDB(this.dbName)
.getCollection(this.collName)
.count({x: this.counter});
assert.eq(1, docFound);
this.counter++;
jsTest.log.info("Restart replication and wait for steady");
restartReplicationOnSecondaries(this.replSet);
this.replSet.awaitReplication();
};
// This function expects the user defaults to be:
// defaultWriteConcern: {w: "majority", wtimeout: 500}
// defaultReadConcern: {level: "majority"}
// These values were chosen both for ease of testing and to ensure we aren't overlapping
// with the implicit or empty constructor defaults.
this.checkUserSpecifiedDefaults = function () {
jsTest.log.info("Stop replication on secondaries");
stopReplicationOnSecondaries(this.replSet, false);
jsTest.log.info("Do a write, it should time out due to missing majority");
assert.commandFailedWithCode(
this.replSet
.getPrimary()
.getDB(this.dbName)
.runCommand({insert: this.collName, documents: [{x: this.counter}]}),
ErrorCodes.WriteConcernTimeout,
);
jsTest.log.info("Do a read, it should not return the document since the read concern is majority");
let docFound = this.replSet
.getPrimary()
.getDB(this.dbName)
.getCollection(this.collName)
.count({x: this.counter});
assert.eq(0, docFound);
this.counter++;
jsTest.log.info("Restart replication and wait for steady");
restartReplicationOnSecondaries(this.replSet);
this.replSet.awaitReplication();
};
});
afterEach(() => {
if (this.cluster !== undefined) {
this.cluster.stop();
}
if (this.mongos !== undefined) {
MongoRunner.stopMongos(this.mongos);
}
this.replSet.stopSet();
});
it("Implicit default", () => {
jsTest.log.info("Check implicit defaults as a normal replica set");
this.checkImplicitDefaults();
jsTest.log.info("Check implicit defaults when started with --shardsvr");
this.replSet.stopSet(null, true, {});
this.replSet.startSet({"shardsvr": ""}, true);
this.checkImplicitDefaults();
jsTest.log.info("Check implicit defaults after being added to the cluster");
this.cluster = new ShardingTest({shards: 0});
assert.commandWorked(this.cluster.s.adminCommand({addShard: this.replSet.getURL()}));
// Fetch the sharding metadata so that the write doesn't have to do a refresh.
assert.commandWorked(
this.replSet.getPrimary().adminCommand({_flushRoutingTableCacheUpdates: this.dbName + "." + this.collName}),
);
this.checkImplicitDefaults();
});
it("Implicit default for config server promotion", () => {
jsTest.log.info("Check implicit defaults as a normal replica set");
this.checkImplicitDefaults();
jsTest.log.info("Check implicit defaults when started with --shardsvr");
this.replSet.stopSet(null, true, {});
this.replSet.startSet({"configsvr": "", replicaSetConfigShardMaintenanceMode: ""}, true);
this.checkImplicitDefaults();
jsTest.log.info("Check implicit defaults after being added to the cluster");
this.mongos = MongoRunner.runMongos({configdb: this.replSet.getURL()});
assert.commandWorked(this.mongos.adminCommand({transitionFromDedicatedConfigServer: 1}));
// Fetch the sharding metadata so that the write doesn't have to do a refresh.
assert.commandWorked(
this.replSet.getPrimary().adminCommand({_flushRoutingTableCacheUpdates: this.dbName + "." + this.collName}),
);
this.checkImplicitDefaults();
});
it("User specified default", () => {
jsTest.log.info("Set the defaults to something other than the implicit default");
this.cluster = new ShardingTest({shards: 0});
let conns = [this.replSet.getPrimary(), this.cluster.s];
conns.forEach((conn) => {
assert.commandWorked(
conn.adminCommand({
setDefaultRWConcern: 1,
defaultWriteConcern: {w: "majority", wtimeout: 500},
defaultReadConcern: {level: "majority"},
writeConcern: {w: "majority"},
}),
);
});
jsTest.log.info("Check user specified defaults as a normal replica set");
this.checkUserSpecifiedDefaults();
jsTest.log.info("Check user specified defaults when started with --shardsvr");
this.replSet.stopSet(null, true, {});
this.replSet.startSet({"shardsvr": ""}, true);
this.replSet.awaitReplication();
this.checkUserSpecifiedDefaults();
jsTest.log.info("Check user specified defaults after being added to the cluster");
assert.commandWorked(this.cluster.s.adminCommand({addShard: this.replSet.getURL()}));
// Fetch the sharding metadata so that the write doesn't have to do a refresh.
assert.commandWorked(
this.replSet.getPrimary().adminCommand({_flushRoutingTableCacheUpdates: this.dbName + "." + this.collName}),
);
this.checkUserSpecifiedDefaults();
});
it("User specified default for config server promotion", () => {
jsTest.log.info("Set the defaults to something other than the implicit default");
assert.commandWorked(
this.replSet.getPrimary().adminCommand({
setDefaultRWConcern: 1,
defaultWriteConcern: {w: "majority", wtimeout: 500},
defaultReadConcern: {level: "majority"},
writeConcern: {w: "majority"},
}),
);
jsTest.log.info("Check user specified defaults as a normal replica set");
this.checkUserSpecifiedDefaults();
jsTest.log.info("Check user specified defaults when started with --configsvr");
this.replSet.stopSet(null, true, {});
this.replSet.startSet({"configsvr": "", replicaSetConfigShardMaintenanceMode: ""}, true);
this.replSet.awaitReplication();
this.checkUserSpecifiedDefaults();
jsTest.log.info("Check user specified defaults after being added to the cluster");
this.mongos = MongoRunner.runMongos({configdb: this.replSet.getURL()});
assert.commandWorked(this.mongos.adminCommand({transitionFromDedicatedConfigServer: 1}));
// Fetch the sharding metadata so that the write doesn't have to do a refresh.
assert.commandWorked(
this.replSet.getPrimary().adminCommand({_flushRoutingTableCacheUpdates: this.dbName + "." + this.collName}),
);
this.checkUserSpecifiedDefaults();
});
it("Changing the default on the cluster does not change the shard's default", () => {
jsTest.log.info("Add the shard to the cluster");
this.cluster = new ShardingTest({shards: 0});
this.replSet.stopSet(null, true, {});
this.replSet.startSet({"shardsvr": ""}, true);
this.replSet.awaitReplication();
assert.commandWorked(this.cluster.s.adminCommand({addShard: this.replSet.getURL()}));
this.replSet.getPrimary().adminCommand({_flushRoutingTableCacheUpdates: this.dbName + "." + this.collName});
jsTest.log.info("Change the defaults on the config server");
assert.commandWorked(
this.cluster.s.adminCommand({
setDefaultRWConcern: 1,
defaultWriteConcern: {w: 1, wtimeout: 0},
defaultReadConcern: {level: "majority"},
writeConcern: {w: "majority"},
}),
);
jsTest.log.info("Check that the defaults are still the implicit ones via direct connection");
this.checkImplicitDefaults();
jsTest.log.info("Verify that the defaults cannot be modified on the shard");
assert.commandFailedWithCode(
this.replSet.getPrimary().adminCommand({
setDefaultRWConcern: 1,
defaultWriteConcern: {w: 1, wtimeout: 0},
defaultReadConcern: {level: "majority"},
writeConcern: {w: "majority"},
}),
51301,
);
});
});

View File

@ -142,3 +142,6 @@ filters:
- "index_commands_shard_targeting.js":
approvers:
- 10gen/server-catalog-and-routing-ddl
- "shard_identity_rollback.js":
approvers:
- 10gen/server-catalog-and-routing

View File

@ -162,6 +162,7 @@ TestData.skipCheckOrphans = true;
toShard.adminCommand({
_shardsvrCloneCatalogData: "test",
from: fromShard.host,
writeConcern: {w: 1},
}),
ErrorCodes.InvalidOptions,
);

View File

@ -141,7 +141,8 @@ jsTest.log("Testing replSetAbortPrimaryCatchUp");
});
const stopReplProducerFailPoint1 = configureFailPoint(secondary1Conn, "stopReplProducer");
stopReplProducerFailPoint1.wait();
runAsAdminUser(primary, {insert: "catch_up", documents: [{_id: 1}]}, "test");
// Since we have stopped replication on both secondaries, run this with w: 1
runAsAdminUser(primary, {insert: "catch_up", documents: [{_id: 1}], writeConcern: {w: 1}}, "test");
// Step up the first secondary, it will enter catch up indefinitely
assert.commandWorked(secondary1Conn.adminCommand({replSetStepUp: 1}));

View File

@ -44,8 +44,11 @@ let shardIdentityDoc = {
clusterId: ObjectId(),
};
// Do this explicitly with w:1 so that we don't hang waiting for replication that will never happen.
assert.commandWorked(
priConn.getDB("admin").system.version.update({_id: "shardIdentity"}, shardIdentityDoc, {upsert: true}),
priConn
.getDB("admin")
.system.version.update({_id: "shardIdentity"}, shardIdentityDoc, {upsert: true, writeConcern: {w: 1}}),
);
// Ensure sharding state on the primary was initialized
@ -62,8 +65,13 @@ secondaries.forEach(function (secondary) {
assert(!res.enabled, tojson(res));
});
// Ensure manually deleting the shardIdentity document is not allowed.
assert.writeErrorWithCode(priConn.getDB("admin").system.version.remove({_id: "shardIdentity"}), 40070);
// Ensure manually deleting the shardIdentity document is not allowed. We do this with w: 1 because
// otherwise we would wait for majority write concern of the prior op which was the write of the
// shard identity.
assert.writeErrorWithCode(
priConn.getDB("admin").system.version.remove({_id: "shardIdentity"}, {writeConcern: {w: 1}}),
40070,
);
jsTest.log("shutting down primary");
// Shut down the primary so a secondary gets elected that definitely won't have replicated the

View File

@ -284,7 +284,9 @@ const failureModes = {
stopServerReplication(expectTwoPhaseCommit ? st.rs1.getSecondaries() : st.rs0.getSecondaries());
// Do a write on rs0 through the router outside the transaction to ensure the
// transaction will choose a read time that has not been majority committed.
// transaction will choose a read time that has not been majority committed. We do this
// write with {w: 1} because we stopped replication on secondaries so anything else is
// unfulfillable.
assert.commandWorked(st.s.getDB(dbName).getCollection("dummy").insert({dummy: 1}));
},
beforeCommit: noop,
@ -329,7 +331,7 @@ const failureModes = {
// Any read shard failure should have triggered an implicit abort on all shards.
// Note the first shard already received commitTransaction but couldn't majority
// commit it, so it should have already committed the transaction.
const dummyTxnCmd = addTxnFields({commitTransaction: 1}, lsid, txnNumber);
const dummyTxnCmd = addTxnFields({commitTransaction: 1, writeConcern: {w: 1}}, lsid, txnNumber);
assert.commandWorked(st.rs0.getPrimary().adminCommand(dummyTxnCmd));
assert.commandFailedWithCode(
st.rs1.getPrimary().adminCommand(dummyTxnCmd),

View File

@ -332,8 +332,14 @@ if (!FeatureFlagUtil.isPresentAndEnabled(st.shard1, "ShardAuthoritativeDbMetadat
stopReplicationOnSecondaries(recoveryShardReplSetTest, false /* changeReplicaSetDefaultWCToLocal */);
// Do a write on the recovery node to bump the recovery node's system last OpTime.
recoveryShardReplSetTest.getPrimary().getDB("dummy").getCollection("dummy").insert({dummy: 1});
// Do a write on the recovery node to bump the recovery node's system last OpTime. We do this
// write with {w: 1} because we stopped replication on secondaries so anything else is
// unfulfillable.
recoveryShardReplSetTest
.getPrimary()
.getDB("dummy")
.getCollection("dummy")
.insert({dummy: 1}, {writeConcern: {w: 1}});
// While the recovery shard primary cannot majority commit writes, commitTransaction returns
// NoSuchTransaction with a writeConcern error.
@ -363,8 +369,14 @@ if (!FeatureFlagUtil.isPresentAndEnabled(st.shard1, "ShardAuthoritativeDbMetadat
stopReplicationOnSecondaries(recoveryShardReplSetTest, false /* changeReplicaSetDefaultWCToLocal */);
// Do a write on the recovery node to bump the recovery node's system last OpTime.
recoveryShardReplSetTest.getPrimary().getDB("dummy").getCollection("dummy").insert({dummy: 1});
// Do a write on the recovery node to bump the recovery node's system last OpTime. We do this
// write with {w: 1} because we stopped replication on secondaries so anything else is
// unfulfillable.
recoveryShardReplSetTest
.getPrimary()
.getDB("dummy")
.getCollection("dummy")
.insert({dummy: 1}, {writeConcern: {w: 1}});
// While the recovery shard primary cannot majority commit writes, commitTransaction returns
// ok with a writeConcern error.

View File

@ -1461,14 +1461,16 @@ StatusWith<repl::ReadConcernArgs> ExecCommandDatabase::_extractReadConcern(
"internalClient connection {}",
redact(_execContext.getRequest().body.toString())),
readConcernArgs.isSpecified());
} else if (serverGlobalParams.clusterRole.has(ClusterRole::ShardServer) ||
serverGlobalParams.clusterRole.has(ClusterRole::ConfigServer)) {
if (!readConcernArgs.isSpecified()) {
// TODO: Disabled until after SERVER-44539, to avoid log spam.
// LOGV2(21954, "Missing readConcern on {command}", "Missing readConcern "
// "for command", "command"_attr = _invocation->definition()->getName());
}
} else {
if ((serverGlobalParams.clusterRole.has(ClusterRole::ShardServer) ||
serverGlobalParams.clusterRole.has(ClusterRole::ConfigServer)) &&
!readConcernArgs.isSpecified()) {
// TODO: Disabled until after SERVER-44539, to avoid log spam.
// LOGV2(21954,
// "Missing readConcern for command",
// "command"_attr = _invocation->definition()->getName());
}
// A member in a regular replica set. Since these servers receive client queries, in
// this context empty RC (ie. readConcern: {}) means the same as if absent/unspecified,
// which is to apply the CWRWC defaults if present. This means we just test isEmpty(),

View File

@ -240,7 +240,7 @@ TEST_F(ServiceEntryPointShardServerTest, TestReadConcernClientUnspecifiedNoDefau
}
TEST_F(ServiceEntryPointShardServerTest, TestReadConcernClientUnspecifiedWithDefault) {
testReadConcernClientUnspecifiedWithDefault(false);
testReadConcernClientUnspecifiedWithDefault();
}
TEST_F(ServiceEntryPointShardServerTest, TestReadConcernClientSuppliedLevelNotAllowed) {
@ -275,7 +275,7 @@ TEST_F(ServiceEntryPointShardServerTest, TestWriteConcernClientUnspecifiedNoDefa
TEST_F(ServiceEntryPointShardServerTest, TestWriteConcernClientUnspecifiedWithDefault) {
_replCoordMock->setWriteConcernMajorityShouldJournal(false);
testWriteConcernClientUnspecifiedWithDefault(false);
testWriteConcernClientUnspecifiedWithDefault();
}
#ifdef MONGO_CONFIG_OTEL
@ -364,7 +364,7 @@ TEST_F(ServiceEntryPointReplicaSetTest, TestReadConcernClientUnspecifiedNoDefaul
}
TEST_F(ServiceEntryPointReplicaSetTest, TestReadConcernClientUnspecifiedWithDefault) {
testReadConcernClientUnspecifiedWithDefault(true);
testReadConcernClientUnspecifiedWithDefault();
}
TEST_F(ServiceEntryPointReplicaSetTest, TestReadConcernClientSuppliedLevelNotAllowed) {
@ -399,7 +399,7 @@ TEST_F(ServiceEntryPointReplicaSetTest, TestWriteConcernClientUnspecifiedNoDefau
TEST_F(ServiceEntryPointReplicaSetTest, TestWriteConcernClientUnspecifiedWithDefault) {
_replCoordMock->setWriteConcernMajorityShouldJournal(false);
testWriteConcernClientUnspecifiedWithDefault(true);
testWriteConcernClientUnspecifiedWithDefault();
}
#ifdef MONGO_CONFIG_OTEL

View File

@ -239,6 +239,7 @@ mongo_cc_library(
],
deps = [
":sharding_mongod_test_fixture",
"//src/mongo/db:read_write_concern_defaults_mock",
"//src/mongo/db/global_catalog:sharding_catalog_client_impl",
"//src/mongo/db/op_observer",
"//src/mongo/db/op_observer:op_observer_impl",

View File

@ -151,6 +151,8 @@ void ConfigServerTestFixture::setUp() {
std::move(specialExec),
std::move(shardLocal),
std::move(localCatalogClient));
ReadWriteConcernDefaults::create(getService(), _lookupMock.getFetchDefaultsFn());
}
void ConfigServerTestFixture::tearDown() {

View File

@ -44,6 +44,7 @@
#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/read_write_concern_defaults_cache_lookup_mock.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/sharding_environment/client/shard.h"
#include "mongo/db/sharding_environment/grid.h"
@ -254,6 +255,9 @@ private:
// Allows for processing tasks through the NetworkInterfaceMock/ThreadPoolMock subsystem.
std::unique_ptr<executor::NetworkTestEnv> _addShardNetworkTestEnv;
// Allows for commands to not specify a default read/write concern.
ReadWriteConcernDefaultsLookupMock _lookupMock;
};
} // namespace mongo

View File

@ -133,10 +133,9 @@ StatusWith<WriteConcernOptions> extractWriteConcern(OperationContext* opCtx,
bool clientSuppliedWriteConcern = !writeConcern.usedDefaultConstructedWC;
bool customDefaultWasApplied = false;
// WriteConcern defaults can only be applied on regular replica set members.
// Operations received by shard and config servers should always have WC explicitly specified.
bool canApplyDefaultWC = serverGlobalParams.clusterRole.has(ClusterRole::None) &&
repl::ReplicationCoordinator::get(opCtx)->getSettings().isReplSet() &&
// Though the mongoS should always supply a write concern for shardsvr/configsvr nodes, we still
// apply the default here for direct shard operations (or for normal replica set members).
bool canApplyDefaultWC = repl::ReplicationCoordinator::get(opCtx)->getSettings().isReplSet() &&
(!opCtx->inMultiDocumentTransaction() ||
isTransactionCommand(opCtx->getService(), commandName)) &&
!opCtx->getClient()->isInDirectClient() && !isInternalClient;

View File

@ -122,7 +122,7 @@ TEST_F(ServiceEntryPointRouterRoleTest, TestReadConcernClientUnspecifiedNoDefaul
}
TEST_F(ServiceEntryPointRouterRoleTest, TestReadConcernClientUnspecifiedWithDefault) {
testReadConcernClientUnspecifiedWithDefault(true);
testReadConcernClientUnspecifiedWithDefault();
}
TEST_F(ServiceEntryPointRouterRoleTest, TestReadConcernClientSuppliedLevelNotAllowed) {
@ -154,7 +154,7 @@ TEST_F(ServiceEntryPointRouterRoleTest, TestWriteConcernClientUnspecifiedNoDefau
}
TEST_F(ServiceEntryPointRouterRoleTest, TestWriteConcernClientUnspecifiedWithDefault) {
testWriteConcernClientUnspecifiedWithDefault(true);
testWriteConcernClientUnspecifiedWithDefault();
}
#ifdef MONGO_CONFIG_OTEL

View File

@ -384,11 +384,8 @@ void ServiceEntryPointTestFixture::testReadConcernClientUnspecifiedNoDefault() {
ASSERT_EQ(logs.countTextContaining("Applying default readConcern on command"), 1);
}
void ServiceEntryPointTestFixture::testReadConcernClientUnspecifiedWithDefault(
bool expectClusterDefault) {
// When the read concern is not specified:
// * In the router and replica set cases, a cluster-wide default read concern applies
// * In the shard server case, an implicit default applies.
void ServiceEntryPointTestFixture::testReadConcernClientUnspecifiedWithDefault() {
// When the read concern is not specified, a cluster-wide default read concern applies
const auto cmdBSON = BSON(TestCmdSucceedsDefaultRCPermitted::kCommandName << 1);
auto opCtx = makeOperationContext();
setDefaultReadConcern(opCtx.get(), repl::ReadConcernArgs::kAvailable);
@ -397,15 +394,10 @@ void ServiceEntryPointTestFixture::testReadConcernClientUnspecifiedWithDefault(
logs.stop();
auto readConcernArgs = repl::ReadConcernArgs::get(opCtx.get());
if (expectClusterDefault) {
ASSERT_EQ(readConcernArgs.getLevel(), repl::ReadConcernArgs::kAvailable.getLevel());
ASSERT_EQ(readConcernArgs.getProvenance(),
ReadWriteConcernProvenance(ReadWriteConcernProvenanceSourceEnum::customDefault));
ASSERT_EQ(logs.countTextContaining("Applying default readConcern on command"), 1);
} else {
ASSERT(readConcernArgs.isImplicitDefault());
ASSERT_EQ(logs.countTextContaining("Applying default readConcern on command"), 0);
}
ASSERT_EQ(readConcernArgs.getLevel(), repl::ReadConcernArgs::kAvailable.getLevel());
ASSERT_EQ(readConcernArgs.getProvenance(),
ReadWriteConcernProvenance(ReadWriteConcernProvenanceSourceEnum::customDefault));
ASSERT_EQ(logs.countTextContaining("Applying default readConcern on command"), 1);
}
void ServiceEntryPointTestFixture::testReadConcernClientSuppliedLevelNotAllowed(
@ -542,20 +534,13 @@ void ServiceEntryPointTestFixture::testWriteConcernClientUnspecifiedNoDefault()
runWriteConcernTestExpectImplicitDefault(opCtx.get());
}
void ServiceEntryPointTestFixture::testWriteConcernClientUnspecifiedWithDefault(
bool expectClusterDefault) {
// When the write concern is not specified:
// * In the router and replica set cases, a cluster-wide default write concern applies
// * In the shard server case, an implicit default applies.
void ServiceEntryPointTestFixture::testWriteConcernClientUnspecifiedWithDefault() {
// When the write concern is not specified, a cluster-wide default write concern applies
auto opCtx = makeOperationContext();
auto defaultWCObj = BSON("w" << "majority"
<< "wtimeout" << 500);
setDefaultWriteConcern(opCtx.get(), defaultWCObj);
if (expectClusterDefault) {
runWriteConcernTestExpectClusterDefault(opCtx.get());
} else {
runWriteConcernTestExpectImplicitDefault(opCtx.get());
}
runWriteConcernTestExpectClusterDefault(opCtx.get());
}
void ServiceEntryPointTestFixture::runWriteConcernTestExpectImplicitDefault(

View File

@ -99,7 +99,7 @@ public:
void testCommandMaxTimeMS();
void testOpCtxInterrupt(bool deferHandling);
void testReadConcernClientUnspecifiedNoDefault();
void testReadConcernClientUnspecifiedWithDefault(bool expectClusterDefault);
void testReadConcernClientUnspecifiedWithDefault();
void testReadConcernClientSuppliedLevelNotAllowed(bool exceptionLogged);
void testReadConcernClientSuppliedAllowed();
void testReadConcernExtractedOnException();
@ -107,7 +107,7 @@ public:
void testExhaustCommandNextInvocationSet();
void testWriteConcernClientSpecified();
void testWriteConcernClientUnspecifiedNoDefault();
void testWriteConcernClientUnspecifiedWithDefault(bool expectClusterDefault);
void testWriteConcernClientUnspecifiedWithDefault();
#ifdef MONGO_CONFIG_OTEL
void testTelemetryContextDeserializedFromRequest();