diff options
author | Gabriel Russell <gabriel.russell@mongodb.com> | 2020-03-02 17:48:47 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-04-14 17:02:16 +0000 |
commit | cdf9ea3b479bbffc1de900884ee10e29e7349bd2 (patch) | |
tree | 0da63f8345d2d0dc7e79b407da1726486fddbecb /src/mongo/unittest | |
parent | 298652908ebcc41ba28b1d68a3c6a90486ccce98 (diff) | |
download | mongo-cdf9ea3b479bbffc1de900884ee10e29e7349bd2.tar.gz |
SERVER-46568 removing the unittestOutput domain
Diffstat (limited to 'src/mongo/unittest')
-rw-r--r-- | src/mongo/unittest/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/unittest/death_test.cpp | 119 | ||||
-rw-r--r-- | src/mongo/unittest/death_test.h | 18 | ||||
-rw-r--r-- | src/mongo/unittest/unittest.cpp | 81 | ||||
-rw-r--r-- | src/mongo/unittest/unittest.h | 12 | ||||
-rw-r--r-- | src/mongo/unittest/unittest_test.cpp | 5 |
6 files changed, 123 insertions, 113 deletions
diff --git a/src/mongo/unittest/SConscript b/src/mongo/unittest/SConscript index d472bd49bcc..f7691b0c5cd 100644 --- a/src/mongo/unittest/SConscript +++ b/src/mongo/unittest/SConscript @@ -21,6 +21,7 @@ env.Library( LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/server_options_core', '$BUILD_DIR/mongo/util/options_parser/options_parser', + '$BUILD_DIR/mongo/util/debugger', ], ) diff --git a/src/mongo/unittest/death_test.cpp b/src/mongo/unittest/death_test.cpp index 31add6149ac..b33900aff90 100644 --- a/src/mongo/unittest/death_test.cpp +++ b/src/mongo/unittest/death_test.cpp @@ -30,6 +30,10 @@ #include "mongo/platform/basic.h" +#include <fmt/format.h> +#include <stdio.h> + +#include "mongo/bson/json.h" #include "mongo/unittest/death_test.h" #ifndef _WIN32 @@ -47,23 +51,36 @@ #include "mongo/logv2/log.h" #include "mongo/util/assert_util.h" +#include "mongo/util/debugger.h" #include "mongo/util/quick_exit.h" -#define checkSyscall(EXPR) \ - do { \ - if (-1 == (EXPR)) { \ - const int err = errno; \ - LOGV2_ERROR(24138, \ - "{expr} failed: {errno}", \ - "expr"_attr = #EXPR, \ - "errno"_attr = errnoWithDescription(err)); \ - invariantFailed("-1 != (" #EXPR ")", __FILE__, __LINE__); \ - } \ - } while (false) - namespace mongo { namespace unittest { +class DeathTestSyscallException : public std::runtime_error { +public: + using std::runtime_error::runtime_error; +}; + +#define logAndThrowWithErrno(expr) logAndThrowWithErrnoAt(expr, __FILE__, __LINE__, errno) + +void logAndThrowWithErrnoAt(const StringData expr, + const StringData file, + const unsigned line, + const int err) { + using namespace fmt::literals; + LOGV2_ERROR(24138, + "{expr} failed: {error} @{file}:{line}", + "expression failed", + "expr"_attr = expr, + "error"_attr = errnoWithDescription(err), + "file"_attr = file, + "line"_attr = line); + breakpoint(); + throw DeathTestSyscallException( + "{} failed: {} @{}:{}"_format(expr, errnoWithDescription(err), file, line)); +} + void DeathTestBase::_doTest() { #if defined(_WIN32) LOGV2(24133, "Skipping death test on Windows"); @@ -73,23 +90,47 @@ void DeathTestBase::_doTest() { return; #else int pipes[2]; - checkSyscall(pipe(pipes)); + if (pipe(pipes) == -1) + logAndThrowWithErrno("pipe()"); pid_t child; - checkSyscall(child = fork()); + if ((child = fork()) == -1) + logAndThrowWithErrno("fork()"); if (child) { - checkSyscall(close(pipes[1])); - char buf[1000]; + if (close(pipes[1]) == -1) + logAndThrowWithErrno("close(pipe[1])"); std::ostringstream os; + FILE* pf = 0; + if ((pf = fdopen(pipes[0], "r")) == NULL) + logAndThrowWithErrno("fdopen(pipe[0], \"r\")"); + auto pfGuard = makeGuard([&] { + if (fclose(pf) != 0) + logAndThrowWithErrno("fclose(pf)"); + }); + char* lineBuf = nullptr; + size_t lineBufSize = 0; + auto lineBufGuard = makeGuard([&] { free(lineBuf); }); ssize_t bytesRead; - LOGV2(24135, "========== Beginning of interleaved output of death test =========="); - while (0 < (bytesRead = read(pipes[0], buf, sizeof(buf)))) { - std::cout.write(buf, bytesRead); - invariant(std::cout); - os.write(buf, bytesRead); + while ((bytesRead = getline(&lineBuf, &lineBufSize, pf)) != -1) { + StringData line(lineBuf, bytesRead); + if (line.empty()) + continue; + if (line[line.size() - 1] == '\n') + line = line.substr(0, line.size() - 1); + if (line.empty()) + continue; + int parsedLen; + auto parsedChildLog = fromjson(lineBuf, &parsedLen); + if (static_cast<size_t>(parsedLen) == line.size()) { + LOGV2(20165, "child", "json"_attr = parsedChildLog); + } else { + LOGV2(20169, "child", "text"_attr = line); + } + os.write(lineBuf, bytesRead); invariant(os); } - LOGV2(24136, "========== End of interleaved output of death test =========="); - checkSyscall(bytesRead); + if (!feof(pf)) + logAndThrowWithErrno("getline(&buf, &bufSize, pf)"); + pid_t pid; int stat; while (child != (pid = waitpid(child, &stat, 0))) { @@ -99,20 +140,17 @@ void DeathTestBase::_doTest() { case EINTR: continue; default: - LOGV2_FATAL( - 24139, - "Unrecoverable error while waiting for {child}: {errnoWithDescription_err}", - "child"_attr = child, - "errnoWithDescription_err"_attr = errnoWithDescription(err)); - MONGO_UNREACHABLE; + logAndThrowWithErrno("waitpid(child, &stat, 0)"); } } if (WIFSIGNALED(stat) || (WIFEXITED(stat) && WEXITSTATUS(stat) != 0)) { // Exited with a signal or non-zero code. Validate the expected message. if (_isRegex()) { - ASSERT_STRING_SEARCH_REGEX(os.str(), _doGetPattern()); + ASSERT_STRING_SEARCH_REGEX(os.str(), _doGetPattern()) + << " @" << _getFile() << ":" << _getLine(); } else { - ASSERT_STRING_CONTAINS(os.str(), _doGetPattern()); + ASSERT_STRING_CONTAINS(os.str(), _doGetPattern()) + << " @" << _getFile() << ":" << _getLine(); } return; } else { @@ -122,18 +160,23 @@ void DeathTestBase::_doTest() { } // This code only executes in the child process. - checkSyscall(close(pipes[0])); - checkSyscall(dup2(pipes[1], 1)); - checkSyscall(dup2(1, 2)); + if (close(pipes[0]) == -1) + logAndThrowWithErrno("close(pipes[0])"); + if (dup2(pipes[1], 1) == -1) + logAndThrowWithErrno("dup2(pipes[1], 1)"); + if (dup2(1, 2) == -1) + logAndThrowWithErrno("dup2(1, 2)"); - // We disable the creation of core dump files in the child process since the child process is - // expected to exit uncleanly. This avoids unnecessarily creating core dump files when the child - // process calls std::abort() or std::terminate(). + // We disable the creation of core dump files in the child process since the child process + // is expected to exit uncleanly. This avoids unnecessarily creating core dump files when + // the child process calls std::abort() or std::terminate(). const struct rlimit kNoCoreDump { 0U, 0U }; - checkSyscall(setrlimit(RLIMIT_CORE, &kNoCoreDump)); + if (setrlimit(RLIMIT_CORE, &kNoCoreDump) == -1) + logAndThrowWithErrno("setrlimit(RLIMIT_CORE, &kNoCoreDump)"); try { auto test = _doMakeTest(); + LOGV2(23515, "Running DeathTest in child"); test->run(); LOGV2(20166, "Death test failed to die"); } catch (const TestAssertionFailureException& tafe) { diff --git a/src/mongo/unittest/death_test.h b/src/mongo/unittest/death_test.h index 599f3da2faa..f93f66c485f 100644 --- a/src/mongo/unittest/death_test.h +++ b/src/mongo/unittest/death_test.h @@ -96,6 +96,14 @@ return IS_REGEX; \ } \ \ + static int getLine() { \ + return __LINE__; \ + } \ + \ + static std::string getFile() { \ + return __FILE__; \ + } \ + \ private: \ void _doTest() override; \ static inline const RegistrationAgent<::mongo::unittest::DeathTest<TEST_TYPE>> _agent{ \ @@ -118,6 +126,8 @@ private: virtual std::unique_ptr<Test> _doMakeTest() = 0; virtual std::string _doGetPattern() = 0; virtual bool _isRegex() = 0; + virtual int _getLine() = 0; + virtual std::string _getFile() = 0; }; template <typename T> @@ -136,6 +146,14 @@ private: return T::isRegex(); } + int _getLine() override { + return T::getLine(); + } + + std::string _getFile() override { + return T::getFile(); + } + std::unique_ptr<Test> _doMakeTest() override { return _makeTest(); } diff --git a/src/mongo/unittest/unittest.cpp b/src/mongo/unittest/unittest.cpp index 2d0a1863cb5..608e97c1ad8 100644 --- a/src/mongo/unittest/unittest.cpp +++ b/src/mongo/unittest/unittest.cpp @@ -27,8 +27,7 @@ * it in the license file. */ -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault -#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kDefault #include "mongo/platform/basic.h" @@ -42,14 +41,15 @@ #include <map> #include <memory> -#include "mongo/base/checked_cast.h" -#include "mongo/base/init.h" -#include "mongo/db/server_options.h" #include "mongo/logger/console_appender.h" #include "mongo/logger/log_manager.h" #include "mongo/logger/logger.h" #include "mongo/logger/message_event_utf8_encoder.h" #include "mongo/logger/message_log_domain.h" + +#include "mongo/base/checked_cast.h" +#include "mongo/base/init.h" +#include "mongo/db/server_options.h" #include "mongo/logv2/bson_formatter.h" #include "mongo/logv2/component_settings_filter.h" #include "mongo/logv2/log.h" @@ -61,7 +61,6 @@ #include "mongo/logv2/plain_formatter.h" #include "mongo/platform/mutex.h" #include "mongo/util/assert_util.h" -#include "mongo/util/log.h" #include "mongo/util/stacktrace.h" #include "mongo/util/timer.h" @@ -73,11 +72,6 @@ bool stringContains(const std::string& haystack, const std::string& needle) { return haystack.find(needle) != std::string::npos; } -logger::MessageLogDomain* unittestOutput() { - static const auto p = logger::globalLogManager()->getNamedDomain("unittest"); - return p; -} - /** Each map key is owned by its corresponding Suite object. */ auto& suitesMap() { static std::map<StringData, std::shared_ptr<Suite>> m; @@ -86,28 +80,6 @@ auto& suitesMap() { } // namespace -logger::LogstreamBuilderDeprecated log() { - return LogstreamBuilderDeprecated( - unittestOutput(), getThreadName(), logger::LogSeverity::Log()); -} - -logger::LogstreamBuilderDeprecated warning() { - return LogstreamBuilderDeprecated( - unittestOutput(), getThreadName(), logger::LogSeverity::Warning()); -} - -void setupTestLogger() { - unittestOutput()->attachAppender( - std::make_unique<logger::ConsoleAppender<logger::MessageLogDomain::Event>>( - std::make_unique<logger::MessageEventDetailsEncoder>())); -} - -MONGO_INITIALIZER_WITH_PREREQUISITES(UnitTestOutput, ("GlobalLogManager", "default")) -(InitializerContext*) { - setupTestLogger(); - return Status::OK(); -} - class Result { public: struct FailStatus { @@ -235,8 +207,6 @@ private: // Captured BSON std::vector<std::string> _capturedBSONLogMessages; - logger::MessageLogDomain::AppenderHandle _captureAppenderHandle; - std::unique_ptr<logger::MessageLogDomain::EventAppender> _captureAppender; // Capture Sink for Plain Text boost::shared_ptr<boost::log::sinks::synchronous_sink<logv2::LogCaptureBackend>> _captureSink; @@ -315,43 +285,28 @@ void CaptureLogs::startCapturingLogMessages() { _capturedLogMessages.clear(); _capturedBSONLogMessages.clear(); - if (logV2Enabled()) { - if (!_captureSink) { - _captureSink = logv2::LogCaptureBackend::create(_capturedLogMessages); - _captureSink->set_filter( - logv2::AllLogsFilter(logv2::LogManager::global().getGlobalDomain())); - _captureSink->set_formatter(logv2::PlainFormatter()); + if (!_captureSink) { + _captureSink = logv2::LogCaptureBackend::create(_capturedLogMessages); + _captureSink->set_filter( + logv2::AllLogsFilter(logv2::LogManager::global().getGlobalDomain())); + _captureSink->set_formatter(logv2::PlainFormatter()); - _captureBSONSink = logv2::LogCaptureBackend::create(_capturedBSONLogMessages); + _captureBSONSink = logv2::LogCaptureBackend::create(_capturedBSONLogMessages); - _captureBSONSink->set_filter( - logv2::AllLogsFilter(logv2::LogManager::global().getGlobalDomain())); - _captureBSONSink->set_formatter(logv2::BSONFormatter()); - } - boost::log::core::get()->add_sink(_captureSink); - boost::log::core::get()->add_sink(_captureBSONSink); - } else { - if (!_captureAppender) { - _captureAppender = std::make_unique<StringVectorAppender>(&_capturedLogMessages); - } - checked_cast<StringVectorAppender*>(_captureAppender.get())->enable(); - _captureAppenderHandle = - logger::globalLogDomain()->attachAppender(std::move(_captureAppender)); + _captureBSONSink->set_filter( + logv2::AllLogsFilter(logv2::LogManager::global().getGlobalDomain())); + _captureBSONSink->set_formatter(logv2::BSONFormatter()); } + boost::log::core::get()->add_sink(_captureSink); + boost::log::core::get()->add_sink(_captureBSONSink); _isCapturingLogMessages = true; } void CaptureLogs::stopCapturingLogMessages() { invariant(_isCapturingLogMessages); - if (logV2Enabled()) { - boost::log::core::get()->remove_sink(_captureSink); - boost::log::core::get()->remove_sink(_captureBSONSink); - } else { - invariant(!_captureAppender); - _captureAppender = logger::globalLogDomain()->detachAppender(_captureAppenderHandle); - checked_cast<StringVectorAppender*>(_captureAppender.get())->disable(); - } + boost::log::core::get()->remove_sink(_captureSink); + boost::log::core::get()->remove_sink(_captureBSONSink); _isCapturingLogMessages = false; } diff --git a/src/mongo/unittest/unittest.h b/src/mongo/unittest/unittest.h index 8fa5869dc29..b2ffab38891 100644 --- a/src/mongo/unittest/unittest.h +++ b/src/mongo/unittest/unittest.h @@ -51,6 +51,7 @@ #include "mongo/base/string_data.h" #include "mongo/logger/logstream_builder.h" #include "mongo/logger/message_log_domain.h" +#include "mongo/logv2/log_detail.h" #include "mongo/unittest/bson_test_util.h" #include "mongo/unittest/unittest_helpers.h" #include "mongo/util/assert_util.h" @@ -347,15 +348,6 @@ namespace mongo::unittest { class Result; -void setupTestLogger(); - -/** - * Gets a LogstreamBuilder for logging to the unittest log domain, which may have - * different target from the global log domain. - */ -logger::LogstreamBuilderDeprecated log(); -logger::LogstreamBuilderDeprecated warning(); - /** * Representation of a collection of tests. * @@ -489,9 +481,7 @@ struct OldStyleSuiteInitializer { } void init(OldStyleSuiteSpecification& suiteSpec) const { - log() << "\t about to setupTests" << std::endl; suiteSpec.setupTests(); - log() << "\t done setupTests" << std::endl; auto& suite = Suite::getSuite(suiteSpec.name()); for (auto&& t : suiteSpec.tests()) { suite.add(t.name, "", t.fn); diff --git a/src/mongo/unittest/unittest_test.cpp b/src/mongo/unittest/unittest_test.cpp index 1689e5e3ebb..9d325b300f5 100644 --- a/src/mongo/unittest/unittest_test.cpp +++ b/src/mongo/unittest/unittest_test.cpp @@ -31,6 +31,8 @@ * Unit tests of the unittest framework itself. */ +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kDefault + #include "mongo/platform/basic.h" #include <functional> @@ -38,6 +40,7 @@ #include <string> #include "mongo/bson/bsonobjbuilder.h" +#include "mongo/logv2/log.h" #include "mongo/unittest/death_test.h" #include "mongo/unittest/unittest.h" #include "mongo/util/assert_util.h" @@ -270,7 +273,7 @@ class DeathTestSelfTestFixture : public ::mongo::unittest::Test { public: void setUp() override {} void tearDown() override { - mongo::unittest::log() << "Died in tear-down"; + LOGV2(24148, "Died in tear-down"); invariant(false); } }; |