456 lines
17 KiB
C++
456 lines
17 KiB
C++
//
|
|
// 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_
|