diff options
Diffstat (limited to 'src/mongo/logger/log_test.cpp')
-rw-r--r-- | src/mongo/logger/log_test.cpp | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/src/mongo/logger/log_test.cpp b/src/mongo/logger/log_test.cpp deleted file mode 100644 index 464f3583a8b..00000000000 --- a/src/mongo/logger/log_test.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/logger/log_test.h" - -#include <sstream> -#include <string> -#include <vector> - -#include "mongo/logger/appender.h" -#include "mongo/logger/encoder.h" -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_component_settings.h" -#include "mongo/logger/log_test_util.h" -#include "mongo/logger/message_event_utf8_encoder.h" -#include "mongo/logger/message_log_domain.h" -#include "mongo/logger/rotatable_file_appender.h" -#include "mongo/logger/rotatable_file_writer.h" -#include "mongo/logv2/plain_formatter.h" -#include "mongo/logv2/text_formatter.h" -#include "mongo/platform/compiler.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/concurrency/thread_name.h" -#include "mongo/util/str.h" - -using namespace mongo::logger; - -namespace mongo { -namespace { - -typedef LogTest<MessageEventDetailsEncoder, logv2::TextFormatter> LogTestDetailsEncoder; -typedef LogTest<MessageEventUnadornedEncoder, logv2::PlainFormatter> LogTestUnadornedEncoder; - -class CountAppender : public Appender<MessageEventEphemeral> { -public: - CountAppender() : _count(0) {} - virtual ~CountAppender() {} - - virtual Status append(const MessageEventEphemeral& event) { - ++_count; - return Status::OK(); - } - - int getCount() { - return _count; - } - -private: - int _count; -}; - -/** Simple tests for detaching appenders. */ -TEST_F(LogTestUnadornedEncoder, DetachAppender) { - std::unique_ptr<MessageLogDomain::EventAppender> countAppender = - std::make_unique<CountAppender>(); - MessageLogDomain domain; - - // Appending to the domain before attaching the appender does not affect the appender. - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "1")) - .transitional_ignore(); - ASSERT_EQUALS(0, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); - - // Appending to the domain after attaching the appender does affect the appender. - MessageLogDomain::AppenderHandle handle = domain.attachAppender(std::move(countAppender)); - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "2")) - .transitional_ignore(); - countAppender = domain.detachAppender(handle); - ASSERT_EQUALS(1, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); - - // Appending to the domain after detaching the appender does not affect the appender. - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "3")) - .transitional_ignore(); - ASSERT_EQUALS(1, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); -} - -class A { -public: - std::string toString() const { - log() << "Golly!\n"; - return "Golly!"; - } -}; - -// Tests that logging while in the midst of logging produces two distinct log messages, with the -// inner log message appearing before the outer. -TEST_F(LogTestUnadornedEncoder, LogstreamBuilderReentrance) { - log() << "Logging A() -- " << A() << " -- done!" << std::endl; - ASSERT_EQUALS(2U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("Golly!")); - ASSERT(StringData(_logLines[1]).startsWith("Logging A() -- Golly! -- done!")); -} - -// -// Instantiating this object is a basic test of static-initializer-time logging. -// -class B { -public: - B() { - log() << "Exercising initializer time logging."; - } -} b; - -// Constants for log component test cases. -const LogComponent componentDefault = LogComponent::kDefault; -const LogComponent componentA = LogComponent::kCommand; -const LogComponent componentB = LogComponent::kAccessControl; -const LogComponent componentC = LogComponent::kNetwork; -const LogComponent componentD = LogComponent::kStorage; -const LogComponent componentE = LogComponent::kJournal; - -// No log component declared at file scope. -// Component severity configuration: -// LogComponent::kDefault: 2 -TEST_F(LogTestUnadornedEncoder, MongoLogMacroNoFileScopeLogComponent) { - setMinimumLoggedSeverity(LogSeverity::Debug(2)); - - LOG(2) << "This is logged"; - LOG(3) << "This is not logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("This is logged")); - - // MONGO_LOG_COMPONENT - _logLines.clear(); - MONGO_LOG_COMPONENT(2, componentA) << "This is logged"; - MONGO_LOG_COMPONENT(3, componentA) << "This is not logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("This is logged")); -} - -// -// Component log level tests. -// The global log manager holds the component log level configuration for the global log domain. -// LOG() and MONGO_LOG_COMPONENT() macros in util/log.h determine at runtime if a log message -// should be written to the log domain. -// - -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsMinimumLogSeverity) { - LogComponentSettings settings; - ASSERT_TRUE(settings.hasMinimumLogSeverity(LogComponent::kDefault)); - ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == LogSeverity::Log()); - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - if (component == LogComponent::kDefault) { - continue; - } - ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); - } - - // Override and clear minimum severity level. - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - LogSeverity severity = LogSeverity::Debug(2); - - // Override severity level. - settings.setMinimumLoggedSeverity(component, severity); - ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); - ASSERT_TRUE(settings.getMinimumLogSeverity(component) == severity); - - // Clear severity level. - // Special case: when clearing LogComponent::kDefault, the corresponding - // severity level is set to default values (ie. Log()). - settings.clearMinimumLoggedSeverity(component); - if (component == LogComponent::kDefault) { - ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); - ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == - LogSeverity::Log()); - } else { - ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); - } - } -} - -// Test for shouldLog() when the minimum logged severity is set only for LogComponent::kDefault. -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogDefaultLogComponentOnly) { - LogComponentSettings settings; - - // Initial log severity for LogComponent::kDefault is Log(). - ASSERT_TRUE(shouldLogV1(LogSeverity::Info())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Log())); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - // If any components are provided to shouldLog(), we should get the same outcome - // because we have not configured any non-LogComponent::kDefault components. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Log())); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - - // Set minimum logged severity so that Debug(1) messages are written to log domain. - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - ASSERT_TRUE(shouldLogV1(LogSeverity::Info())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Log())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - // Revert back. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); - - // Same results when components are supplied to shouldLog(). - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); -} - -// Test for shouldLog() when we have configured a single component. -// Also checks that severity level has been reverted to match LogComponent::kDefault -// after clearing level. -// Minimum severity levels: -// LogComponent::kDefault: 1 -// componentA: 2 -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogSingleComponent) { - LogComponentSettings settings; - - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); - - // Components for log message: componentA only. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); - - // Clear severity level for componentA and check shouldLog() again. - settings.clearMinimumLoggedSeverity(componentA); - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - - // Test shouldLog() with global settings. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - // Components for log message: LogComponent::kDefault only. - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); -} - -// Test for shouldLog() when we have configured multiple components. -// Minimum severity levels: -// LogComponent::kDefault: 1 -// componentA: 2 -// componentB: 0 -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogMultipleComponentsConfigured) { - LogComponentSettings settings; - - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); - settings.setMinimumLoggedSeverity(componentB, LogSeverity::Log()); - - // Components for log message: componentA only. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); - - // Components for log message: componentB only. - ASSERT_TRUE(settings.shouldLog(componentB, LogSeverity::Log())); - ASSERT_FALSE(settings.shouldLog(componentB, LogSeverity::Debug(1))); - - // Components for log message: componentC only. - // Since a component-specific minimum severity is not configured for componentC, - // shouldLog() falls back on LogComponent::kDefault. - ASSERT_TRUE(settings.shouldLog(componentC, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentC, LogSeverity::Debug(2))); - - // Test shouldLog() with global settings. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - - // Components for log message: LogComponent::kDefault only. - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); -} - -// Log component hierarchy. -TEST_F(LogTestUnadornedEncoder, LogComponentHierarchy) { - // Parent component is not meaningful for kDefault and kNumLogComponents. - ASSERT_EQUALS(LogComponent::kNumLogComponents, LogComponent(LogComponent::kDefault).parent()); - ASSERT_EQUALS(LogComponent::kNumLogComponents, - LogComponent(LogComponent::kNumLogComponents).parent()); - - // Default -> ComponentD -> ComponentE - ASSERT_EQUALS(LogComponent::kDefault, LogComponent(componentD).parent()); - ASSERT_EQUALS(componentD, LogComponent(componentE).parent()); - ASSERT_NOT_EQUALS(LogComponent::kDefault, LogComponent(componentE).parent()); - - // Log components should inherit parent's log severity in settings. - LogComponentSettings settings; - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentD, LogSeverity::Debug(2)); - - // componentE should inherit componentD's log severity. - ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(3))); - - // Clearing parent's log severity - componentE should inherit from Default. - settings.clearMinimumLoggedSeverity(componentD); - ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(2))); -} - -// Dotted name of component includes names of ancestors. -TEST_F(LogTestUnadornedEncoder, LogComponentDottedName) { - // Default -> ComponentD -> ComponentE - ASSERT_EQUALS(componentDefault.getShortName(), - LogComponent(LogComponent::kDefault).getDottedName()); - ASSERT_EQUALS(componentD.getShortName(), componentD.getDottedName()); - ASSERT_EQUALS(componentD.getShortName() + "." + componentE.getShortName(), - componentE.getDottedName()); -} - -// Log names of all components should have the same length. -TEST_F(LogTestUnadornedEncoder, LogComponentNameForLog) { - size_t defaultNameForLogLength = componentDefault.getNameForLog().toString().length(); - ASSERT_NOT_EQUALS(0U, defaultNameForLogLength); - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - ASSERT_EQUALS(defaultNameForLogLength, component.getNameForLog().toString().length()); - } -} - -/** - * Verifies that the encoded log line contains string. - */ -void testEncodedLogLine(const MessageEventEphemeral& event, const std::string& expectedSubstring) { - MessageEventDetailsEncoder encoder; - std::ostringstream os; - ASSERT_TRUE(encoder.encode(event, os)); - std::string s = os.str(); - if (s.find(expectedSubstring) == std::string::npos) { - FAIL(str::stream() << "encoded log line does not contain substring \"" << expectedSubstring - << "\". log line: " << s); - } -} - -// Log severity should always be logged as a single capital letter. -TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogSeverity) { - Date_t d = Date_t::now(); - const auto ctx = "WHAT"_sd; - const auto msg = "HUH"_sd; - // Severe is indicated by (F)atal. - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Severe(), ctx, msg), " F "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Error(), ctx, msg), " E "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Warning(), ctx, msg), " W "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Info(), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Log(), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(0), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(1), ctx, msg), " D1 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(2), ctx, msg), " D2 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(3), ctx, msg), " D3 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(4), ctx, msg), " D4 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(5), ctx, msg), " D5 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(100), ctx, msg), " D5 "); - // Unknown severity. - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Severe().moreSevere(), ctx, msg), - " U "); -} - -// Non-default log component short name should always be logged. -TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogComponent) { - Date_t d = Date_t::now(); - const auto ctx = "WHAT"_sd; - const auto msg = "HUH"_sd; - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Info(), component, ctx, msg), - str::stream() << " I " << component.getNameForLog() << " ["); - } -} - -// Tests pass through of log component: -// log macros -> LogStreamBuilder -> MessageEventEphemeral -> MessageEventDetailsEncoder -TEST_F(LogTestDetailsEncoder, ) { - setMinimumLoggedSeverity(LogSeverity::Log()); - - // Default log component short name should not appear in detailed log line. - MONGO_LOG_COMPONENT(0, componentDefault) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(componentDefault.getNameForLog().toString()), - std::string::npos); - - // Non-default log component short name should appear in detailed log line. - _logLines.clear(); - MONGO_LOG_COMPONENT(0, componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(componentA.getNameForLog().toString()), std::string::npos); -} - -// Tests pass through of log component: -// unconditional log functions -> LogStreamBuilder -> MessageEventEphemeral -// -> MessageEventDetailsEncoder -TEST_F(LogTestDetailsEncoder, LogFunctions) { - // severe() - no component specified. - severe() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " F " << componentDefault.getNameForLog()), - std::string::npos); - - // severe() - with component. - _logLines.clear(); - severe(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " F " << componentA.getNameForLog()), - std::string::npos); - - // error() - no component specified. - _logLines.clear(); - error() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " E " << componentDefault.getNameForLog()), - std::string::npos); - - // error() - with component. - _logLines.clear(); - error(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " E " << componentA.getNameForLog()), - std::string::npos); - - // warning() - no component specified. - _logLines.clear(); - warning() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " W " << componentDefault.getNameForLog()), - std::string::npos); - - // warning() - with component. - _logLines.clear(); - warning(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " W " << componentA.getNameForLog()), - std::string::npos); - - // log() - no component specified. - _logLines.clear(); - log() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " I " << componentDefault.getNameForLog()), - std::string::npos); - - // log() - with component. - _logLines.clear(); - log(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " I " << componentA.getNameForLog()), - std::string::npos); -} - -} // namespace -} // namespace mongo |