summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/auth/security_token.js2
-rw-r--r--jstests/auth/token_privileges.js2
-rw-r--r--src/mongo/db/catalog/collection_catalog.cpp2
-rw-r--r--src/mongo/db/catalog/views_for_database.cpp2
-rw-r--r--src/mongo/db/commands.h2
-rw-r--r--src/mongo/db/repl/oplog_entry.idl2
-rw-r--r--src/mongo/db/repl/tenant_oplog_applier_test.cpp4
-rw-r--r--src/mongo/db/views/durable_view_catalog.cpp8
-rw-r--r--src/mongo/util/SConscript24
-rw-r--r--src/mongo/util/namespace_string_util.cpp68
-rw-r--r--src/mongo/util/namespace_string_util.h77
-rw-r--r--src/mongo/util/namespace_string_util_test.cpp152
12 files changed, 333 insertions, 12 deletions
diff --git a/jstests/auth/security_token.js b/jstests/auth/security_token.js
index a96c0e487d8..a2f59b2f395 100644
--- a/jstests/auth/security_token.js
+++ b/jstests/auth/security_token.js
@@ -155,7 +155,7 @@ function runTests(enabled) {
MongoRunner.stopMongod(standalone);
}
- // TODO SERVER-67155 Run on replica sets as well. Currently the namespace from oplog entries
+ // TODO SERVER-69499 Run on replica sets as well. Currently the namespace from oplog entries
// won't be deserialized including the tenantId.
/*{
const rst = new ReplSetTest({nodes: 2, nodeOptions: opts});
diff --git a/jstests/auth/token_privileges.js b/jstests/auth/token_privileges.js
index b955e97f796..2378146564d 100644
--- a/jstests/auth/token_privileges.js
+++ b/jstests/auth/token_privileges.js
@@ -73,7 +73,7 @@ const opts = {
MongoRunner.stopMongod(standalone);
}
-// TODO SERVER-67155 Run on replica sets as well. Currently the namespace from oplog entries
+// TODO SERVER-69499 Run on replica sets as well. Currently the namespace from oplog entries
// won't be deserialized including the tenantId.
/*{
const rst = new ReplSetTest({nodes: 2, nodeOptions: opts});
diff --git a/src/mongo/db/catalog/collection_catalog.cpp b/src/mongo/db/catalog/collection_catalog.cpp
index 7a98aae38b2..dca8d9dfc2b 100644
--- a/src/mongo/db/catalog/collection_catalog.cpp
+++ b/src/mongo/db/catalog/collection_catalog.cpp
@@ -1593,7 +1593,7 @@ Status CollectionCatalog::_createOrUpdateView(
// Build the BSON definition for this view to be saved in the durable view catalog and/or to
// insert in the viewMap. If the collation is empty, omit it from the definition altogether.
BSONObjBuilder viewDefBuilder;
- // TODO SERVER-67155 Use serialize function on NamespaceString to create the string to write.
+ // TODO SERVER-69499 Use serialize function on NamespaceString to create the string to write.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))) {
diff --git a/src/mongo/db/catalog/views_for_database.cpp b/src/mongo/db/catalog/views_for_database.cpp
index 5fd510fff55..2ebf6c18b91 100644
--- a/src/mongo/db/catalog/views_for_database.cpp
+++ b/src/mongo/db/catalog/views_for_database.cpp
@@ -107,7 +107,7 @@ Status ViewsForDatabase::_insert(OperationContext* opCtx,
}
NamespaceString viewName;
- // TODO SERVER-67155 Use deserialize function on NamespaceString to reconstruct NamespaceString
+ // TODO SERVER-69499 Use deserialize function on NamespaceString to reconstruct NamespaceString
// correctly.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index d903da77372..64a83ee99ae 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -1154,7 +1154,7 @@ private:
static RequestType _parseRequest(OperationContext* opCtx,
const DatabaseName& dbName,
const BSONObj& cmdObj) {
- // TODO SERVER-67155 pass tenantId to the BSONObj parse function
+ // TODO SERVER-69499 pass tenantId to the BSONObj parse function
return RequestType::parse(
IDLParserContext(RequestType::kCommandName,
APIParameters::get(opCtx).getAPIStrict().value_or(false)),
diff --git a/src/mongo/db/repl/oplog_entry.idl b/src/mongo/db/repl/oplog_entry.idl
index ed433979f7b..af75666591d 100644
--- a/src/mongo/db/repl/oplog_entry.idl
+++ b/src/mongo/db/repl/oplog_entry.idl
@@ -60,7 +60,7 @@ enums:
kPostImage: "postImage"
structs:
- # TODO SERVER-67155 Ensure the tenantId is included in the serialized "ns" field when
+ # TODO SERVER-69499 Ensure the tenantId is included in the serialized "ns" field when
# multitenancySupport is on but featureFlagRequireTenantId is off. Currently it will not be
# included in either place
DurableReplOperation:
diff --git a/src/mongo/db/repl/tenant_oplog_applier_test.cpp b/src/mongo/db/repl/tenant_oplog_applier_test.cpp
index 9905fc65c33..495ec4b3c79 100644
--- a/src/mongo/db/repl/tenant_oplog_applier_test.cpp
+++ b/src/mongo/db/repl/tenant_oplog_applier_test.cpp
@@ -205,7 +205,7 @@ private:
logv2::LogComponent::kTenantMigration, logv2::LogSeverity::Debug(1)};
};
-// TODO SERVER-67155 Remove all calls to DatabaseName::toStringWithTenantId() once the OplogEntry
+// TODO SERVER-69499 Remove all calls to DatabaseName::toStringWithTenantId() once the OplogEntry
// deserializer passes "tid" to the NamespaceString constructor
TEST_F(TenantOplogApplierTest, NoOpsForSingleBatch) {
std::vector<OplogEntry> srcOps;
@@ -847,7 +847,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_Success) {
ASSERT_TRUE(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_IX));
ASSERT_TRUE(opCtx->writesAreReplicated());
ASSERT_FALSE(args.fromMigrate);
- // TODO SERVER-67155 Check that (nss.dbName() == _dbName) once the OplogEntry deserializer
+ // TODO SERVER-69499 Check that (nss.dbName() == _dbName) once the OplogEntry deserializer
// passes "tid" to the NamespaceString constructor
ASSERT_EQUALS(nss.dbName().db(), _dbName.toStringWithTenantId());
ASSERT_EQUALS(nss.coll(), "bar");
diff --git a/src/mongo/db/views/durable_view_catalog.cpp b/src/mongo/db/views/durable_view_catalog.cpp
index 748ee8bbc49..603de20e69f 100644
--- a/src/mongo/db/views/durable_view_catalog.cpp
+++ b/src/mongo/db/views/durable_view_catalog.cpp
@@ -72,7 +72,7 @@ void validateViewDefinitionBSON(OperationContext* opCtx,
}
NamespaceString viewName;
- // TODO SERVER-67155 Use deserialize function on NamespaceString to reconstruct NamespaceString
+ // TODO SERVER-69499 Use deserialize function on NamespaceString to reconstruct NamespaceString
// correctly.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
@@ -143,7 +143,7 @@ Status DurableViewCatalog::onExternalInsert(OperationContext* opCtx,
auto catalog = CollectionCatalog::get(opCtx);
NamespaceString viewName;
- // TODO SERVER-67155 Use deserialize function on NamespaceString to reconstruct NamespaceString
+ // TODO SERVER-69499 Use deserialize function on NamespaceString to reconstruct NamespaceString
// correctly.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
@@ -260,7 +260,7 @@ void DurableViewCatalogImpl::upsert(OperationContext* opCtx,
invariant(systemViews);
std::string nssOnDisk;
- // TODO SERVER-67155 Move this check into a function on NamespaceString.
+ // TODO SERVER-69499 Move this check into a function on NamespaceString.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))) {
@@ -304,7 +304,7 @@ void DurableViewCatalogImpl::remove(OperationContext* opCtx, const NamespaceStri
std::string nssOnDisk;
- // TODO SERVER-67155 Move this check into a function on NamespaceString.
+ // TODO SERVER-69499 Move this check into a function on NamespaceString.
if (!gMultitenancySupport ||
(serverGlobalParams.featureCompatibility.isVersionInitialized() &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))) {
diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript
index fc59a929ee0..e0b0487dd49 100644
--- a/src/mongo/util/SConscript
+++ b/src/mongo/util/SConscript
@@ -228,6 +228,30 @@ env.Library(
)
env.Library(
+ target='namespace_string_util',
+ source=[
+ 'namespace_string_util.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/db/multitenancy',
+ '$BUILD_DIR/mongo/db/server_base',
+ '$BUILD_DIR/mongo/db/server_feature_flags',
+ '$BUILD_DIR/mongo/db/server_options_core',
+ '$BUILD_DIR/mongo/idl/feature_flag',
+ ],
+)
+
+env.CppUnitTest(
+ target='namespace_string_util_test',
+ source=[
+ 'namespace_string_util_test.cpp',
+ ],
+ LIBDEPS=[
+ 'namespace_string_util',
+ ],
+)
+
+env.Library(
target="periodic_runner",
source=[
"periodic_runner.cpp",
diff --git a/src/mongo/util/namespace_string_util.cpp b/src/mongo/util/namespace_string_util.cpp
new file mode 100644
index 00000000000..141d5781ec8
--- /dev/null
+++ b/src/mongo/util/namespace_string_util.cpp
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2022-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/util/namespace_string_util.h"
+#include "mongo/db/multitenancy_gen.h"
+#include "mongo/db/namespace_string.h"
+#include "mongo/db/server_feature_flags_gen.h"
+#include "mongo/util/str.h"
+#include <ostream>
+
+namespace mongo {
+
+std::string NamespaceStringUtil::serialize(const NamespaceString& ns) {
+ if (gMultitenancySupport) {
+ if (serverGlobalParams.featureCompatibility.isVersionInitialized() &&
+ gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility)) {
+ return ns.toString();
+ }
+ return ns.toStringWithTenantId();
+ }
+ return ns.toString();
+}
+
+NamespaceString NamespaceStringUtil::deserialize(boost::optional<TenantId> tenantId,
+ StringData ns) {
+ if (gMultitenancySupport) {
+ if (serverGlobalParams.featureCompatibility.isVersionInitialized() &&
+ gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility)) {
+ invariant(tenantId != boost::none);
+ return NamespaceString(std::move(tenantId), ns);
+ }
+ auto nss = NamespaceString::parseFromStringExpectTenantIdInMultitenancyMode(ns);
+ if (tenantId != boost::none) {
+ invariant(tenantId == nss.tenantId());
+ }
+ return nss;
+ }
+ invariant(tenantId == boost::none);
+ return NamespaceString(boost::none, ns);
+}
+
+} // namespace mongo
diff --git a/src/mongo/util/namespace_string_util.h b/src/mongo/util/namespace_string_util.h
new file mode 100644
index 00000000000..001c0f785c0
--- /dev/null
+++ b/src/mongo/util/namespace_string_util.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2022-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/db/namespace_string.h"
+#include "mongo/db/tenant_id.h"
+
+namespace mongo {
+
+class NamespaceStringUtil {
+public:
+ /**
+ * Serializes a NamespaceString object.
+ *
+ * If multitenancySupport is enabled and featureFlagRequireTenantID is enabled, then tenantId is
+ * not included in the serialization.
+ * eg. serialize(NamespaceString(tenantID, "foo.bar")) -> "foo.bar"
+ *
+ * If multitenancySupport is enabled and featureFlagRequireTenantID is disabled, then tenantId
+ * is included in the serialization.
+ * eg. serialize(NamespaceString(tenantID, "foo.bar")) -> "tenantID_foo.bar"
+ *
+ * If multitenancySupport is disabled, the tenantID is not set in the NamespaceString Object.
+ * eg. serialize(NamespaceString(boost::none, "foo.bar")) -> "foo.bar"
+ */
+ static std::string serialize(const NamespaceString& ns);
+
+ /**
+ * Deserializes StringData ns to a NamespaceString object.
+ *
+ * If multitenancySupport is enabled and featureFlagRequireTenantID is enabled, then a
+ * NamespaceString object is constructed using the tenantId passed in to the constructor. The
+ * invariant requires tenantID to be initialized and passed to the constructor.
+ * eg. deserialize(tenantID, "foo.bar") -> NamespaceString(tenantID, "foo.bar")
+ *
+ * If multitenancySupport is enabled and featureFlagRequireTenantID is disabled, then ns is
+ * required to be prefixed with a tenantID. The tenantID parameter is ignored and
+ * NamespaceString is constructed using only ns. The invariant requires that if a tenantID
+ * is a parameter, then the tenatID is equal to the prefixed tenantID.
+ * eg. deserialize(boost::none, "preTenantID_foo.bar") -> NamespaceString(preTenantId,
+ * "foo.bar")
+ *
+ * If multitenancySupport is disabled then the invariant requires tenantID to not be initialized
+ * and NamespaceString is constructor without the tenantID.
+ * eg. deserialize(boost::none, "foo.bar") -> NamespaceString(boost::none, "foo.bar")
+ */
+ static NamespaceString deserialize(boost::optional<TenantId> tenantId, StringData ns);
+};
+
+} // namespace mongo
diff --git a/src/mongo/util/namespace_string_util_test.cpp b/src/mongo/util/namespace_string_util_test.cpp
new file mode 100644
index 00000000000..60d9edf9770
--- /dev/null
+++ b/src/mongo/util/namespace_string_util_test.cpp
@@ -0,0 +1,152 @@
+/**
+ * Copyright (C) 2022-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/platform/basic.h"
+
+#include "mongo/db/multitenancy_gen.h"
+#include "mongo/db/namespace_string.h"
+#include "mongo/idl/server_parameter_test_util.h"
+#include "mongo/unittest/death_test.h"
+#include "mongo/unittest/unittest.h"
+#include "mongo/util/namespace_string_util.h"
+
+namespace mongo {
+
+// TenantID is not included in serialization when multitenancySupport and
+// featureFlagRequireTenantID are enabled.
+TEST(NamespaceStringUtilTest, SerializeMultitenancySupportOnFeatureFlagRequireTenantIDOn) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ TenantId tenantId(OID::gen());
+ NamespaceString nss(tenantId, "foo.bar");
+ ASSERT_EQ(NamespaceStringUtil::serialize(nss), "foo.bar");
+}
+
+// TenantID is included in serialization when multitenancySupport is enabled and
+// featureFlagRequireTenantID is disabled.
+TEST(NamespaceStringUtilTest, SerializeMultitenancySupportOnFeatureFlagRequireTenantIDOff) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", false);
+ TenantId tenantId(OID::gen());
+ std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar";
+ NamespaceString nss(tenantId, "foo.bar");
+ ASSERT_EQ(NamespaceStringUtil::serialize(nss), tenantNsStr);
+}
+
+// Serialize correctly when multitenancySupport is disabled.
+TEST(NamespaceStringUtilTest, SerializeMultitenancySupportOff) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", false);
+ NamespaceString nss(boost::none, "foo.bar");
+ ASSERT_EQ(NamespaceStringUtil::serialize(nss), "foo.bar");
+}
+
+// Assert that if multitenancySupport and featureFlagRequireTenantID are on, then tenantId is set.
+DEATH_TEST_REGEX(NamespaceStringUtilTest,
+ DeserializeAssertTenantIdSetMultitenancySupportOnFeatureFlagRequireTenantIDOn,
+ "Invariant failure.*") {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ NamespaceString nss = NamespaceStringUtil::deserialize(boost::none, "foo.bar");
+}
+
+// Deserialize NamespaceString using the tenantID as a parameter to the NamespaceString constructor
+// when multitenancySupport and featureFlagRequireTenantID are enabled and ns does not have prefixed
+// tenantID.
+TEST(NamespaceStringUtilTest,
+ DeserializeNSSWithoutPrefixedTenantIDMultitenancySupportOnFeatureFlagRequireTenantIDOn) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", true);
+ TenantId tenantId(OID::gen());
+ NamespaceString nss = NamespaceStringUtil::deserialize(tenantId, "foo.bar");
+ ASSERT_EQ(nss.ns(), "foo.bar");
+ ASSERT(nss.tenantId());
+ ASSERT_EQ(nss, NamespaceString(tenantId, "foo.bar"));
+}
+
+// Assert that if multitenancySupport is enabled and featureFlagRequireTenantID is disabled,
+// then tenantId parsed from ns and tenantID passed to NamespaceString object are equal.
+DEATH_TEST_REGEX(NamespaceStringUtilTest,
+ DeserializeAssertTenantIdSetMultitenancySupportOnFeatureFlagRequireTenantIDOff,
+ "Invariant failure.*") {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", false);
+ TenantId tenantId(OID::gen());
+ TenantId tenantId2(OID::gen());
+ std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar";
+ NamespaceString nss = NamespaceStringUtil::deserialize(tenantId2, tenantNsStr);
+}
+
+// Deserialize NamespaceString when multitenancySupport is enabled and featureFlagRequireTenantID is
+// disabled.
+TEST(NamespaceStringUtilTest, DeserializeMultitenancySupportOnFeatureFlagRequireTenantIDOff) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", true);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", false);
+ TenantId tenantId(OID::gen());
+ std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar";
+ NamespaceString nss = NamespaceStringUtil::deserialize(boost::none, tenantNsStr);
+ NamespaceString nss1 = NamespaceStringUtil::deserialize(tenantId, tenantNsStr);
+ ASSERT_EQ(nss.ns(), "foo.bar");
+ ASSERT(nss.tenantId());
+ ASSERT_EQ(nss, NamespaceString(tenantId, "foo.bar"));
+ ASSERT_EQ(nss, nss1);
+}
+
+// Assert tenantID is not initialized when multitenancySupport is disabled.
+DEATH_TEST_REGEX(NamespaceStringUtilTest,
+ DeserializeMultitenancySupportOff,
+ "Invariant failure.*") {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", false);
+ TenantId tenantId(OID::gen());
+ NamespaceStringUtil::deserialize(tenantId, "foo.bar");
+}
+
+// Deserialize NamespaceString with prefixed tenantId when multitenancySupport and
+// featureFlagRequireTenantId are disabled.
+TEST(NamespaceStringUtilTest,
+ DeserializeWithTenantIdInStringMultitenancySupportOffFeatureFlagRequireTenantIDOff) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", false);
+ TenantId tenantId(OID::gen());
+ std::string tenantNsStr = str::stream() << tenantId.toString() << "_foo.bar";
+ std::string dbNameStr = str::stream() << tenantId.toString() << "_foo";
+ NamespaceString nss = NamespaceStringUtil::deserialize(boost::none, tenantNsStr);
+ ASSERT_EQ(nss.tenantId(), boost::none);
+ ASSERT_EQ(nss.dbName().db(), dbNameStr);
+}
+
+// Deserialize NamespaceString when multitenancySupport and featureFlagRequireTenantID are disabled.
+TEST(NamespaceStringUtilTest, DeserializeMultitenancySupportOffFeatureFlagRequireTenantIDOff) {
+ RAIIServerParameterControllerForTest multitenanyController("multitenancySupport", false);
+ RAIIServerParameterControllerForTest featureFlagController("featureFlagRequireTenantID", false);
+ NamespaceString nss = NamespaceStringUtil::deserialize(boost::none, "foo.bar");
+ ASSERT_EQ(nss.ns(), "foo.bar");
+ ASSERT(!nss.tenantId());
+ ASSERT_EQ(nss, NamespaceString(boost::none, "foo.bar"));
+}
+
+} // namespace mongo