diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2018-07-18 13:46:53 -0400 |
---|---|---|
committer | Henrik Edin <henrik.edin@mongodb.com> | 2018-07-27 16:20:53 -0400 |
commit | bfe170e49b1dc10b2badde45bc13c057a2f8ab61 (patch) | |
tree | f71d35e019c3194d033545c73296d415e18eb496 | |
parent | 018905518ca552775255f36a52e9fd187f9d61f8 (diff) | |
download | mongo-bfe170e49b1dc10b2badde45bc13c057a2f8ab61.tar.gz |
SERVER-36258 Construct ServiceContext after mongo initializers complete.
40 files changed, 198 insertions, 138 deletions
diff --git a/jstests/sharding/time_zone_info_mongos.js b/jstests/sharding/time_zone_info_mongos.js index 5ed4dd9866b..c75ac56628b 100644 --- a/jstests/sharding/time_zone_info_mongos.js +++ b/jstests/sharding/time_zone_info_mongos.js @@ -28,7 +28,9 @@ // Test that a non-existent timezone directory causes mongoS startup to fail. conn = MongoRunner.runMongos({configdb: st.configRS.getURL(), timeZoneInfo: tzNoInfo}); assert.eq(conn, null, "expected launching mongos with bad timezone rules to fail"); - assert.neq(-1, rawMongoProgramOutput().indexOf("Failed global initialization")); + // Look for either old or new error message + assert(rawMongoProgramOutput().indexOf("Failed to create service context") != -1 || + rawMongoProgramOutput().indexOf("Failed global initialization") != -1); // Enable sharding on the test DB and ensure its primary is st.shard0.shardName. assert.commandWorked(mongosDB.adminCommand({enableSharding: mongosDB.getName()})); diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript index 43af0a24e0e..8bdb16a9c98 100644 --- a/src/mongo/client/SConscript +++ b/src/mongo/client/SConscript @@ -37,6 +37,7 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/transport/transport_layer_egress_init', + '$BUILD_DIR/mongo/db/service_context_test_fixture', 'clientdriver_network', ], ) diff --git a/src/mongo/client/mongo_uri_test.cpp b/src/mongo/client/mongo_uri_test.cpp index 9584bfd6f9a..d934bcde049 100644 --- a/src/mongo/client/mongo_uri_test.cpp +++ b/src/mongo/client/mongo_uri_test.cpp @@ -35,18 +35,18 @@ #include "mongo/bson/bsontypes.h" #include "mongo/bson/json.h" #include "mongo/client/mongo_uri.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" #include <boost/filesystem/operations.hpp> +namespace mongo { namespace { -using mongo::MongoURI; - struct URITestCase { std::string URI; std::string uname; std::string password; - mongo::ConnectionString::ConnectionType type; + ConnectionString::ConnectionType type; std::string setname; size_t numservers; size_t numOptions; @@ -57,8 +57,8 @@ struct InvalidURITestCase { std::string URI; }; -const mongo::ConnectionString::ConnectionType kMaster = mongo::ConnectionString::MASTER; -const mongo::ConnectionString::ConnectionType kSet = mongo::ConnectionString::SET; +const ConnectionString::ConnectionType kMaster = ConnectionString::MASTER; +const ConnectionString::ConnectionType kSet = ConnectionString::SET; const URITestCase validCases[] = { @@ -407,34 +407,34 @@ const InvalidURITestCase invalidCases[] = { }; // Helper Method to take a filename for a json file and return the array of tests inside of it -mongo::BSONObj getBsonFromJsonFile(std::string fileName) { +BSONObj getBsonFromJsonFile(std::string fileName) { boost::filesystem::path directoryPath = boost::filesystem::current_path(); boost::filesystem::path filePath(directoryPath / "src" / "mongo" / "client" / "mongo_uri_tests" / fileName); std::string filename(filePath.string()); std::ifstream infile(filename.c_str()); std::string data((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>()); - mongo::BSONObj obj = mongo::fromjson(data); - ASSERT_TRUE(obj.valid(mongo::BSONVersion::kLatest)); + BSONObj obj = fromjson(data); + ASSERT_TRUE(obj.valid(BSONVersion::kLatest)); ASSERT_TRUE(obj.hasField("tests")); - mongo::BSONObj arr = obj.getField("tests").embeddedObject().getOwned(); + BSONObj arr = obj.getField("tests").embeddedObject().getOwned(); ASSERT_TRUE(arr.couldBeArray()); return arr; } // Helper method to take a BSONElement and either extract its string or return an empty string -std::string returnStringFromElementOrNull(mongo::BSONElement element) { +std::string returnStringFromElementOrNull(BSONElement element) { ASSERT_TRUE(!element.eoo()); - if (element.type() == mongo::jstNULL) { + if (element.type() == jstNULL) { return std::string(); } - ASSERT_EQ(element.type(), mongo::String); + ASSERT_EQ(element.type(), String); return element.String(); } // Helper method to take a valid test case, parse() it, and assure the output is correct void testValidURIFormat(URITestCase testCase) { - mongo::unittest::log() << "Testing URI: " << testCase.URI << '\n'; + unittest::log() << "Testing URI: " << testCase.URI << '\n'; std::string errMsg; const auto cs_status = MongoURI::parse(testCase.URI); ASSERT_OK(cs_status); @@ -462,13 +462,13 @@ TEST(MongoURI, InvalidURIs) { for (size_t i = 0; i != numCases; ++i) { const InvalidURITestCase testCase = invalidCases[i]; - mongo::unittest::log() << "Testing URI: " << testCase.URI << '\n'; + unittest::log() << "Testing URI: " << testCase.URI << '\n'; auto cs_status = MongoURI::parse(testCase.URI); ASSERT_NOT_OK(cs_status); } } -TEST(MongoURI, ValidButBadURIsFailToConnect) { +TEST_F(ServiceContextTest, ValidButBadURIsFailToConnect) { // "invalid" is a TLD that cannot exit on the public internet (see rfc2606). It should always // parse as a valid URI, but connecting should always fail. auto sw_uri = MongoURI::parse("mongodb://user:pass@hostname.invalid:12345"); @@ -477,7 +477,7 @@ TEST(MongoURI, ValidButBadURIsFailToConnect) { ASSERT_TRUE(uri.isValid()); std::string errmsg; - auto dbclient = uri.connect(mongo::StringData(), errmsg); + auto dbclient = uri.connect(StringData(), errmsg); ASSERT_EQ(dbclient, static_cast<decltype(dbclient)>(nullptr)); } @@ -494,7 +494,7 @@ TEST(MongoURI, CloneURIForServer) { auto& uriOptions = uri.getOptions(); ASSERT_EQ(uriOptions.at("ssl"), "true"); - auto clonedURI = uri.cloneURIForServer(mongo::HostAndPort{"localhost:27020"}); + auto clonedURI = uri.cloneURIForServer(HostAndPort{"localhost:27020"}); ASSERT_EQ(clonedURI.type(), kMaster); ASSERT_TRUE(clonedURI.getSetName().empty()); @@ -524,7 +524,7 @@ TEST(MongoURI, specTests) { const auto testBson = getBsonFromJsonFile(file); for (const auto& testElement : testBson) { - ASSERT_EQ(testElement.type(), mongo::Object); + ASSERT_EQ(testElement.type(), Object); const auto test = testElement.Obj(); // First extract the valid field and the uri field @@ -535,13 +535,13 @@ TEST(MongoURI, specTests) { const auto uriDoc = test.getField("uri"); ASSERT_FALSE(uriDoc.eoo()); - ASSERT_EQ(uriDoc.type(), mongo::String); + ASSERT_EQ(uriDoc.type(), String); const auto uri = uriDoc.String(); if (!valid) { // This uri string is invalid --> parse the uri and ensure it fails const InvalidURITestCase testCase = {uri}; - mongo::unittest::log() << "Testing URI: " << testCase.URI << '\n'; + unittest::log() << "Testing URI: " << testCase.URI << '\n'; auto cs_status = MongoURI::parse(testCase.URI); ASSERT_NOT_OK(cs_status); } else { @@ -552,8 +552,8 @@ TEST(MongoURI, specTests) { const auto auth = test.getField("auth"); ASSERT_FALSE(auth.eoo()); - if (auth.type() != mongo::jstNULL) { - ASSERT_EQ(auth.type(), mongo::Object); + if (auth.type() != jstNULL) { + ASSERT_EQ(auth.type(), Object); const auto authObj = auth.embeddedObject(); database = returnStringFromElementOrNull(authObj.getField("db")); username = returnStringFromElementOrNull(authObj.getField("username")); @@ -563,22 +563,22 @@ TEST(MongoURI, specTests) { // parse the hosts const auto hosts = test.getField("hosts"); ASSERT_FALSE(hosts.eoo()); - ASSERT_EQ(hosts.type(), mongo::Array); + ASSERT_EQ(hosts.type(), Array); const auto numHosts = static_cast<size_t>(hosts.Obj().nFields()); // parse the options - mongo::ConnectionString::ConnectionType connectionType = kMaster; + ConnectionString::ConnectionType connectionType = kMaster; size_t numOptions = 0; std::string setName; const auto optionsElement = test.getField("options"); ASSERT_FALSE(optionsElement.eoo()); - if (optionsElement.type() != mongo::jstNULL) { - ASSERT_EQ(optionsElement.type(), mongo::Object); + if (optionsElement.type() != jstNULL) { + ASSERT_EQ(optionsElement.type(), Object); const auto optionsObj = optionsElement.Obj(); numOptions = optionsObj.nFields(); const auto replsetElement = optionsObj.getField("replicaSet"); if (!replsetElement.eoo()) { - ASSERT_EQ(replsetElement.type(), mongo::String); + ASSERT_EQ(replsetElement.type(), String); setName = replsetElement.String(); connectionType = kSet; } @@ -600,7 +600,6 @@ TEST(MongoURI, specTests) { } TEST(MongoURI, srvRecordTest) { - using namespace mongo; enum Expectation : bool { success = true, failure = false }; const struct { int lineNumber; @@ -843,11 +842,10 @@ TEST(MongoURI, srvRecordTest) { for (std::size_t i = 0; i < std::min(options.size(), expectedOptions.size()); ++i) { if (options[i] != expectedOptions[i]) { - mongo::unittest::log() << "Option: \"" << options[i].first << "=" - << options[i].second << "\" doesn't equal: \"" - << expectedOptions[i].first << "=" - << expectedOptions[i].second << "\"" - << " data on line: " << test.lineNumber << std::endl; + unittest::log() << "Option: \"" << options[i].first << "=" << options[i].second + << "\" doesn't equal: \"" << expectedOptions[i].first << "=" + << expectedOptions[i].second << "\"" + << " data on line: " << test.lineNumber << std::endl; std::cerr << "Failing URI: \"" << test.uri << "\"" << " data on line: " << test.lineNumber << std::endl; ASSERT(false); @@ -874,3 +872,4 @@ TEST(MongoURI, srvRecordTest) { } } // namespace +} // namespace mongo diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index afa17539d9f..b792d074862 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -679,6 +679,7 @@ env.CppUnitTest( 'auth/authmocks', 'catalog/database_holder_mock', 'catalog_raii', + 'service_context_test_fixture', 'stats/fill_locker_info', ], ) diff --git a/src/mongo/db/catalog_raii_test.cpp b/src/mongo/db/catalog_raii_test.cpp index 05a0bfeb1cb..fc78ed36cfa 100644 --- a/src/mongo/db/catalog_raii_test.cpp +++ b/src/mongo/db/catalog_raii_test.cpp @@ -36,6 +36,7 @@ #include "mongo/db/client.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/concurrency/lock_state.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" #include "mongo/util/log.h" #include "mongo/util/time_support.h" @@ -43,13 +44,13 @@ namespace mongo { namespace { -class CatalogRAIITestFixture : public unittest::Test { +class CatalogRAIITestFixture : public ServiceContextTest { public: typedef std::pair<ServiceContext::UniqueClient, ServiceContext::UniqueOperationContext> ClientAndCtx; ClientAndCtx makeClientWithLocker(const std::string& clientName) { - auto client = getGlobalServiceContext()->makeClient(clientName); + auto client = getServiceContext()->makeClient(clientName); auto opCtx = client->makeOperationContext(); opCtx->swapLockState(stdx::make_unique<LockerImpl>()); return std::make_pair(std::move(client), std::move(opCtx)); diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 36c5bd0b149..19762719102 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -364,7 +364,7 @@ ExitCode _initAndListen(int listenPort) { } // Disallow running a storage engine that doesn't support capped collections with --profile - if (!getGlobalServiceContext()->getStorageEngine()->supportsCappedCollections() && + if (!serviceContext->getStorageEngine()->supportsCappedCollections() && serverGlobalParams.defaultProfile != 0) { log() << "Running " << storageGlobalParams.engine << " with profiling is not supported. " << "Make sure you are not using --profile."; @@ -803,10 +803,7 @@ auto makeReplicationExecutor(ServiceContext* serviceContext) { executor::makeNetworkInterface("Replication", nullptr, std::move(hookList))); } -MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager, - ("SSLManager", "ServiceContext", "default")) -(InitializerContext* context) { - auto serviceContext = getGlobalServiceContext(); +void setUpReplication(ServiceContext* serviceContext) { repl::StorageInterface::set(serviceContext, stdx::make_unique<repl::StorageInterfaceImpl>()); auto storageInterface = repl::StorageInterface::get(serviceContext); @@ -843,7 +840,6 @@ MONGO_INITIALIZER_WITH_PREREQUISITES(CreateReplicationManager, static_cast<int64_t>(curTimeMillis64())); repl::ReplicationCoordinator::set(serviceContext, std::move(replCoord)); repl::setOplogCollectionName(serviceContext); - return Status::OK(); } #ifdef MONGO_CONFIG_SSL @@ -990,7 +986,17 @@ int mongoDbMain(int argc, char* argv[], char** envp) { severe(LogComponent::kControl) << "Failed global initialization: " << status; quickExit(EXIT_FAILURE); } + + try { + setGlobalServiceContext(ServiceContext::make()); + } catch (...) { + auto cause = exceptionToStatus(); + severe(LogComponent::kControl) << "Failed to create service context: " << redact(cause); + quickExit(EXIT_FAILURE); + } + auto service = getGlobalServiceContext(); + setUpReplication(service); service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service)); ErrorExtraInfo::invariantHaveAllParsers(); diff --git a/src/mongo/db/query/datetime/init_timezone_data.cpp b/src/mongo/db/query/datetime/init_timezone_data.cpp index 18a842f231c..d93f9202b32 100644 --- a/src/mongo/db/query/datetime/init_timezone_data.cpp +++ b/src/mongo/db/query/datetime/init_timezone_data.cpp @@ -38,28 +38,25 @@ #include "mongo/util/mongoutils/str.h" namespace mongo { - -MONGO_INITIALIZER_WITH_PREREQUISITES( - LoadTimeZoneDB, ("GlobalLogManager", "EndStartupOptionStorage", "ServiceContext")) -(InitializerContext* context) { - auto serviceContext = getGlobalServiceContext(); - if (!serverGlobalParams.timeZoneInfoPath.empty()) { - std::unique_ptr<timelib_tzdb, TimeZoneDatabase::TimeZoneDBDeleter> timeZoneDatabase( - timelib_zoneinfo(const_cast<char*>(serverGlobalParams.timeZoneInfoPath.c_str())), - TimeZoneDatabase::TimeZoneDBDeleter()); - if (!timeZoneDatabase) { - return {ErrorCodes::FailedToParse, - str::stream() << "failed to load time zone database from path \"" - << serverGlobalParams.timeZoneInfoPath - << "\""}; +namespace { +ServiceContext::ConstructorActionRegisterer loadTimeZoneDB{ + "LoadTimeZoneDB", [](ServiceContext* service) { + if (!serverGlobalParams.timeZoneInfoPath.empty()) { + std::unique_ptr<timelib_tzdb, TimeZoneDatabase::TimeZoneDBDeleter> timeZoneDatabase( + timelib_zoneinfo(const_cast<char*>(serverGlobalParams.timeZoneInfoPath.c_str())), + TimeZoneDatabase::TimeZoneDBDeleter()); + if (!timeZoneDatabase) { + uasserted(ErrorCodes::FailedToParse, + str::stream() << "failed to load time zone database from path \"" + << serverGlobalParams.timeZoneInfoPath + << "\""); + } + TimeZoneDatabase::set(service, + stdx::make_unique<TimeZoneDatabase>(std::move(timeZoneDatabase))); + } else { + // No 'zoneInfo' specified on the command line, fall back to the built-in rules. + TimeZoneDatabase::set(service, stdx::make_unique<TimeZoneDatabase>()); } - TimeZoneDatabase::set(serviceContext, - stdx::make_unique<TimeZoneDatabase>(std::move(timeZoneDatabase))); - } else { - // No 'zoneInfo' specified on the command line, fall back to the built-in rules. - TimeZoneDatabase::set(serviceContext, stdx::make_unique<TimeZoneDatabase>()); - } - return Status::OK(); -} - + }}; +} // namespace } // namespace mongo diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index e413e6d8323..06c1d23ee06 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -884,6 +884,7 @@ env.CppUnitTest( 'repl_coordinator_impl', 'replmocks', '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/service_context_test_fixture', ], ) @@ -1027,6 +1028,7 @@ env.CppUnitTest('isself_test', '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/serveronly', '$BUILD_DIR/mongo/db/service_context_d', + '$BUILD_DIR/mongo/db/service_context_test_fixture', 'isself', ], ) @@ -1218,6 +1220,7 @@ env.Library( ], LIBDEPS=[ 'replmocks', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/util/concurrency/thread_pool', ], @@ -1299,6 +1302,7 @@ env.CppUnitTest( 'oplog_entry', 'replmocks', '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], @@ -1382,6 +1386,7 @@ env.CppUnitTest( LIBDEPS=[ 'multiapplier', '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/unittest/task_executor_proxy', ], @@ -1464,6 +1469,7 @@ env.CppUnitTest( '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/commands/feature_compatibility_parsers', '$BUILD_DIR/mongo/db/query/command_request_response', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture', '$BUILD_DIR/mongo/unittest/concurrency', 'base_cloner_test_fixture', diff --git a/src/mongo/db/repl/base_cloner_test_fixture.h b/src/mongo/db/repl/base_cloner_test_fixture.h index 7e6900a2785..bb266948a08 100644 --- a/src/mongo/db/repl/base_cloner_test_fixture.h +++ b/src/mongo/db/repl/base_cloner_test_fixture.h @@ -37,6 +37,7 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/repl/collection_cloner.h" #include "mongo/db/repl/storage_interface_mock.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/stdx/condition_variable.h" @@ -53,7 +54,8 @@ namespace repl { class BaseCloner; -class BaseClonerTest : public executor::ThreadPoolExecutorTest { +class BaseClonerTest : public executor::ThreadPoolExecutorTest, + public ScopedGlobalServiceContextForTest { public: typedef executor::NetworkInterfaceMock::NetworkOperationIterator NetworkOperationIterator; diff --git a/src/mongo/db/repl/databases_cloner_test.cpp b/src/mongo/db/repl/databases_cloner_test.cpp index b6e9f97431e..f32c83c756a 100644 --- a/src/mongo/db/repl/databases_cloner_test.cpp +++ b/src/mongo/db/repl/databases_cloner_test.cpp @@ -38,6 +38,7 @@ #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/repl/storage_interface.h" #include "mongo/db/repl/storage_interface_mock.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/stdx/mutex.h" @@ -77,7 +78,8 @@ struct StorageInterfaceResults { }; -class DBsClonerTest : public executor::ThreadPoolExecutorTest { +class DBsClonerTest : public executor::ThreadPoolExecutorTest, + public ScopedGlobalServiceContextForTest { public: DBsClonerTest() : _storageInterface{}, _dbWorkThreadPool(ThreadPool::Options()) {} diff --git a/src/mongo/db/repl/initial_syncer_test.cpp b/src/mongo/db/repl/initial_syncer_test.cpp index 0f0f95e9fa1..2948a08ff01 100644 --- a/src/mongo/db/repl/initial_syncer_test.cpp +++ b/src/mongo/db/repl/initial_syncer_test.cpp @@ -56,6 +56,7 @@ #include "mongo/db/repl/sync_source_selector_mock.h" #include "mongo/db/repl/task_executor_mock.h" #include "mongo/db/repl/update_position_args.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/stdx/mutex.h" @@ -112,7 +113,9 @@ struct CollectionCloneInfo { Status status{ErrorCodes::NotYetInitialized, ""}; }; -class InitialSyncerTest : public executor::ThreadPoolExecutorTest, public SyncSourceSelector { +class InitialSyncerTest : public executor::ThreadPoolExecutorTest, + public SyncSourceSelector, + public ScopedGlobalServiceContextForTest { public: InitialSyncerTest() {} @@ -419,6 +422,7 @@ protected: _dbWorkThreadPool.reset(); _replicationProcess.reset(); _storageInterface.reset(); + Client::destroy(); } /** diff --git a/src/mongo/db/repl/isself_test.cpp b/src/mongo/db/repl/isself_test.cpp index 55a13c675d7..2fa60b5ae4c 100644 --- a/src/mongo/db/repl/isself_test.cpp +++ b/src/mongo/db/repl/isself_test.cpp @@ -31,6 +31,7 @@ #include "mongo/db/repl/isself.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/net/socket_utils.h" @@ -43,7 +44,7 @@ namespace { using std::string; -TEST(IsSelf, DetectsSameHostIPv4) { +TEST_F(ServiceContextTest, DetectsSameHostIPv4) { #if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) bool wasEnabled = IPv6Enabled(); enableIPv6(false); @@ -60,7 +61,7 @@ TEST(IsSelf, DetectsSameHostIPv4) { #endif } -TEST(IsSelf, DetectsSameHostIPv6) { +TEST_F(ServiceContextTest, DetectsSameHostIPv6) { #if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) bool wasEnabled = IPv6Enabled(); enableIPv6(true); diff --git a/src/mongo/db/repl/multiapplier_test.cpp b/src/mongo/db/repl/multiapplier_test.cpp index 52ba1fd23d2..cde8f7c0c60 100644 --- a/src/mongo/db/repl/multiapplier_test.cpp +++ b/src/mongo/db/repl/multiapplier_test.cpp @@ -31,6 +31,7 @@ #include "mongo/db/client.h" #include "mongo/db/jsobj.h" #include "mongo/db/repl/multiapplier.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_task_executor_test_fixture.h" #include "mongo/unittest/unittest.h" @@ -40,7 +41,8 @@ namespace { using namespace mongo; using namespace mongo::repl; -class MultiApplierTest : public executor::ThreadPoolExecutorTest { +class MultiApplierTest : public executor::ThreadPoolExecutorTest, + ScopedGlobalServiceContextForTest { public: private: executor::ThreadPoolMock::Options makeThreadPoolMockOptions() const override; diff --git a/src/mongo/db/repl/repl_set_config_checks_test.cpp b/src/mongo/db/repl/repl_set_config_checks_test.cpp index 3dce745a2fa..5cbc1909347 100644 --- a/src/mongo/db/repl/repl_set_config_checks_test.cpp +++ b/src/mongo/db/repl/repl_set_config_checks_test.cpp @@ -36,13 +36,14 @@ #include "mongo/db/repl/replication_coordinator_external_state_mock.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { namespace repl { namespace { -TEST(ValidateConfigForInitiate, VersionMustBe1) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_VersionMustBe1) { ReplicationCoordinatorExternalStateMock rses; rses.addSelf(HostAndPort("h1")); @@ -60,7 +61,7 @@ TEST(ValidateConfigForInitiate, VersionMustBe1) { validateConfigForInitiate(&rses, config, getGlobalServiceContext()).getStatus()); } -TEST(ValidateConfigForInitiate, MustFindSelf) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_MustFindSelf) { ReplSetConfig config; ASSERT_OK(config.initializeForInitiate(BSON("_id" << "rs0" @@ -95,7 +96,7 @@ TEST(ValidateConfigForInitiate, MustFindSelf) { &presentOnceExternalState, config, getGlobalServiceContext()))); } -TEST(ValidateConfigForInitiate, SelfMustBeElectable) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_SelfMustBeElectable) { ReplSetConfig config; ASSERT_OK(config.initializeForInitiate(BSON("_id" << "rs0" @@ -121,7 +122,7 @@ TEST(ValidateConfigForInitiate, SelfMustBeElectable) { .getStatus()); } -TEST(ValidateConfigForInitiate, WriteConcernMustBeSatisfiable) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_WriteConcernMustBeSatisfiable) { ReplSetConfig config; ASSERT_OK( config.initializeForInitiate(BSON("_id" @@ -144,7 +145,7 @@ TEST(ValidateConfigForInitiate, WriteConcernMustBeSatisfiable) { .getStatus()); } -TEST(ValidateConfigForInitiate, ArbiterPriorityMustBeZeroOrOne) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_ArbiterPriorityMustBeZeroOrOne) { ReplSetConfig zeroConfig; ReplSetConfig oneConfig; ReplSetConfig twoConfig; @@ -216,7 +217,7 @@ TEST(ValidateConfigForInitiate, ArbiterPriorityMustBeZeroOrOne) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigVersionNumberMustBeHigherThanOld) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigVersionNumberMustBeHigherThanOld) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -284,7 +285,7 @@ TEST(ValidateConfigForReconfig, NewConfigVersionNumberMustBeHigherThanOld) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigMustNotChangeSetName) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotChangeSetName) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -333,7 +334,7 @@ TEST(ValidateConfigForReconfig, NewConfigMustNotChangeSetName) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigMustNotChangeSetId) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotChangeSetId) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -388,7 +389,7 @@ TEST(ValidateConfigForReconfig, NewConfigMustNotChangeSetId) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigMustNotFlipBuildIndexesFlag) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotFlipBuildIndexesFlag) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -470,7 +471,7 @@ TEST(ValidateConfigForReconfig, NewConfigMustNotFlipBuildIndexesFlag) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigMustNotFlipArbiterFlag) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotFlipArbiterFlag) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -545,7 +546,7 @@ TEST(ValidateConfigForReconfig, NewConfigMustNotFlipArbiterFlag) { .getStatus()); } -TEST(ValidateConfigForReconfig, HostAndIdRemappingRestricted) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_HostAndIdRemappingRestricted) { // When reconfiguring a replica set, it is allowed to introduce (host, id) pairs // absent from the old config only when the hosts and ids were both individually // absent in the old config. @@ -654,7 +655,7 @@ TEST(ValidateConfigForReconfig, HostAndIdRemappingRestricted) { .getStatus()); } -TEST(ValidateConfigForReconfig, MustFindSelf) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_MustFindSelf) { // Old and new config are same except for version change; this is just testing that we can // find ourself in the new config. ReplSetConfig oldConfig; @@ -725,7 +726,7 @@ TEST(ValidateConfigForReconfig, MustFindSelf) { &presentOnceExternalState, oldConfig, newConfig, getGlobalServiceContext(), true))); } -TEST(ValidateConfigForReconfig, ArbiterPriorityValueMustBeZeroOrOne) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_ArbiterPriorityValueMustBeZeroOrOne) { ReplicationCoordinatorExternalStateMock externalState; externalState.addSelf(HostAndPort("h1")); @@ -823,7 +824,7 @@ TEST(ValidateConfigForReconfig, ArbiterPriorityValueMustBeZeroOrOne) { .getStatus()); } -TEST(ValidateConfigForReconfig, SelfMustEndElectable) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_SelfMustEndElectable) { // Old and new config are same except for version change and the electability of one node; // this is just testing that we must be electable in the new config. ReplSetConfig oldConfig; @@ -871,7 +872,7 @@ TEST(ValidateConfigForReconfig, SelfMustEndElectable) { .getStatus()); } -TEST(ValidateConfigForInitiate, NewConfigInvalid) { +TEST_F(ServiceContextTest, ValidateConfigForInitiate_NewConfigInvalid) { // The new config is not valid due to a duplicate _id value. This tests that if the new // config is invalid, validateConfigForInitiate will return a status indicating what is // wrong with the new config. @@ -896,7 +897,7 @@ TEST(ValidateConfigForInitiate, NewConfigInvalid) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigInvalid) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigInvalid) { // The new config is not valid due to a duplicate _id value. This tests that if the new // config is invalid, validateConfigForReconfig will return a status indicating what is // wrong with the new config. @@ -939,7 +940,7 @@ TEST(ValidateConfigForReconfig, NewConfigInvalid) { .getStatus()); } -TEST(ValidateConfigForReconfig, NewConfigWriteConcernNotSatisifiable) { +TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigWriteConcernNotSatisifiable) { // The new config is not valid due to an unsatisfiable write concern. This tests that if the // new config is invalid, validateConfigForReconfig will return a status indicating what is // wrong with the new config. @@ -982,7 +983,7 @@ TEST(ValidateConfigForReconfig, NewConfigWriteConcernNotSatisifiable) { .getStatus()); } -TEST(ValidateConfigForStartUp, NewConfigInvalid) { +TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigInvalid) { // The new config is not valid due to a duplicate _id value. This tests that if the new // config is invalid, validateConfigForStartUp will return a status indicating what is wrong // with the new config. @@ -1007,7 +1008,7 @@ TEST(ValidateConfigForStartUp, NewConfigInvalid) { .getStatus()); } -TEST(ValidateConfigForStartUp, NewConfigValid) { +TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigValid) { // The new config is valid. This tests that validateConfigForStartUp will return a // Status::OK() indicating the validity of this configuration. ReplSetConfig newConfig; @@ -1032,7 +1033,7 @@ TEST(ValidateConfigForStartUp, NewConfigValid) { .getStatus()); } -TEST(ValidateConfigForStartUp, NewConfigWriteConcernNotSatisfiable) { +TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigWriteConcernNotSatisfiable) { // The new config contains an unsatisfiable write concern. We don't allow these configs to be // created anymore, but we allow any which exist to pass and the database to start up to // maintain backwards compatibility. @@ -1056,7 +1057,7 @@ TEST(ValidateConfigForStartUp, NewConfigWriteConcernNotSatisfiable) { .getStatus()); } -TEST(ValidateConfigForHeartbeatReconfig, NewConfigInvalid) { +TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigInvalid) { // The new config is not valid due to a duplicate _id value. This tests that if the new // config is invalid, validateConfigForHeartbeatReconfig will return a status indicating // what is wrong with the new config. @@ -1081,7 +1082,7 @@ TEST(ValidateConfigForHeartbeatReconfig, NewConfigInvalid) { .getStatus()); } -TEST(ValidateConfigForHeartbeatReconfig, NewConfigValid) { +TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigValid) { // The new config is valid. This tests that validateConfigForHeartbeatReconfig will return // a Status::OK() indicating the validity of this config change. ReplSetConfig newConfig; @@ -1104,7 +1105,7 @@ TEST(ValidateConfigForHeartbeatReconfig, NewConfigValid) { .getStatus()); } -TEST(ValidateConfigForHeartbeatReconfig, NewConfigWriteConcernNotSatisfiable) { +TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigWriteConcernNotSatisfiable) { // The new config contains an unsatisfiable write concern. We don't allow these configs to be // created anymore, but we allow any which exist to be received in a heartbeat. ReplSetConfig newConfig; @@ -1129,7 +1130,7 @@ TEST(ValidateConfigForHeartbeatReconfig, NewConfigWriteConcernNotSatisfiable) { .getStatus()); } -TEST(ValidateForReconfig, ForceStillNeedsValidConfig) { +TEST_F(ServiceContextTest, ValidateForReconfig_ForceStillNeedsValidConfig) { // The new config is invalid due to two nodes with the same _id value. This tests that // ValidateForReconfig fails with an invalid config, even if force is true. ReplSetConfig oldConfig; @@ -1168,7 +1169,7 @@ TEST(ValidateForReconfig, ForceStillNeedsValidConfig) { .getStatus()); } -TEST(ValidateForReconfig, ForceStillNeedsSelfPresent) { +TEST_F(ServiceContextTest, ValidateForReconfig_ForceStillNeedsSelfPresent) { // The new config does not contain self. This tests that ValidateForReconfig fails // if the member receiving it is absent from the config, even if force is true. ReplSetConfig oldConfig; diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp index bac2809f798..038cb0a67c4 100644 --- a/src/mongo/db/service_context.cpp +++ b/src/mongo/db/service_context.cpp @@ -349,22 +349,6 @@ void ServiceContext::notifyStartupComplete() { namespace { -// clang-format off -GlobalInitializerRegisterer registerCreateServiceContext{ - "ServiceContext", - {"default"}, - [](InitializerContext* context) { - setGlobalServiceContext(ServiceContext::make()); - return Status::OK(); - }, - [](DeinitializerContext* context) { - // For now, deregistration is done manually after all deinitializers run, in case any - // erroneously access the globalServiceContext without expressing a dependency. - return Status::OK(); - } -}; -// clang-format on - /** * Accessor function to get the global list of ServiceContext constructor and destructor * functions. @@ -390,7 +374,6 @@ ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( destructor = [](ServiceContext*) {}; _registerer.emplace(std::move(name), std::move(prereqs), - std::vector<std::string>{"ServiceContext"}, [this, constructor, destructor](InitializerContext* context) { _iter = registeredConstructorActions().emplace( registeredConstructorActions().end(), diff --git a/src/mongo/db/service_context_test_fixture.cpp b/src/mongo/db/service_context_test_fixture.cpp index 486478f56e6..e9aba482801 100644 --- a/src/mongo/db/service_context_test_fixture.cpp +++ b/src/mongo/db/service_context_test_fixture.cpp @@ -38,23 +38,29 @@ namespace mongo { -ServiceContextTest::ServiceContextTest() { +ScopedGlobalServiceContextForTest::ScopedGlobalServiceContextForTest() { setGlobalServiceContext(ServiceContext::make()); auto const serviceContext = getGlobalServiceContext(); - Client::initThread(getThreadName()); auto observerRegistry = std::make_unique<OpObserverRegistry>(); serviceContext->setOpObserver(std::move(observerRegistry)); } -ServiceContextTest::~ServiceContextTest() { - Client::destroy(); +ScopedGlobalServiceContextForTest::~ScopedGlobalServiceContextForTest() { setGlobalServiceContext({}); } -ServiceContext* ServiceContextTest::getServiceContext() { +ServiceContext* ScopedGlobalServiceContextForTest::getServiceContext() { return getGlobalServiceContext(); } +ServiceContextTest::ServiceContextTest() { + Client::initThread(getThreadName()); +} + +ServiceContextTest::~ServiceContextTest() { + Client::destroy(); +} + Client* ServiceContextTest::getClient() { return Client::getCurrent(); } diff --git a/src/mongo/db/service_context_test_fixture.h b/src/mongo/db/service_context_test_fixture.h index 1e23c6666d2..8588b1e18e5 100644 --- a/src/mongo/db/service_context_test_fixture.h +++ b/src/mongo/db/service_context_test_fixture.h @@ -34,17 +34,25 @@ namespace mongo { -/** - * Test fixture for tests that require a properly initialized global service context. - */ -class ServiceContextTest : public unittest::Test { + +class ScopedGlobalServiceContextForTest { public: /** - * Returns a service context, which is only valid for this instance of the test. - * Must not be called before setUp or after tearDown. - */ + * Returns a service context, which is only valid for this instance of the test. + * Must not be called before setUp or after tearDown. + */ ServiceContext* getServiceContext(); +protected: + ScopedGlobalServiceContextForTest(); + virtual ~ScopedGlobalServiceContextForTest(); +}; + +/** + * Test fixture for tests that require a properly initialized global service context. + */ +class ServiceContextTest : public unittest::Test, public ScopedGlobalServiceContextForTest { +public: /** * Returns the default Client for this test. */ diff --git a/src/mongo/db/sorter/SConscript b/src/mongo/db/sorter/SConscript index 0757cd5097d..7b5dd0bdd6e 100644 --- a/src/mongo/db/sorter/SConscript +++ b/src/mongo/db/sorter/SConscript @@ -7,6 +7,7 @@ sorterEnv.InjectThirdPartyIncludePaths(libraries=['snappy']) sorterEnv.CppUnitTest('sorter_test', 'sorter_test.cpp', LIBDEPS=['$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/storage/encryption_hooks', '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/s/is_mongos', diff --git a/src/mongo/db/sorter/sorter_test.cpp b/src/mongo/db/sorter/sorter_test.cpp index 3d9fc03b58f..d55bab970f4 100644 --- a/src/mongo/db/sorter/sorter_test.cpp +++ b/src/mongo/db/sorter/sorter_test.cpp @@ -36,6 +36,7 @@ #include "mongo/base/init.h" #include "mongo/base/static_assert.h" #include "mongo/config.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/platform/random.h" #include "mongo/stdx/thread.h" #include "mongo/unittest/temp_dir.h" @@ -239,7 +240,7 @@ public: } }; -class SortedFileWriterAndFileIteratorTests { +class SortedFileWriterAndFileIteratorTests : public ScopedGlobalServiceContextForTest { public: void run() { unittest::TempDir tempDir("sortedFileWriterTests"); @@ -325,7 +326,7 @@ public: }; namespace SorterTests { -class Basic { +class Basic : public ScopedGlobalServiceContextForTest { public: virtual ~Basic() {} diff --git a/src/mongo/db/storage/kv/SConscript b/src/mongo/db/storage/kv/SConscript index 7edb39d2366..384738813c0 100644 --- a/src/mongo/db/storage/kv/SConscript +++ b/src/mongo/db/storage/kv/SConscript @@ -114,6 +114,7 @@ env.CppUnitTest( 'kv_engine_mock', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/namespace_string', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/storage/devnull/storage_devnull_core', '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store', ], @@ -131,6 +132,7 @@ env.CppUnitTest( 'kv_engine_mock', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/namespace_string', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/storage/devnull/storage_devnull_core', '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store', ], diff --git a/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp b/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp index d2e4a77f7e9..b27937839b3 100644 --- a/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp +++ b/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp @@ -37,6 +37,7 @@ #include "mongo/db/index/multikey_paths.h" #include "mongo/db/index_names.h" #include "mongo/db/operation_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/storage/devnull/devnull_kv_engine.h" #include "mongo/db/storage/kv/kv_database_catalog_entry_mock.h" #include "mongo/db/storage/kv/kv_engine.h" @@ -48,7 +49,7 @@ namespace mongo { namespace { -class KVCollectionCatalogEntryTest : public unittest::Test { +class KVCollectionCatalogEntryTest : public ServiceContextTest { public: KVCollectionCatalogEntryTest() : _nss("unittests.kv_collection_catalog_entry"), diff --git a/src/mongo/db/storage/kv/kv_database_catalog_entry_test.cpp b/src/mongo/db/storage/kv/kv_database_catalog_entry_test.cpp index 0e122cf5603..353ce9f407f 100644 --- a/src/mongo/db/storage/kv/kv_database_catalog_entry_test.cpp +++ b/src/mongo/db/storage/kv/kv_database_catalog_entry_test.cpp @@ -33,6 +33,7 @@ #include "mongo/base/string_data.h" #include "mongo/db/catalog/collection_options.h" #include "mongo/db/operation_context_noop.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/storage/devnull/devnull_kv_engine.h" #include "mongo/db/storage/kv/kv_prefix.h" #include "mongo/db/storage/kv/kv_storage_engine.h" @@ -42,7 +43,7 @@ namespace mongo { namespace { -TEST(KVDatabaseCatalogEntryTest, CreateCollectionValidNamespace) { +TEST_F(ServiceContextTest, CreateCollectionValidNamespace) { KVStorageEngine storageEngine( new DevNullKVEngine(), KVStorageEngineOptions{}, kvDatabaseCatalogEntryMockFactory); storageEngine.finishInit(); @@ -54,7 +55,7 @@ TEST(KVDatabaseCatalogEntryTest, CreateCollectionValidNamespace) { ASSERT_FALSE(collectionNamespaces.empty()); } -TEST(KVDatabaseCatalogEntryTest, CreateCollectionEmptyNamespace) { +TEST_F(ServiceContextTest, CreateCollectionEmptyNamespace) { KVStorageEngine storageEngine( new DevNullKVEngine(), KVStorageEngineOptions{}, kvDatabaseCatalogEntryMockFactory); storageEngine.finishInit(); @@ -84,7 +85,7 @@ public: }; // After createCollection fails, collection namespaces should remain empty. -TEST(KVDatabaseCatalogEntryTest, CreateCollectionInvalidRecordStore) { +TEST_F(ServiceContextTest, CreateCollectionInvalidRecordStore) { KVStorageEngine storageEngine(new InvalidRecordStoreKVEngine(), KVStorageEngineOptions{}, kvDatabaseCatalogEntryMockFactory); diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript index 9d42061472d..72fb04cbcd3 100644 --- a/src/mongo/db/storage/wiredtiger/SConscript +++ b/src/mongo/db/storage/wiredtiger/SConscript @@ -128,6 +128,7 @@ if wiredtiger: '$BUILD_DIR/mongo/db/serveronly', '$BUILD_DIR/mongo/db/service_context', '$BUILD_DIR/mongo/db/service_context_d', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/storage/storage_engine_metadata', '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/db/storage/wiredtiger/storage_wiredtiger_core', diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp index 164d52013dd..0815bcf0bc8 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_init_test.cpp @@ -31,6 +31,7 @@ #include "mongo/db/json.h" #include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/storage/storage_engine_init.h" #include "mongo/db/storage/storage_engine_metadata.h" #include "mongo/db/storage/storage_options.h" @@ -43,7 +44,7 @@ namespace { using namespace mongo; -class WiredTigerFactoryTest : public mongo::unittest::Test { +class WiredTigerFactoryTest : public ServiceContextTest { private: virtual void setUp() { ServiceContext* globalEnv = getGlobalServiceContext(); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp index 2832d72bbf2..77906f1b222 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp @@ -47,6 +47,8 @@ namespace { class WiredTigerKVHarnessHelper : public KVHarnessHelper { public: WiredTigerKVHarnessHelper() : _dbpath("wt-kv-harness") { + if (!hasGlobalServiceContext()) + setGlobalServiceContext(ServiceContext::make()); _engine.reset(new WiredTigerKVEngine( kWiredTigerEngineName, _dbpath.path(), _cs.get(), "", 1, false, false, false, false)); repl::ReplicationCoordinator::set( @@ -57,6 +59,7 @@ public: virtual ~WiredTigerKVHarnessHelper() { _engine.reset(NULL); + // Cannot cleanup the global service context here, the test still have clients remaining. } virtual KVEngine* restartEngine() { diff --git a/src/mongo/db/update/SConscript b/src/mongo/db/update/SConscript index 405f3a5bb9c..ad97577a94a 100644 --- a/src/mongo/db/update/SConscript +++ b/src/mongo/db/update/SConscript @@ -117,6 +117,7 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils', + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/logical_clock', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', '$BUILD_DIR/mongo/db/query/query_test_service_context', diff --git a/src/mongo/db/update/update_node_test_fixture.h b/src/mongo/db/update/update_node_test_fixture.h index 050c9444e75..6da205a2cb8 100644 --- a/src/mongo/db/update/update_node_test_fixture.h +++ b/src/mongo/db/update/update_node_test_fixture.h @@ -30,12 +30,13 @@ #include "mongo/db/logical_clock.h" #include "mongo/db/service_context.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/db/update/update_node.h" #include "mongo/unittest/unittest.h" namespace mongo { -class UpdateNodeTest : public mongo::unittest::Test { +class UpdateNodeTest : public ServiceContextTest { public: ~UpdateNodeTest() override = default; diff --git a/src/mongo/dbtests/dbtests.cpp b/src/mongo/dbtests/dbtests.cpp index 07a4b4fe915..33aee8da3ab 100644 --- a/src/mongo/dbtests/dbtests.cpp +++ b/src/mongo/dbtests/dbtests.cpp @@ -168,6 +168,7 @@ int dbtestsMain(int argc, char** argv, char** envp) { ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42); repl::ReplSettings replSettings; replSettings.setOplogSizeBytes(10 * 1024 * 1024); + setGlobalServiceContext(ServiceContext::make()); ServiceContext* service = getGlobalServiceContext(); service->setServiceEntryPoint(std::make_unique<ServiceEntryPointMongod>(service)); diff --git a/src/mongo/embedded/embedded.cpp b/src/mongo/embedded/embedded.cpp index aa4b4133c5e..00b67e1c264 100644 --- a/src/mongo/embedded/embedded.cpp +++ b/src/mongo/embedded/embedded.cpp @@ -169,6 +169,7 @@ ServiceContext* initialize(const char* yaml_config) { Status status = mongo::runGlobalInitializers(yaml_config ? 1 : 0, argv, nullptr); uassertStatusOKWithContext(status, "Global initilization failed"); + setGlobalServiceContext(ServiceContext::make()); Client::initThread("initandlisten"); diff --git a/src/mongo/executor/task_executor_test_common.cpp b/src/mongo/executor/task_executor_test_common.cpp index 1d04675ae03..b2cd5a166cb 100644 --- a/src/mongo/executor/task_executor_test_common.cpp +++ b/src/mongo/executor/task_executor_test_common.cpp @@ -342,7 +342,7 @@ COMMON_EXECUTOR_TEST(EventWaitingWithTimeoutTest) { auto eventThatWillNeverBeTriggered = unittest::assertGet(executor.makeEvent()); - auto serviceContext = getGlobalServiceContext(); + auto serviceContext = ServiceContext::make(); serviceContext->setFastClockSource(stdx::make_unique<ClockSourceMock>()); auto mockClock = static_cast<ClockSourceMock*>(serviceContext->getFastClockSource()); @@ -364,7 +364,7 @@ COMMON_EXECUTOR_TEST(EventSignalWithTimeoutTest) { auto eventSignalled = unittest::assertGet(executor.makeEvent()); - auto serviceContext = getGlobalServiceContext(); + auto serviceContext = ServiceContext::make(); serviceContext->setFastClockSource(stdx::make_unique<ClockSourceMock>()); auto mockClock = static_cast<ClockSourceMock*>(serviceContext->getFastClockSource()); diff --git a/src/mongo/executor/task_executor_test_fixture.cpp b/src/mongo/executor/task_executor_test_fixture.cpp index f58657bacbb..d534377b643 100644 --- a/src/mongo/executor/task_executor_test_fixture.cpp +++ b/src/mongo/executor/task_executor_test_fixture.cpp @@ -65,6 +65,11 @@ void TaskExecutorTest::setUp() { _executor = makeTaskExecutor(std::move(net)); } +void TaskExecutorTest::tearDown() { + _executor.reset(nullptr); + _net = nullptr; +} + void TaskExecutorTest::launchExecutorThread() { _executor->startup(); postExecutorThreadLaunch(); diff --git a/src/mongo/executor/task_executor_test_fixture.h b/src/mongo/executor/task_executor_test_fixture.h index ff9904125d4..b99f90cb3af 100644 --- a/src/mongo/executor/task_executor_test_fixture.h +++ b/src/mongo/executor/task_executor_test_fixture.h @@ -72,6 +72,7 @@ public: * Initializes both the NetworkInterfaceMock and TaskExecutor but does not start the executor. */ void setUp() override; + void tearDown() override; void launchExecutorThread(); void shutdownExecutorThread(); diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index e460e41ad1a..4bb567eaf36 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -466,6 +466,7 @@ env.CppUnitTest( 'client/shard_connection_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/dbtests/mocklib', '$BUILD_DIR/mongo/util/net/network', 'client/sharding_connection_hook', diff --git a/src/mongo/s/client/shard_connection_test.cpp b/src/mongo/s/client/shard_connection_test.cpp index 927c4f1aeae..fd3d9dd9a14 100644 --- a/src/mongo/s/client/shard_connection_test.cpp +++ b/src/mongo/s/client/shard_connection_test.cpp @@ -30,6 +30,7 @@ #include <vector> #include "mongo/db/client.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/dbtests/mock/mock_conn_registry.h" #include "mongo/dbtests/mock/mock_dbclient_connection.h" #include "mongo/s/client/shard_connection.h" @@ -47,7 +48,7 @@ namespace { const std::string TARGET_HOST = "$dummy:27017"; -class ShardConnFixture : public unittest::Test { +class ShardConnFixture : public ServiceContextTest { public: void setUp() { Client::initThreadIfNotAlready("ShardConnFixture"); diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index d5d38e1cc34..0dc64211d36 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -559,7 +559,6 @@ ExitCode mongoSMain(int argc, char* argv[], char** envp) { if (argc < 1) return EXIT_BADOPTIONS; - registerShutdownTask([&]() { cleanupTask(getGlobalServiceContext()); }); setupSignalHandlers(); @@ -569,6 +568,16 @@ ExitCode mongoSMain(int argc, char* argv[], char** envp) { return EXIT_ABRUPT; } + try { + setGlobalServiceContext(ServiceContext::make()); + } catch (...) { + auto cause = exceptionToStatus(); + severe(LogComponent::kDefault) << "Failed to create service context: " << redact(cause); + return EXIT_ABRUPT; + } + + registerShutdownTask([&]() { cleanupTask(getGlobalServiceContext()); }); + ErrorExtraInfo::invariantHaveAllParsers(); startupConfigActions(std::vector<std::string>(argv, argv + argc)); diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp index c1d37dd0129..bf0a1d3a9db 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/dbshell.cpp @@ -743,7 +743,7 @@ int _main(int argc, char* argv[], char** envp) { mongo::shell_utils::RecordMyLocation(argv[0]); mongo::runGlobalInitializersOrDie(argc, argv, envp); - + setGlobalServiceContext(ServiceContext::make()); // TODO This should use a TransportLayerManager or TransportLayerFactory auto serviceContext = getGlobalServiceContext(); transport::TransportLayerASIO::Options opts; diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp index 26086ee29d1..01093145986 100644 --- a/src/mongo/tools/bridge.cpp +++ b/src/mongo/tools/bridge.cpp @@ -413,6 +413,7 @@ int bridgeMain(int argc, char** argv, char** envp) { runGlobalInitializersOrDie(argc, argv, envp); startSignalProcessingThread(LogFileStatus::kNoLogFileToRotate); + setGlobalServiceContext(ServiceContext::make()); auto serviceContext = getGlobalServiceContext(); serviceContext->setServiceEntryPoint(std::make_unique<ServiceEntryPointBridge>(serviceContext)); serviceContext->setServiceExecutor( diff --git a/src/mongo/unittest/SConscript b/src/mongo/unittest/SConscript index e3593d9ff8b..1193b6d2b07 100644 --- a/src/mongo/unittest/SConscript +++ b/src/mongo/unittest/SConscript @@ -46,6 +46,7 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/client/connection_string', + '$BUILD_DIR/mongo/db/service_context', '$BUILD_DIR/mongo/util/options_parser/options_parser_init', ], ) @@ -59,6 +60,7 @@ bmEnv.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/service_context', '$BUILD_DIR/third_party/shim_benchmark', ], ) diff --git a/src/mongo/unittest/benchmark_main.cpp b/src/mongo/unittest/benchmark_main.cpp index a29168ad5d5..8029a4005fa 100644 --- a/src/mongo/unittest/benchmark_main.cpp +++ b/src/mongo/unittest/benchmark_main.cpp @@ -34,6 +34,7 @@ #include "mongo/base/initializer.h" #include "mongo/config.h" +#include "mongo/db/service_context.h" #include "mongo/util/log.h" #include "mongo/util/signal_handlers_synchronous.h" @@ -43,6 +44,7 @@ int main(int argc, char** argv, char** envp) { ::mongo::setupSynchronousSignalHandlers(); ::mongo::runGlobalInitializersOrDie(argc, argv, envp); + ::mongo::setGlobalServiceContext(::mongo::ServiceContext::make()); // Copied from the BENCHMARK_MAIN macro. ::benchmark::Initialize(&argc, argv); diff --git a/src/mongo/unittest/integration_test_main.cpp b/src/mongo/unittest/integration_test_main.cpp index b2e3168bccc..20d2d8e0546 100644 --- a/src/mongo/unittest/integration_test_main.cpp +++ b/src/mongo/unittest/integration_test_main.cpp @@ -71,6 +71,7 @@ ConnectionString getFixtureConnectionString() { int main(int argc, char** argv, char** envp) { setupSynchronousSignalHandlers(); runGlobalInitializersOrDie(argc, argv, envp); + setGlobalServiceContext(ServiceContext::make()); quickExit(unittest::Suite::run(std::vector<std::string>(), "", 1)); } |