diff --git a/BUILD.bazel b/BUILD.bazel index 0b00f0b1db3..3b0fc0046db 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -430,6 +430,10 @@ mongo_install( extensions_with_config( name = "dist_test_extensions", srcs = [ + # Any extension that we intend to load in extensions passthrough tests and in the + # extension-enabled variant MUST have the "_mongo_extension" suffix for the + # find_extensions.sh script to recognize it. + # TODO SERVER-108821: Remove the comment below once extension stages are no longer # listed by $listMqlEntities. # Any extension added here will result in the with-extensions Evergreen variant @@ -440,6 +444,11 @@ extensions_with_config( # TODO SERVER-109108: Remove this entry when the bar extension is no longer needed. "//src/mongo/db/extension/test_examples:bar_mongo_extension", "//src/mongo/db/extension/test_examples:foo_mongo_extension", + + # Any extension that is just loaded in a no-passthrough test MUST NOT have the + # "_mongo_extension" suffix. + "//src/mongo/db/extension/test_examples:no_symbol_bad_extension", + "//src/mongo/db/extension/test_examples:duplicate_stage_descriptor_bad_extension", ], ) diff --git a/bazel/mongo_src_rules.bzl b/bazel/mongo_src_rules.bzl index 129f2ca7bcd..2199aa4af46 100644 --- a/bazel/mongo_src_rules.bzl +++ b/bazel/mongo_src_rules.bzl @@ -1494,3 +1494,87 @@ def mongo_cc_fuzzer_test( exec_properties = exec_properties, **kwargs ) + +# Note: For these extensions to load successfully in the server, they must be built with +# --allocator=system. Otherwise, the extensions will get a local instance of tcmalloc which +# fails to run properly because there isn't enough TLS space available for both the host and +# extension's tcmalloc. In transitions.bzl, we define a Bazel transition for managing the allocator +# and other extension-specific options. +def mongo_cc_extension_shared_library( + name, + srcs = [], + deps = [], + header_deps = [], + visibility = None, + data = [], + tags = [], + copts = [], + linkopts = [], + includes = [], + linkstatic = False, + local_defines = [], + target_compatible_with = [], + defines = [], + additional_linker_inputs = [], + features = [], + exec_properties = {}, + **kwargs): + mongo_cc_library( + name = name, + srcs = srcs, + deps = deps + [ + "//src/mongo/db/extension/public:api", + "//src/mongo/db/extension/sdk:sdk_cpp", + ], + header_deps = header_deps, + visibility = visibility, + data = data, + tags = tags, + copts = copts, + linkopts = linkopts, + includes = includes, + linkstatic = linkstatic, + local_defines = local_defines, + defines = defines, + features = features, + exec_properties = exec_properties, + additional_linker_inputs = additional_linker_inputs + select({ + "@platforms//os:linux": [ + ":test_extensions.version_script.lds", + ], + "//conditions:default": [], + }) + select({ + "@platforms//os:macos": [ + ":test_extensions.exported_symbols_list.lds", + ], + "//conditions:default": [], + }), + # linkshared produces a shared library as the output. + # TODO SERVER-109255 Make sure the test extensions are statically linked, as we expect + # all extensions to be. + linkshared = True, + non_transitive_dyn_linkopts = select({ + "@platforms//os:linux": [ + "-Wl,--version-script=$(location :test_extensions.version_script.lds)", + ], + "//conditions:default": [], + }) + select({ + "@platforms//os:macos": [ + "-Wl,-exported_symbols_list,$(location :test_extensions.exported_symbols_list.lds)", + ], + "//conditions:default": [], + }), + skip_global_deps = [ + # This is a globally injected dependency. We don't want a special allocator linked + # here. Instead, the allocator should be overriden at load time. + "allocator", + "libunwind", + ], + target_compatible_with = target_compatible_with + select({ + "//bazel/config:shared_archive_or_link_dynamic": [], + "//conditions:default": ["@platforms//:incompatible"], + }) + select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + ) diff --git a/jstests/noPassthrough/extensions/extensions_parameter_error_cases.js b/jstests/noPassthrough/extensions/extensions_loading_error_cases.js similarity index 72% rename from jstests/noPassthrough/extensions/extensions_parameter_error_cases.js rename to jstests/noPassthrough/extensions/extensions_loading_error_cases.js index a84d92839a2..8473f4690e7 100644 --- a/jstests/noPassthrough/extensions/extensions_parameter_error_cases.js +++ b/jstests/noPassthrough/extensions/extensions_loading_error_cases.js @@ -1,13 +1,23 @@ /** * Tests error cases when using the --loadExtensions startup parameter on mongos and mongod. * - * @tags: [featureFlagExtensionsAPI] + * This includes testing cases where the host rejects the parsed options, file does not exist, and + * two cases where the extension is rejected by the host during loading. + * + * @tags: [ + * featureFlagExtensionsAPI, + * # TODO SERVER-109351 Re-enable aubsan coverage by resolving memory leak + * incompatible_aubsan, + * ] */ - import {isLinux} from "jstests/libs/os_helpers.js"; import {ShardingTest} from "jstests/libs/shardingtest.js"; const pathToExtensionFoo = MongoRunner.getExtensionPath("libfoo_mongo_extension.so"); +const pathToMissingSymbolExtension = MongoRunner.getExtensionPath("libno_symbol_bad_extension.so"); +const pathToDuplicateStageExtension = + MongoRunner.getExtensionPath("libduplicate_stage_descriptor_bad_extension.so"); + // Create a ShardingTest so that we have a config DB for mongos to point to in our test. We don't // use ShardingTest directly because repeated failed ShardingTest startups causes issues in the test // environment. This also reduces the amount of times we have to start a whole sharded cluster in @@ -52,6 +62,10 @@ if (isLinux()) { runTest({options: {loadExtensions: 12345}}); // Path to extension does not exist. runTest({options: {loadExtensions: "path/does/not/exist.so"}}); + // Path to extension with an .so that is missing the get_mongodb_extension symbol. + runTest({options: {loadExtensions: pathToMissingSymbolExtension}}); + // Path to extension that attempts to register duplicate stage descriptors. + runTest({options: {loadExtensions: pathToDuplicateStageExtension}}); } else { // Startup should fail because we are attempting to load an extension on a platform that is not // linux. diff --git a/src/mongo/db/extension/host/BUILD.bazel b/src/mongo/db/extension/host/BUILD.bazel index 5463ae22f06..98ba25d0ff1 100644 --- a/src/mongo/db/extension/host/BUILD.bazel +++ b/src/mongo/db/extension/host/BUILD.bazel @@ -59,19 +59,19 @@ mongo_cc_unit_test( # TODO SERVER-109108: Remove this entry when the buzz extension is no longer needed. "//src/mongo/db/extension/test_examples:buzz_mongo_extension", "//src/mongo/db/extension/test_examples:foo_mongo_extension", - "//src/mongo/db/extension/test_examples:hostVersionFails_mongo_extension", + "//src/mongo/db/extension/test_examples:host_version_fails_bad_extension", "//src/mongo/db/extension/test_examples:hostVersionSucceeds_mongo_extension", - "//src/mongo/db/extension/test_examples:initializeVersionFails_mongo_extension", + "//src/mongo/db/extension/test_examples:initialize_version_fails_bad_extension", "//src/mongo/db/extension/test_examples:loadTwoStages_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed1_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed2_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed3_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed4_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed5_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed6_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed7_mongo_extension", - "//src/mongo/db/extension/test_examples:malformed8_mongo_extension", - "//src/mongo/db/extension/test_examples:nullStageDescriptor_mongo_extension", + "//src/mongo/db/extension/test_examples:no_symbol_bad_extension", + "//src/mongo/db/extension/test_examples:null_mongo_extension_bad_extension", + "//src/mongo/db/extension/test_examples:major_version_too_high_bad_extension", + "//src/mongo/db/extension/test_examples:major_version_too_low_bad_extension", + "//src/mongo/db/extension/test_examples:minor_version_too_high_bad_extension", + "//src/mongo/db/extension/test_examples:null_initialize_function_bad_extension", + "//src/mongo/db/extension/test_examples:major_version_max_int_bad_extension", + "//src/mongo/db/extension/test_examples:duplicate_stage_descriptor_bad_extension", + "//src/mongo/db/extension/test_examples:null_stage_descriptor_bad_extension", ], tags = ["mongo_unittest_seventh_group"], target_compatible_with = select({ diff --git a/src/mongo/db/extension/host/load_extension.cpp b/src/mongo/db/extension/host/load_extension.cpp index 1945e1e554e..cb3b814f40d 100644 --- a/src/mongo/db/extension/host/load_extension.cpp +++ b/src/mongo/db/extension/host/load_extension.cpp @@ -50,40 +50,6 @@ #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kDefault namespace mongo::extension::host { - -stdx::unordered_map> ExtensionLoader::loadedExtensions; - -bool loadExtensions(const std::vector& extensionPaths) { - if (extensionPaths.empty()) { - return true; - } - - if (!feature_flags::gFeatureFlagExtensionsAPI.isEnabled()) { - LOGV2_ERROR(10668500, - "Extensions are not allowed with the current configuration. You may need to " - "enable featureFlagExtensionsAPI."); - return false; - } - - for (const auto& extension : extensionPaths) { - LOGV2(10668501, "Loading extension", "filePath"_attr = extension); - - try { - ExtensionLoader::load(extension); - } catch (...) { - LOGV2_ERROR(10668502, - "Error loading extension", - "filePath"_attr = extension, - "status"_attr = exceptionToStatus()); - return false; - } - - LOGV2(10668503, "Successfully loaded extension", "filePath"_attr = extension); - } - - return true; -} - namespace { void assertVersionCompatibility(const ::MongoExtensionAPIVersionVector* hostVersions, const ::MongoExtensionAPIVersion& extensionVersion) { @@ -145,10 +111,43 @@ ExtensionHandle getMongoExtension(SharedLibrary& extensionLib, const std::string } } // namespace +stdx::unordered_map> ExtensionLoader::loadedExtensions; + +bool loadExtensions(const std::vector& extensionPaths) { + if (extensionPaths.empty()) { + return true; + } + + if (!feature_flags::gFeatureFlagExtensionsAPI.isEnabled()) { + LOGV2_ERROR(10668500, + "Extensions are not allowed with the current configuration. You may need to " + "enable featureFlagExtensionsAPI."); + return false; + } + + for (const auto& extension : extensionPaths) { + LOGV2(10668501, "Loading extension", "filePath"_attr = extension); + + try { + ExtensionLoader::load(extension); + } catch (...) { + LOGV2_ERROR(10668502, + "Error loading extension", + "filePath"_attr = extension, + "status"_attr = exceptionToStatus()); + return false; + } + + LOGV2(10668503, "Successfully loaded extension", "filePath"_attr = extension); + } + + return true; +} + void ExtensionLoader::load(const std::string& extensionPath) { uassert(10845400, - str::stream() << "Loading extension '" << extensionPath - << "' failed: " << "Extension has already been loaded", + str::stream() << "Loading extension '" << extensionPath << "' failed: " + << "Extension has already been loaded", !loadedExtensions.contains(extensionPath)); StatusWith> swExtensionLib = diff --git a/src/mongo/db/extension/host/load_extension_test.cpp b/src/mongo/db/extension/host/load_extension_test.cpp index f9ee4045221..57ffa2c7d94 100644 --- a/src/mongo/db/extension/host/load_extension_test.cpp +++ b/src/mongo/db/extension/host/load_extension_test.cpp @@ -76,45 +76,53 @@ TEST_F(LoadExtensionsTest, LoadExtensionErrorCases) { AssertionException, 10615500); - // malformed1_extension is missing the get_mongodb_extension symbol definition. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed1_mongo_extension.so")), + // no_symbol_bad_extension is missing the get_mongodb_extension symbol definition. + ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libno_symbol_bad_extension.so")), AssertionException, 10615501); - // malformed2_extension returns null from get_mongodb_extension. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed2_mongo_extension.so")), - AssertionException, - 10615503); + // null_mongo_extension_bad_extension returns null from get_mongodb_extension. + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libnull_mongo_extension_bad_extension.so")), + AssertionException, + 10615503); - // malformed3_extension has an incompatible major version (plus 1). - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed3_mongo_extension.so")), - AssertionException, - 10615504); + // major_version_too_high_bad_extension has an incompatible major version (plus 1). + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libmajor_version_too_high_bad_extension.so")), + AssertionException, + 10615504); - // malformed4_extension has an incompatible major version (minus 1). - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed4_mongo_extension.so")), - AssertionException, - 10615504); + // major_version_too_low_bad_extension has an incompatible major version (minus 1). + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libmajor_version_too_low_bad_extension.so")), + AssertionException, + 10615504); - // malformed5_extension has an incompatible minor version. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed5_mongo_extension.so")), - AssertionException, - 10615505); + // minor_version_too_high_bad_extension has an incompatible minor version. + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libminor_version_too_high_bad_extension.so")), + AssertionException, + 10615505); - // malformed6_extension has a null initialization function. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed6_mongo_extension.so")), - AssertionException, - 10615506); + // null_initialize_function_bad_extension has a null initialization function. + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libnull_initialize_function_bad_extension.so")), + AssertionException, + 10615506); - // malformed7_extension has the maximum uint32_t value as its major version. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed7_mongo_extension.so")), - AssertionException, - 10615504); + // major_version_max_int_bad_extension has the maximum uint32_t value as its major version. + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libmajor_version_max_int_bad_extension.so")), + AssertionException, + 10615504); - // malformed8_extension attempts to register the same stage descriptor multiple times. - ASSERT_THROWS_CODE(ExtensionLoader::load(getExtensionPath("libmalformed8_mongo_extension.so")), - AssertionException, - 10696402); + // duplicate_stage_descriptor_bad_extension attempts to register the same stage descriptor + // multiple times. + ASSERT_THROWS_CODE( + ExtensionLoader::load(getExtensionPath("libduplicate_stage_descriptor_bad_extension.so")), + AssertionException, + 10696402); } // TODO SERVER-109108: Switch this to use the foo extension once we can reset state in between @@ -189,20 +197,20 @@ TEST_F(LoadExtensionsTest, LoadExtensionHostVersionParameterSucceeds) { TEST_F(LoadExtensionsTest, LoadExtensionHostVersionParameterFails) { ASSERT_THROWS_CODE( - ExtensionLoader::load(getExtensionPath("libhostVersionFails_mongo_extension.so")), + ExtensionLoader::load(getExtensionPath("libhost_version_fails_bad_extension.so")), AssertionException, 10615503); } -TEST_F(LoadExtensionsTest, LoadExtensionInitializeVersionFails) { +TEST_F(LoadExtensionsTest, LoadExtensioninitialize_version_fails) { ASSERT_THROWS_CODE( - ExtensionLoader::load(getExtensionPath("libinitializeVersionFails_mongo_extension.so")), + ExtensionLoader::load(getExtensionPath("libinitialize_version_fails_bad_extension.so")), AssertionException, 10726600); } -DEATH_TEST_F(LoadExtensionsTest, LoadExtensionNullStageDescriptor, "10596400") { - ExtensionLoader::load(getExtensionPath("libnullStageDescriptor_mongo_extension.so")); +DEATH_TEST_F(LoadExtensionsTest, LoadExtensionnull_stage_descriptor, "10596400") { + ExtensionLoader::load(getExtensionPath("libnull_stage_descriptor_bad_extension.so")); } TEST(LoadExtensionTest, LoadExtensionTwoStagesSucceeds) { diff --git a/src/mongo/db/extension/test_examples/BUILD.bazel b/src/mongo/db/extension/test_examples/BUILD.bazel index 9a52fb33ec0..9be46e1149a 100644 --- a/src/mongo/db/extension/test_examples/BUILD.bazel +++ b/src/mongo/db/extension/test_examples/BUILD.bazel @@ -1,77 +1,51 @@ -load("//bazel:mongo_src_rules.bzl", "mongo_cc_library", "mongo_cc_unit_test") +load("//bazel:mongo_src_rules.bzl", "mongo_cc_extension_shared_library", "mongo_cc_library", "mongo_cc_unit_test") package(default_visibility = ["//visibility:public"]) +# Extensions under test_examples/ [ - # Note: For these extensions to load successfully in the server, they must be built with - # --allocator=system. Otherwise, the extensions will get a local instance of tcmalloc which - # fails to run properly because there isn't enough TLS space available for both the host and - # extension's tcmalloc. When testing on evergreen, we should build the extensions with the - # system allocator, and load the extensions into a host that was built with tcmalloc. - mongo_cc_library( + mongo_cc_extension_shared_library( name = extension_name + "_mongo_extension", srcs = [extension_name + ".cpp"], - additional_linker_inputs = select({ - "@platforms//os:linux": [ - ":test_extensions.version_script.lds", - ], - "//conditions:default": [], - }) + select({ - "@platforms//os:macos": [ - ":test_extensions.exported_symbols_list.lds", - ], - "//conditions:default": [], - }), - # linkshared produces a shared library as the output. - # TODO SERVER-109255 Make sure the test extensions are statically linked, as we expect - # all extensions to be. - linkshared = True, - non_transitive_dyn_linkopts = select({ - "@platforms//os:linux": [ - "-Wl,--version-script=$(location :test_extensions.version_script.lds)", - ], - "//conditions:default": [], - }) + select({ - "@platforms//os:macos": [ - "-Wl,-exported_symbols_list,$(location :test_extensions.exported_symbols_list.lds)", - ], - "//conditions:default": [], - }), - skip_global_deps = [ - # This is a globally injected dependency. We don't want a special allocator linked - # here. Instead, the allocator should be overriden at load time. - "allocator", - "libunwind", - ], - target_compatible_with = select({ - "//bazel/config:shared_archive_or_link_dynamic": [], - "//conditions:default": ["@platforms//:incompatible"], - }) + select({ - "@platforms//os:linux": [], - "//conditions:default": ["@platforms//:incompatible"], - }), - deps = [ - "//src/mongo/db/extension/public:api", - "//src/mongo/db/extension/sdk:sdk_cpp", - ], ) for extension_name in [ - "malformed1", - "malformed2", - "malformed3", - "malformed4", - "malformed5", - "malformed6", - "malformed7", - "malformed8", "foo", "bar", # TODO SERVER-109108: Remove this entry when the buzz extension is no longer needed. "buzz", - "hostVersionSucceeds", - "hostVersionFails", - "initializeVersionFails", - "loadTwoStages", - "nullStageDescriptor", + ] +] + +# Extensions under test_examples/loading/ +[ + mongo_cc_extension_shared_library( + name = extension_name + "_mongo_extension", + srcs = ["loading/" + extension_name + ".cpp"], + ) + for extension_name in [ + "hostVersionSucceeds", + "loadTwoStages", + ] +] + +# Extensions under test_examples/fail_to_load/ +# Each of these should fail startup. +[ + mongo_cc_extension_shared_library( + name = extension_name + "_bad_extension", + srcs = ["fail_to_load/" + extension_name + ".cpp"], + ) + for extension_name in [ + "no_symbol", + "null_mongo_extension", + "major_version_too_high", + "major_version_too_low", + "minor_version_too_high", + "null_initialize_function", + "major_version_max_int", + "duplicate_stage_descriptor", + "host_version_fails", + "initialize_version_fails", + "null_stage_descriptor", ] ] diff --git a/src/mongo/db/extension/test_examples/malformed8.cpp b/src/mongo/db/extension/test_examples/fail_to_load/duplicate_stage_descriptor.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed8.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/duplicate_stage_descriptor.cpp diff --git a/src/mongo/db/extension/test_examples/hostVersionFails.cpp b/src/mongo/db/extension/test_examples/fail_to_load/host_version_fails.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/hostVersionFails.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/host_version_fails.cpp diff --git a/src/mongo/db/extension/test_examples/initializeVersionFails.cpp b/src/mongo/db/extension/test_examples/fail_to_load/initialize_version_fails.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/initializeVersionFails.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/initialize_version_fails.cpp diff --git a/src/mongo/db/extension/test_examples/malformed7.cpp b/src/mongo/db/extension/test_examples/fail_to_load/major_version_max_int.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed7.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/major_version_max_int.cpp diff --git a/src/mongo/db/extension/test_examples/malformed3.cpp b/src/mongo/db/extension/test_examples/fail_to_load/major_version_too_high.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed3.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/major_version_too_high.cpp diff --git a/src/mongo/db/extension/test_examples/malformed4.cpp b/src/mongo/db/extension/test_examples/fail_to_load/major_version_too_low.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed4.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/major_version_too_low.cpp diff --git a/src/mongo/db/extension/test_examples/malformed5.cpp b/src/mongo/db/extension/test_examples/fail_to_load/minor_version_too_high.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed5.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/minor_version_too_high.cpp diff --git a/src/mongo/db/extension/test_examples/malformed1.cpp b/src/mongo/db/extension/test_examples/fail_to_load/no_symbol.cpp similarity index 96% rename from src/mongo/db/extension/test_examples/malformed1.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/no_symbol.cpp index 72cece1e4bb..cebd0734037 100644 --- a/src/mongo/db/extension/test_examples/malformed1.cpp +++ b/src/mongo/db/extension/test_examples/fail_to_load/no_symbol.cpp @@ -36,4 +36,4 @@ public: }; // No definition of get_mongodb_extension() here, which is intentional to simulate a malformed -// extension. +// extension missing the export of the get_mongodb_extension symbol. diff --git a/src/mongo/db/extension/test_examples/malformed6.cpp b/src/mongo/db/extension/test_examples/fail_to_load/null_initialize_function.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed6.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/null_initialize_function.cpp diff --git a/src/mongo/db/extension/test_examples/malformed2.cpp b/src/mongo/db/extension/test_examples/fail_to_load/null_mongo_extension.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/malformed2.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/null_mongo_extension.cpp diff --git a/src/mongo/db/extension/test_examples/nullStageDescriptor.cpp b/src/mongo/db/extension/test_examples/fail_to_load/null_stage_descriptor.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/nullStageDescriptor.cpp rename to src/mongo/db/extension/test_examples/fail_to_load/null_stage_descriptor.cpp diff --git a/src/mongo/db/extension/test_examples/hostVersionSucceeds.cpp b/src/mongo/db/extension/test_examples/loading/hostVersionSucceeds.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/hostVersionSucceeds.cpp rename to src/mongo/db/extension/test_examples/loading/hostVersionSucceeds.cpp diff --git a/src/mongo/db/extension/test_examples/loadTwoStages.cpp b/src/mongo/db/extension/test_examples/loading/loadTwoStages.cpp similarity index 100% rename from src/mongo/db/extension/test_examples/loadTwoStages.cpp rename to src/mongo/db/extension/test_examples/loading/loadTwoStages.cpp