summaryrefslogtreecommitdiff
path: root/absl/log/log_basic_test_impl.inc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/log/log_basic_test_impl.inc')
-rw-r--r--absl/log/log_basic_test_impl.inc455
1 files changed, 455 insertions, 0 deletions
diff --git a/absl/log/log_basic_test_impl.inc b/absl/log/log_basic_test_impl.inc
new file mode 100644
index 00000000..f3400095
--- /dev/null
+++ b/absl/log/log_basic_test_impl.inc
@@ -0,0 +1,455 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The testcases in this file are expected to pass or be skipped with any value
+// of ABSL_MIN_LOG_LEVEL
+
+#ifndef ABSL_LOG_LOG_BASIC_TEST_IMPL_H_
+#define ABSL_LOG_LOG_BASIC_TEST_IMPL_H_
+
+// Verify that both sets of macros behave identically by parameterizing the
+// entire test file.
+#ifndef ABSL_TEST_LOG
+#error ABSL_TEST_LOG must be defined for these tests to work.
+#endif
+
+#include <cerrno>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_actions.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/scoped_mock_log.h"
+
+namespace absl_log_internal {
+#if GTEST_HAS_DEATH_TEST
+using ::absl::log_internal::DeathTestExpectedLogging;
+using ::absl::log_internal::DeathTestUnexpectedLogging;
+using ::absl::log_internal::DeathTestValidateExpectations;
+using ::absl::log_internal::DiedOfFatal;
+using ::absl::log_internal::DiedOfQFatal;
+#endif
+using ::absl::log_internal::LoggingEnabledAt;
+using ::absl::log_internal::LogSeverity;
+using ::absl::log_internal::Prefix;
+using ::absl::log_internal::SourceBasename;
+using ::absl::log_internal::SourceFilename;
+using ::absl::log_internal::SourceLine;
+using ::absl::log_internal::Stacktrace;
+using ::absl::log_internal::TextMessage;
+using ::absl::log_internal::ThreadID;
+using ::absl::log_internal::TimestampInMatchWindow;
+using ::absl::log_internal::Verbosity;
+using ::testing::AnyNumber;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::IsTrue;
+
+class BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {};
+
+std::string ThresholdName(
+ testing::TestParamInfo<absl::LogSeverityAtLeast> severity) {
+ std::stringstream ostr;
+ ostr << severity.param;
+ return ostr.str().substr(
+ severity.param == absl::LogSeverityAtLeast::kInfinity ? 0 : 2);
+}
+
+INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogTest,
+ testing::Values(absl::LogSeverityAtLeast::kInfo,
+ absl::LogSeverityAtLeast::kWarning,
+ absl::LogSeverityAtLeast::kError,
+ absl::LogSeverityAtLeast::kFatal,
+ absl::LogSeverityAtLeast::kInfinity),
+ ThresholdName);
+
+TEST_P(BasicLogTest, Info) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [] { ABSL_TEST_LOG(INFO) << "hello world"; };
+
+ if (LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kInfo)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(R"pb(value {
+ literal: "hello world"
+ })pb")),
+ Stacktrace(IsEmpty()))));
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+}
+
+TEST_P(BasicLogTest, Warning) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [] { ABSL_TEST_LOG(WARNING) << "hello world"; };
+
+ if (LoggingEnabledAt(absl::LogSeverity::kWarning)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kWarning)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(R"pb(value {
+ literal: "hello world"
+ })pb")),
+ Stacktrace(IsEmpty()))));
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+}
+
+TEST_P(BasicLogTest, Error) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [] { ABSL_TEST_LOG(ERROR) << "hello world"; };
+
+ if (LoggingEnabledAt(absl::LogSeverity::kError)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kError)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(R"pb(value {
+ literal: "hello world"
+ })pb")),
+ Stacktrace(IsEmpty()))));
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+}
+
+#if GTEST_HAS_DEATH_TEST
+using BasicLogDeathTest = BasicLogTest;
+
+INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest,
+ testing::Values(absl::LogSeverityAtLeast::kInfo,
+ absl::LogSeverityAtLeast::kFatal,
+ absl::LogSeverityAtLeast::kInfinity),
+ ThresholdName);
+
+TEST_P(BasicLogDeathTest, Fatal) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [] { ABSL_TEST_LOG(FATAL) << "hello world"; };
+
+ EXPECT_EXIT(
+ {
+ absl::ScopedMockLog test_sink(
+ absl::MockLogDefault::kDisallowUnexpected);
+
+ EXPECT_CALL(test_sink, Send)
+ .Times(AnyNumber())
+ .WillRepeatedly(DeathTestUnexpectedLogging());
+
+ ::testing::InSequence s;
+
+ // Note the logic in DeathTestValidateExpectations() caters for the case
+ // of logging being disabled at FATAL level.
+
+ if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+ // The first call without the stack trace.
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kFatal)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(
+ R"pb(value { literal: "hello world" })pb")),
+ Stacktrace(IsEmpty()))))
+ .WillOnce(DeathTestExpectedLogging());
+
+ // The second call with the stack trace.
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kFatal)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(
+ R"pb(value { literal: "hello world" })pb")),
+ Stacktrace(Not(IsEmpty())))))
+ .WillOnce(DeathTestExpectedLogging());
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+ },
+ DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_P(BasicLogDeathTest, QFatal) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [] { ABSL_TEST_LOG(QFATAL) << "hello world"; };
+
+ EXPECT_EXIT(
+ {
+ absl::ScopedMockLog test_sink(
+ absl::MockLogDefault::kDisallowUnexpected);
+
+ EXPECT_CALL(test_sink, Send)
+ .Times(AnyNumber())
+ .WillRepeatedly(DeathTestUnexpectedLogging());
+
+ if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kFatal)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(
+ R"pb(value { literal: "hello world" })pb")),
+ Stacktrace(IsEmpty()))))
+ .WillOnce(DeathTestExpectedLogging());
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+ },
+ DiedOfQFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST_P(BasicLogTest, Level) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ for (auto severity : {absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,
+ absl::LogSeverity::kError}) {
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ const int log_line = __LINE__ + 2;
+ auto do_log = [severity] {
+ ABSL_TEST_LOG(LEVEL(severity)) << "hello world";
+ };
+
+ if (LoggingEnabledAt(severity)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(severity)), TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(R"pb(value {
+ literal: "hello world"
+ })pb")),
+ Stacktrace(IsEmpty()))));
+ }
+ test_sink.StartCapturingLogs();
+ do_log();
+ }
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST_P(BasicLogDeathTest, Level) {
+ // TODO(b/242568884): re-enable once bug is fixed.
+ // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ // Ensure that `severity` is not a compile-time constant to prove that
+ // `LOG(LEVEL(severity))` works regardless:
+ auto volatile severity = absl::LogSeverity::kFatal;
+
+ const int log_line = __LINE__ + 1;
+ auto do_log = [severity] { ABSL_TEST_LOG(LEVEL(severity)) << "hello world"; };
+
+ EXPECT_EXIT(
+ {
+ absl::ScopedMockLog test_sink(
+ absl::MockLogDefault::kDisallowUnexpected);
+
+ EXPECT_CALL(test_sink, Send)
+ .Times(AnyNumber())
+ .WillRepeatedly(DeathTestUnexpectedLogging());
+
+ ::testing::InSequence s;
+
+ if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kFatal)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(
+ R"pb(value { literal: "hello world" })pb")),
+ Stacktrace(IsEmpty()))))
+ .WillOnce(DeathTestExpectedLogging());
+
+ EXPECT_CALL(
+ test_sink,
+ Send(AllOf(SourceFilename(Eq(__FILE__)),
+ SourceBasename(Eq("log_basic_test_impl.inc")),
+ SourceLine(Eq(log_line)), Prefix(IsTrue()),
+ LogSeverity(Eq(absl::LogSeverity::kFatal)),
+ TimestampInMatchWindow(),
+ ThreadID(Eq(absl::base_internal::GetTID())),
+ TextMessage(Eq("hello world")),
+ Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+ ENCODED_MESSAGE(EqualsProto(
+ R"pb(value { literal: "hello world" })pb")),
+ Stacktrace(Not(IsEmpty())))))
+ .WillOnce(DeathTestExpectedLogging());
+ }
+
+ test_sink.StartCapturingLogs();
+ do_log();
+ },
+ DiedOfFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST_P(BasicLogTest, LevelClampsNegativeValues) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+ GTEST_SKIP() << "This test cases required INFO log to be enabled";
+ return;
+ }
+
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kInfo))));
+
+ test_sink.StartCapturingLogs();
+ ABSL_TEST_LOG(LEVEL(-1)) << "hello world";
+}
+
+TEST_P(BasicLogTest, LevelClampsLargeValues) {
+ absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+ if (!LoggingEnabledAt(absl::LogSeverity::kError)) {
+ GTEST_SKIP() << "This test cases required ERROR log to be enabled";
+ return;
+ }
+
+ absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+ EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kError))));
+
+ test_sink.StartCapturingLogs();
+ ABSL_TEST_LOG(LEVEL(static_cast<int>(absl::LogSeverity::kFatal) + 1))
+ << "hello world";
+}
+
+TEST(ErrnoPreservationTest, InSeverityExpression) {
+ errno = 77;
+ int saved_errno;
+ ABSL_TEST_LOG(LEVEL((saved_errno = errno, absl::LogSeverity::kInfo)));
+ EXPECT_THAT(saved_errno, Eq(77));
+}
+
+TEST(ErrnoPreservationTest, InStreamedExpression) {
+ if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+ GTEST_SKIP() << "This test cases required INFO log to be enabled";
+ return;
+ }
+
+ errno = 77;
+ int saved_errno = 0;
+ ABSL_TEST_LOG(INFO) << (saved_errno = errno, "hello world");
+ EXPECT_THAT(saved_errno, Eq(77));
+}
+
+TEST(ErrnoPreservationTest, AfterStatement) {
+ errno = 77;
+ ABSL_TEST_LOG(INFO);
+ const int saved_errno = errno;
+ EXPECT_THAT(saved_errno, Eq(77));
+}
+
+// Tests that using a variable/parameter in a logging statement suppresses
+// unused-variable/parameter warnings.
+// -----------------------------------------------------------------------
+class UnusedVariableWarningCompileTest {
+ // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than
+ // `kInfo`.
+ static void LoggedVariable() {
+ const int x = 0;
+ ABSL_TEST_LOG(INFO) << x;
+ }
+ static void LoggedParameter(const int x) { ABSL_TEST_LOG(INFO) << x; }
+ static void SeverityVariable() {
+ const int x = 0;
+ ABSL_TEST_LOG(LEVEL(x)) << "hello world";
+ }
+ static void SeverityParameter(const int x) {
+ ABSL_TEST_LOG(LEVEL(x)) << "hello world";
+ }
+};
+
+} // namespace absl_log_internal
+
+#endif // ABSL_LOG_LOG_BASIC_TEST_IMPL_H_