1// 2// Copyright 2022 The Abseil Authors. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// https://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16// The testcases in this file are expected to pass or be skipped with any value 17// of ABSL_MIN_LOG_LEVEL 18 19#ifndef ABSL_LOG_LOG_BASIC_TEST_IMPL_H_ 20#define ABSL_LOG_LOG_BASIC_TEST_IMPL_H_ 21 22// Verify that both sets of macros behave identically by parameterizing the 23// entire test file. 24#ifndef ABSL_TEST_LOG 25#error ABSL_TEST_LOG must be defined for these tests to work. 26#endif 27 28#include <cerrno> 29#include <sstream> 30#include <string> 31 32#include "gmock/gmock.h" 33#include "gtest/gtest.h" 34#include "absl/base/internal/sysinfo.h" 35#include "absl/base/log_severity.h" 36#include "absl/log/globals.h" 37#include "absl/log/internal/test_actions.h" 38#include "absl/log/internal/test_helpers.h" 39#include "absl/log/internal/test_matchers.h" 40#include "absl/log/log_entry.h" 41#include "absl/log/scoped_mock_log.h" 42 43namespace absl_log_internal { 44#if GTEST_HAS_DEATH_TEST 45using ::absl::log_internal::DeathTestExpectedLogging; 46using ::absl::log_internal::DeathTestUnexpectedLogging; 47using ::absl::log_internal::DeathTestValidateExpectations; 48using ::absl::log_internal::DiedOfFatal; 49using ::absl::log_internal::DiedOfQFatal; 50#endif 51using ::absl::log_internal::LoggingEnabledAt; 52using ::absl::log_internal::LogSeverity; 53using ::absl::log_internal::Prefix; 54using ::absl::log_internal::SourceBasename; 55using ::absl::log_internal::SourceFilename; 56using ::absl::log_internal::SourceLine; 57using ::absl::log_internal::Stacktrace; 58using ::absl::log_internal::TextMessage; 59using ::absl::log_internal::ThreadID; 60using ::absl::log_internal::TimestampInMatchWindow; 61using ::absl::log_internal::Verbosity; 62using ::testing::AnyNumber; 63using ::testing::Eq; 64using ::testing::IsEmpty; 65using ::testing::IsTrue; 66 67class BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {}; 68 69std::string ThresholdName( 70 testing::TestParamInfo<absl::LogSeverityAtLeast> severity) { 71 std::stringstream ostr; 72 ostr << severity.param; 73 return ostr.str().substr( 74 severity.param == absl::LogSeverityAtLeast::kInfinity ? 0 : 2); 75} 76 77INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogTest, 78 testing::Values(absl::LogSeverityAtLeast::kInfo, 79 absl::LogSeverityAtLeast::kWarning, 80 absl::LogSeverityAtLeast::kError, 81 absl::LogSeverityAtLeast::kFatal, 82 absl::LogSeverityAtLeast::kInfinity), 83 ThresholdName); 84 85TEST_P(BasicLogTest, Info) { 86 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 87 88 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 89 90 const int log_line = __LINE__ + 1; 91 auto do_log = [] { ABSL_TEST_LOG(INFO) << "hello world"; }; 92 93 if (LoggingEnabledAt(absl::LogSeverity::kInfo)) { 94 EXPECT_CALL( 95 test_sink, 96 Send(AllOf(SourceFilename(Eq(__FILE__)), 97 SourceBasename(Eq("log_basic_test_impl.inc")), 98 SourceLine(Eq(log_line)), Prefix(IsTrue()), 99 LogSeverity(Eq(absl::LogSeverity::kInfo)), 100 TimestampInMatchWindow(), 101 ThreadID(Eq(absl::base_internal::GetTID())), 102 TextMessage(Eq("hello world")), 103 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 104 ENCODED_MESSAGE(EqualsProto(R"pb(value { 105 literal: "hello world" 106 })pb")), 107 Stacktrace(IsEmpty())))); 108 } 109 110 test_sink.StartCapturingLogs(); 111 do_log(); 112} 113 114TEST_P(BasicLogTest, Warning) { 115 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 116 117 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 118 119 const int log_line = __LINE__ + 1; 120 auto do_log = [] { ABSL_TEST_LOG(WARNING) << "hello world"; }; 121 122 if (LoggingEnabledAt(absl::LogSeverity::kWarning)) { 123 EXPECT_CALL( 124 test_sink, 125 Send(AllOf(SourceFilename(Eq(__FILE__)), 126 SourceBasename(Eq("log_basic_test_impl.inc")), 127 SourceLine(Eq(log_line)), Prefix(IsTrue()), 128 LogSeverity(Eq(absl::LogSeverity::kWarning)), 129 TimestampInMatchWindow(), 130 ThreadID(Eq(absl::base_internal::GetTID())), 131 TextMessage(Eq("hello world")), 132 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 133 ENCODED_MESSAGE(EqualsProto(R"pb(value { 134 literal: "hello world" 135 })pb")), 136 Stacktrace(IsEmpty())))); 137 } 138 139 test_sink.StartCapturingLogs(); 140 do_log(); 141} 142 143TEST_P(BasicLogTest, Error) { 144 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 145 146 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 147 148 const int log_line = __LINE__ + 1; 149 auto do_log = [] { ABSL_TEST_LOG(ERROR) << "hello world"; }; 150 151 if (LoggingEnabledAt(absl::LogSeverity::kError)) { 152 EXPECT_CALL( 153 test_sink, 154 Send(AllOf(SourceFilename(Eq(__FILE__)), 155 SourceBasename(Eq("log_basic_test_impl.inc")), 156 SourceLine(Eq(log_line)), Prefix(IsTrue()), 157 LogSeverity(Eq(absl::LogSeverity::kError)), 158 TimestampInMatchWindow(), 159 ThreadID(Eq(absl::base_internal::GetTID())), 160 TextMessage(Eq("hello world")), 161 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 162 ENCODED_MESSAGE(EqualsProto(R"pb(value { 163 literal: "hello world" 164 })pb")), 165 Stacktrace(IsEmpty())))); 166 } 167 168 test_sink.StartCapturingLogs(); 169 do_log(); 170} 171 172#if GTEST_HAS_DEATH_TEST 173using BasicLogDeathTest = BasicLogTest; 174 175INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest, 176 testing::Values(absl::LogSeverityAtLeast::kInfo, 177 absl::LogSeverityAtLeast::kFatal, 178 absl::LogSeverityAtLeast::kInfinity), 179 ThresholdName); 180 181TEST_P(BasicLogDeathTest, Fatal) { 182 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 183 184 const int log_line = __LINE__ + 1; 185 auto do_log = [] { ABSL_TEST_LOG(FATAL) << "hello world"; }; 186 187 EXPECT_EXIT( 188 { 189 absl::ScopedMockLog test_sink( 190 absl::MockLogDefault::kDisallowUnexpected); 191 192 EXPECT_CALL(test_sink, Send) 193 .Times(AnyNumber()) 194 .WillRepeatedly(DeathTestUnexpectedLogging()); 195 196 ::testing::InSequence s; 197 198 // Note the logic in DeathTestValidateExpectations() caters for the case 199 // of logging being disabled at FATAL level. 200 201 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) { 202 // The first call without the stack trace. 203 EXPECT_CALL( 204 test_sink, 205 Send(AllOf(SourceFilename(Eq(__FILE__)), 206 SourceBasename(Eq("log_basic_test_impl.inc")), 207 SourceLine(Eq(log_line)), Prefix(IsTrue()), 208 LogSeverity(Eq(absl::LogSeverity::kFatal)), 209 TimestampInMatchWindow(), 210 ThreadID(Eq(absl::base_internal::GetTID())), 211 TextMessage(Eq("hello world")), 212 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 213 ENCODED_MESSAGE(EqualsProto( 214 R"pb(value { literal: "hello world" })pb")), 215 Stacktrace(IsEmpty())))) 216 .WillOnce(DeathTestExpectedLogging()); 217 218 // The second call with the stack trace. 219 EXPECT_CALL( 220 test_sink, 221 Send(AllOf(SourceFilename(Eq(__FILE__)), 222 SourceBasename(Eq("log_basic_test_impl.inc")), 223 SourceLine(Eq(log_line)), Prefix(IsTrue()), 224 LogSeverity(Eq(absl::LogSeverity::kFatal)), 225 TimestampInMatchWindow(), 226 ThreadID(Eq(absl::base_internal::GetTID())), 227 TextMessage(Eq("hello world")), 228 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 229 ENCODED_MESSAGE(EqualsProto( 230 R"pb(value { literal: "hello world" })pb")), 231 Stacktrace(Not(IsEmpty()))))) 232 .WillOnce(DeathTestExpectedLogging()); 233 } 234 235 test_sink.StartCapturingLogs(); 236 do_log(); 237 }, 238 DiedOfFatal, DeathTestValidateExpectations()); 239} 240 241TEST_P(BasicLogDeathTest, QFatal) { 242 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 243 244 const int log_line = __LINE__ + 1; 245 auto do_log = [] { ABSL_TEST_LOG(QFATAL) << "hello world"; }; 246 247 EXPECT_EXIT( 248 { 249 absl::ScopedMockLog test_sink( 250 absl::MockLogDefault::kDisallowUnexpected); 251 252 EXPECT_CALL(test_sink, Send) 253 .Times(AnyNumber()) 254 .WillRepeatedly(DeathTestUnexpectedLogging()); 255 256 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) { 257 EXPECT_CALL( 258 test_sink, 259 Send(AllOf(SourceFilename(Eq(__FILE__)), 260 SourceBasename(Eq("log_basic_test_impl.inc")), 261 SourceLine(Eq(log_line)), Prefix(IsTrue()), 262 LogSeverity(Eq(absl::LogSeverity::kFatal)), 263 TimestampInMatchWindow(), 264 ThreadID(Eq(absl::base_internal::GetTID())), 265 TextMessage(Eq("hello world")), 266 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 267 ENCODED_MESSAGE(EqualsProto( 268 R"pb(value { literal: "hello world" })pb")), 269 Stacktrace(IsEmpty())))) 270 .WillOnce(DeathTestExpectedLogging()); 271 } 272 273 test_sink.StartCapturingLogs(); 274 do_log(); 275 }, 276 DiedOfQFatal, DeathTestValidateExpectations()); 277} 278#endif 279 280TEST_P(BasicLogTest, Level) { 281 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 282 283 for (auto severity : {absl::LogSeverity::kInfo, absl::LogSeverity::kWarning, 284 absl::LogSeverity::kError}) { 285 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 286 287 const int log_line = __LINE__ + 2; 288 auto do_log = [severity] { 289 ABSL_TEST_LOG(LEVEL(severity)) << "hello world"; 290 }; 291 292 if (LoggingEnabledAt(severity)) { 293 EXPECT_CALL( 294 test_sink, 295 Send(AllOf(SourceFilename(Eq(__FILE__)), 296 SourceBasename(Eq("log_basic_test_impl.inc")), 297 SourceLine(Eq(log_line)), Prefix(IsTrue()), 298 LogSeverity(Eq(severity)), TimestampInMatchWindow(), 299 ThreadID(Eq(absl::base_internal::GetTID())), 300 TextMessage(Eq("hello world")), 301 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 302 ENCODED_MESSAGE(EqualsProto(R"pb(value { 303 literal: "hello world" 304 })pb")), 305 Stacktrace(IsEmpty())))); 306 } 307 test_sink.StartCapturingLogs(); 308 do_log(); 309 } 310} 311 312#if GTEST_HAS_DEATH_TEST 313TEST_P(BasicLogDeathTest, Level) { 314 // TODO(b/242568884): re-enable once bug is fixed. 315 // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 316 317 // Ensure that `severity` is not a compile-time constant to prove that 318 // `LOG(LEVEL(severity))` works regardless: 319 auto volatile severity = absl::LogSeverity::kFatal; 320 321 const int log_line = __LINE__ + 1; 322 auto do_log = [severity] { ABSL_TEST_LOG(LEVEL(severity)) << "hello world"; }; 323 324 EXPECT_EXIT( 325 { 326 absl::ScopedMockLog test_sink( 327 absl::MockLogDefault::kDisallowUnexpected); 328 329 EXPECT_CALL(test_sink, Send) 330 .Times(AnyNumber()) 331 .WillRepeatedly(DeathTestUnexpectedLogging()); 332 333 ::testing::InSequence s; 334 335 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) { 336 EXPECT_CALL( 337 test_sink, 338 Send(AllOf(SourceFilename(Eq(__FILE__)), 339 SourceBasename(Eq("log_basic_test_impl.inc")), 340 SourceLine(Eq(log_line)), Prefix(IsTrue()), 341 LogSeverity(Eq(absl::LogSeverity::kFatal)), 342 TimestampInMatchWindow(), 343 ThreadID(Eq(absl::base_internal::GetTID())), 344 TextMessage(Eq("hello world")), 345 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 346 ENCODED_MESSAGE(EqualsProto( 347 R"pb(value { literal: "hello world" })pb")), 348 Stacktrace(IsEmpty())))) 349 .WillOnce(DeathTestExpectedLogging()); 350 351 EXPECT_CALL( 352 test_sink, 353 Send(AllOf(SourceFilename(Eq(__FILE__)), 354 SourceBasename(Eq("log_basic_test_impl.inc")), 355 SourceLine(Eq(log_line)), Prefix(IsTrue()), 356 LogSeverity(Eq(absl::LogSeverity::kFatal)), 357 TimestampInMatchWindow(), 358 ThreadID(Eq(absl::base_internal::GetTID())), 359 TextMessage(Eq("hello world")), 360 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), 361 ENCODED_MESSAGE(EqualsProto( 362 R"pb(value { literal: "hello world" })pb")), 363 Stacktrace(Not(IsEmpty()))))) 364 .WillOnce(DeathTestExpectedLogging()); 365 } 366 367 test_sink.StartCapturingLogs(); 368 do_log(); 369 }, 370 DiedOfFatal, DeathTestValidateExpectations()); 371} 372#endif 373 374TEST_P(BasicLogTest, LevelClampsNegativeValues) { 375 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 376 377 if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) { 378 GTEST_SKIP() << "This test cases required INFO log to be enabled"; 379 return; 380 } 381 382 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 383 384 EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kInfo)))); 385 386 test_sink.StartCapturingLogs(); 387 ABSL_TEST_LOG(LEVEL(-1)) << "hello world"; 388} 389 390TEST_P(BasicLogTest, LevelClampsLargeValues) { 391 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam()); 392 393 if (!LoggingEnabledAt(absl::LogSeverity::kError)) { 394 GTEST_SKIP() << "This test cases required ERROR log to be enabled"; 395 return; 396 } 397 398 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 399 400 EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kError)))); 401 402 test_sink.StartCapturingLogs(); 403 ABSL_TEST_LOG(LEVEL(static_cast<int>(absl::LogSeverity::kFatal) + 1)) 404 << "hello world"; 405} 406 407TEST(ErrnoPreservationTest, InSeverityExpression) { 408 errno = 77; 409 int saved_errno; 410 ABSL_TEST_LOG(LEVEL((saved_errno = errno, absl::LogSeverity::kInfo))); 411 EXPECT_THAT(saved_errno, Eq(77)); 412} 413 414TEST(ErrnoPreservationTest, InStreamedExpression) { 415 if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) { 416 GTEST_SKIP() << "This test cases required INFO log to be enabled"; 417 return; 418 } 419 420 errno = 77; 421 int saved_errno = 0; 422 ABSL_TEST_LOG(INFO) << (saved_errno = errno, "hello world"); 423 EXPECT_THAT(saved_errno, Eq(77)); 424} 425 426TEST(ErrnoPreservationTest, AfterStatement) { 427 errno = 77; 428 ABSL_TEST_LOG(INFO); 429 const int saved_errno = errno; 430 EXPECT_THAT(saved_errno, Eq(77)); 431} 432 433// Tests that using a variable/parameter in a logging statement suppresses 434// unused-variable/parameter warnings. 435// ----------------------------------------------------------------------- 436class UnusedVariableWarningCompileTest { 437 // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than 438 // `kInfo`. 439 static void LoggedVariable() { 440 const int x = 0; 441 ABSL_TEST_LOG(INFO) << x; 442 } 443 static void LoggedParameter(const int x) { ABSL_TEST_LOG(INFO) << x; } 444 static void SeverityVariable() { 445 const int x = 0; 446 ABSL_TEST_LOG(LEVEL(x)) << "hello world"; 447 } 448 static void SeverityParameter(const int x) { 449 ABSL_TEST_LOG(LEVEL(x)) << "hello world"; 450 } 451}; 452 453} // namespace absl_log_internal 454 455#endif // ABSL_LOG_LOG_BASIC_TEST_IMPL_H_ 456