log_streamer_test.cc (16566B)
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 #include "absl/log/log_streamer.h" 17 18 #include <ios> 19 #include <iostream> 20 #include <utility> 21 22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 24 #include "absl/base/attributes.h" 25 #include "absl/base/internal/sysinfo.h" 26 #include "absl/base/log_severity.h" 27 #include "absl/log/internal/test_actions.h" 28 #include "absl/log/internal/test_helpers.h" 29 #include "absl/log/internal/test_matchers.h" 30 #include "absl/log/log.h" 31 #include "absl/log/scoped_mock_log.h" 32 #include "absl/strings/string_view.h" 33 34 namespace { 35 using ::absl::log_internal::DeathTestExpectedLogging; 36 using ::absl::log_internal::DeathTestUnexpectedLogging; 37 using ::absl::log_internal::DeathTestValidateExpectations; 38 #if GTEST_HAS_DEATH_TEST 39 using ::absl::log_internal::DiedOfFatal; 40 #endif 41 using ::absl::log_internal::InMatchWindow; 42 using ::absl::log_internal::LogSeverity; 43 using ::absl::log_internal::Prefix; 44 using ::absl::log_internal::SourceFilename; 45 using ::absl::log_internal::SourceLine; 46 using ::absl::log_internal::Stacktrace; 47 using ::absl::log_internal::TextMessage; 48 using ::absl::log_internal::ThreadID; 49 using ::absl::log_internal::Timestamp; 50 using ::testing::_; 51 using ::testing::AnyNumber; 52 using ::testing::Eq; 53 using ::testing::HasSubstr; 54 using ::testing::IsEmpty; 55 using ::testing::IsTrue; 56 57 auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment( 58 new absl::log_internal::LogTestEnvironment); 59 60 void WriteToStream(absl::string_view data, std::ostream* os) { 61 *os << "WriteToStream: " << data; 62 } 63 void WriteToStreamRef(absl::string_view data, std::ostream& os) { 64 os << "WriteToStreamRef: " << data; 65 } 66 67 TEST(LogStreamerTest, LogInfoStreamer) { 68 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 69 70 EXPECT_CALL( 71 test_sink, 72 Send( 73 AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 74 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)), 75 Timestamp(InMatchWindow()), 76 ThreadID(Eq(absl::base_internal::GetTID())), 77 TextMessage(Eq("WriteToStream: foo")), 78 ENCODED_MESSAGE(MatchesEvent( 79 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 80 Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()), 81 ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))), 82 Stacktrace(IsEmpty())))); 83 84 test_sink.StartCapturingLogs(); 85 WriteToStream("foo", &absl::LogInfoStreamer("path/file.cc", 1234).stream()); 86 } 87 88 TEST(LogStreamerTest, LogWarningStreamer) { 89 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 90 91 EXPECT_CALL( 92 test_sink, 93 Send(AllOf( 94 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 95 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kWarning)), 96 Timestamp(InMatchWindow()), 97 ThreadID(Eq(absl::base_internal::GetTID())), 98 TextMessage(Eq("WriteToStream: foo")), 99 ENCODED_MESSAGE(MatchesEvent( 100 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 101 Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()), 102 ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))), 103 Stacktrace(IsEmpty())))); 104 105 test_sink.StartCapturingLogs(); 106 WriteToStream("foo", 107 &absl::LogWarningStreamer("path/file.cc", 1234).stream()); 108 } 109 110 TEST(LogStreamerTest, LogErrorStreamer) { 111 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 112 113 EXPECT_CALL( 114 test_sink, 115 Send(AllOf( 116 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 117 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)), 118 Timestamp(InMatchWindow()), 119 ThreadID(Eq(absl::base_internal::GetTID())), 120 TextMessage(Eq("WriteToStream: foo")), 121 ENCODED_MESSAGE(MatchesEvent( 122 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 123 Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()), 124 ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))), 125 Stacktrace(IsEmpty())))); 126 127 test_sink.StartCapturingLogs(); 128 WriteToStream("foo", &absl::LogErrorStreamer("path/file.cc", 1234).stream()); 129 } 130 131 #if GTEST_HAS_DEATH_TEST 132 TEST(LogStreamerDeathTest, LogFatalStreamer) { 133 EXPECT_EXIT( 134 { 135 absl::ScopedMockLog test_sink; 136 137 EXPECT_CALL(test_sink, Send) 138 .Times(AnyNumber()) 139 .WillRepeatedly(DeathTestUnexpectedLogging()); 140 141 EXPECT_CALL( 142 test_sink, 143 Send(AllOf( 144 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 145 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), 146 Timestamp(InMatchWindow()), 147 ThreadID(Eq(absl::base_internal::GetTID())), 148 TextMessage(Eq("WriteToStream: foo")), 149 ENCODED_MESSAGE(MatchesEvent( 150 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 151 Eq(logging::proto::FATAL), 152 Eq(absl::base_internal::GetTID()), 153 ElementsAre(ValueWithStr(Eq("WriteToStream: foo")))))))) 154 .WillOnce(DeathTestExpectedLogging()); 155 156 test_sink.StartCapturingLogs(); 157 WriteToStream("foo", 158 &absl::LogFatalStreamer("path/file.cc", 1234).stream()); 159 }, 160 DiedOfFatal, DeathTestValidateExpectations()); 161 } 162 #endif 163 164 #ifdef NDEBUG 165 TEST(LogStreamerTest, LogDebugFatalStreamer) { 166 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 167 168 EXPECT_CALL( 169 test_sink, 170 Send(AllOf( 171 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 172 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)), 173 Timestamp(InMatchWindow()), 174 ThreadID(Eq(absl::base_internal::GetTID())), 175 TextMessage(Eq("WriteToStream: foo")), 176 ENCODED_MESSAGE(MatchesEvent( 177 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 178 Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()), 179 ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))), 180 Stacktrace(IsEmpty())))); 181 182 test_sink.StartCapturingLogs(); 183 WriteToStream("foo", 184 &absl::LogDebugFatalStreamer("path/file.cc", 1234).stream()); 185 } 186 #elif GTEST_HAS_DEATH_TEST 187 TEST(LogStreamerDeathTest, LogDebugFatalStreamer) { 188 EXPECT_EXIT( 189 { 190 absl::ScopedMockLog test_sink; 191 192 EXPECT_CALL(test_sink, Send) 193 .Times(AnyNumber()) 194 .WillRepeatedly(DeathTestUnexpectedLogging()); 195 196 EXPECT_CALL( 197 test_sink, 198 Send(AllOf( 199 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 200 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), 201 Timestamp(InMatchWindow()), 202 ThreadID(Eq(absl::base_internal::GetTID())), 203 TextMessage(Eq("WriteToStream: foo")), 204 ENCODED_MESSAGE(MatchesEvent( 205 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 206 Eq(logging::proto::FATAL), 207 Eq(absl::base_internal::GetTID()), 208 ElementsAre(ValueWithStr(Eq("WriteToStream: foo")))))))) 209 .WillOnce(DeathTestExpectedLogging()); 210 211 test_sink.StartCapturingLogs(); 212 WriteToStream( 213 "foo", &absl::LogDebugFatalStreamer("path/file.cc", 1234).stream()); 214 }, 215 DiedOfFatal, DeathTestValidateExpectations()); 216 } 217 #endif 218 219 TEST(LogStreamerTest, LogStreamer) { 220 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 221 222 EXPECT_CALL( 223 test_sink, 224 Send(AllOf( 225 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 226 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)), 227 Timestamp(InMatchWindow()), 228 ThreadID(Eq(absl::base_internal::GetTID())), 229 TextMessage(Eq("WriteToStream: foo")), 230 ENCODED_MESSAGE(MatchesEvent( 231 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 232 Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()), 233 ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))), 234 Stacktrace(IsEmpty())))); 235 236 test_sink.StartCapturingLogs(); 237 WriteToStream( 238 "foo", &absl::LogStreamer(absl::LogSeverity::kError, "path/file.cc", 1234) 239 .stream()); 240 } 241 242 #if GTEST_HAS_DEATH_TEST 243 TEST(LogStreamerDeathTest, LogStreamer) { 244 EXPECT_EXIT( 245 { 246 absl::ScopedMockLog test_sink; 247 248 EXPECT_CALL(test_sink, Send) 249 .Times(AnyNumber()) 250 .WillRepeatedly(DeathTestUnexpectedLogging()); 251 252 EXPECT_CALL( 253 test_sink, 254 Send(AllOf( 255 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 256 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), 257 Timestamp(InMatchWindow()), 258 ThreadID(Eq(absl::base_internal::GetTID())), 259 TextMessage(Eq("WriteToStream: foo")), 260 ENCODED_MESSAGE(MatchesEvent( 261 Eq("path/file.cc"), Eq(1234), InMatchWindow(), 262 Eq(logging::proto::FATAL), 263 Eq(absl::base_internal::GetTID()), 264 ElementsAre(ValueWithStr(Eq("WriteToStream: foo")))))))) 265 .WillOnce(DeathTestExpectedLogging()); 266 267 test_sink.StartCapturingLogs(); 268 WriteToStream("foo", &absl::LogStreamer(absl::LogSeverity::kFatal, 269 "path/file.cc", 1234) 270 .stream()); 271 }, 272 DiedOfFatal, DeathTestValidateExpectations()); 273 } 274 #endif 275 276 TEST(LogStreamerTest, PassedByReference) { 277 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 278 279 EXPECT_CALL( 280 test_sink, 281 Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 282 TextMessage(Eq("WriteToStreamRef: foo")), 283 ENCODED_MESSAGE(MatchesEvent( 284 Eq("path/file.cc"), Eq(1234), _, _, _, 285 ElementsAre(ValueWithStr(Eq("WriteToStreamRef: foo"))))), 286 Stacktrace(IsEmpty())))); 287 288 test_sink.StartCapturingLogs(); 289 WriteToStreamRef("foo", absl::LogInfoStreamer("path/file.cc", 1234).stream()); 290 } 291 292 TEST(LogStreamerTest, StoredAsLocal) { 293 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 294 295 auto streamer = absl::LogInfoStreamer("path/file.cc", 1234); 296 WriteToStream("foo", &streamer.stream()); 297 streamer.stream() << " "; 298 WriteToStreamRef("bar", streamer.stream()); 299 300 // The call should happen when `streamer` goes out of scope; if it 301 // happened before this `EXPECT_CALL` the call would be unexpected and the 302 // test would fail. 303 EXPECT_CALL( 304 test_sink, 305 Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 306 TextMessage(Eq("WriteToStream: foo WriteToStreamRef: bar")), 307 ENCODED_MESSAGE(MatchesEvent( 308 Eq("path/file.cc"), Eq(1234), _, _, _, 309 ElementsAre(ValueWithStr( 310 Eq("WriteToStream: foo WriteToStreamRef: bar"))))), 311 Stacktrace(IsEmpty())))); 312 313 test_sink.StartCapturingLogs(); 314 } 315 316 #if GTEST_HAS_DEATH_TEST 317 TEST(LogStreamerDeathTest, StoredAsLocal) { 318 EXPECT_EXIT( 319 { 320 // This is fatal when it goes out of scope, but not until then: 321 auto streamer = absl::LogFatalStreamer("path/file.cc", 1234); 322 std::cerr << "I'm still alive" << std::endl; 323 WriteToStream("foo", &streamer.stream()); 324 }, 325 DiedOfFatal, HasSubstr("I'm still alive")); 326 } 327 #endif 328 329 TEST(LogStreamerTest, LogsEmptyLine) { 330 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 331 332 EXPECT_CALL(test_sink, Send(AllOf(SourceFilename(Eq("path/file.cc")), 333 SourceLine(Eq(1234)), TextMessage(Eq("")), 334 ENCODED_MESSAGE(MatchesEvent( 335 Eq("path/file.cc"), Eq(1234), _, _, _, 336 ElementsAre(ValueWithStr(Eq(""))))), 337 Stacktrace(IsEmpty())))); 338 339 test_sink.StartCapturingLogs(); 340 absl::LogInfoStreamer("path/file.cc", 1234); 341 } 342 343 #if GTEST_HAS_DEATH_TEST 344 TEST(LogStreamerDeathTest, LogsEmptyLine) { 345 EXPECT_EXIT( 346 { 347 absl::ScopedMockLog test_sink; 348 349 EXPECT_CALL(test_sink, Log) 350 .Times(AnyNumber()) 351 .WillRepeatedly(DeathTestUnexpectedLogging()); 352 353 EXPECT_CALL( 354 test_sink, 355 Send(AllOf(SourceFilename(Eq("path/file.cc")), TextMessage(Eq("")), 356 ENCODED_MESSAGE( 357 MatchesEvent(Eq("path/file.cc"), _, _, _, _, 358 ElementsAre(ValueWithStr(Eq("")))))))) 359 .WillOnce(DeathTestExpectedLogging()); 360 361 test_sink.StartCapturingLogs(); 362 // This is fatal even though it's never used: 363 auto streamer = absl::LogFatalStreamer("path/file.cc", 1234); 364 }, 365 DiedOfFatal, DeathTestValidateExpectations()); 366 } 367 #endif 368 369 TEST(LogStreamerTest, MoveConstruction) { 370 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 371 372 EXPECT_CALL( 373 test_sink, 374 Send( 375 AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 376 LogSeverity(Eq(absl::LogSeverity::kInfo)), 377 TextMessage(Eq("hello 0x10 world 0x10")), 378 ENCODED_MESSAGE(MatchesEvent( 379 Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO), 380 _, ElementsAre(ValueWithStr(Eq("hello 0x10 world 0x10"))))), 381 Stacktrace(IsEmpty())))); 382 383 test_sink.StartCapturingLogs(); 384 auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234); 385 streamer1.stream() << "hello " << std::hex << 16; 386 absl::LogStreamer streamer2(std::move(streamer1)); 387 streamer2.stream() << " world " << 16; 388 } 389 390 TEST(LogStreamerTest, MoveAssignment) { 391 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 392 393 testing::InSequence seq; 394 EXPECT_CALL( 395 test_sink, 396 Send(AllOf( 397 SourceFilename(Eq("path/file2.cc")), SourceLine(Eq(5678)), 398 LogSeverity(Eq(absl::LogSeverity::kWarning)), 399 TextMessage(Eq("something else")), 400 ENCODED_MESSAGE(MatchesEvent( 401 Eq("path/file2.cc"), Eq(5678), _, Eq(logging::proto::WARNING), _, 402 ElementsAre(ValueWithStr(Eq("something else"))))), 403 Stacktrace(IsEmpty())))); 404 EXPECT_CALL( 405 test_sink, 406 Send( 407 AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)), 408 LogSeverity(Eq(absl::LogSeverity::kInfo)), 409 TextMessage(Eq("hello 0x10 world 0x10")), 410 ENCODED_MESSAGE(MatchesEvent( 411 Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO), 412 _, ElementsAre(ValueWithStr(Eq("hello 0x10 world 0x10"))))), 413 Stacktrace(IsEmpty())))); 414 415 test_sink.StartCapturingLogs(); 416 auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234); 417 streamer1.stream() << "hello " << std::hex << 16; 418 auto streamer2 = absl::LogWarningStreamer("path/file2.cc", 5678); 419 streamer2.stream() << "something else"; 420 streamer2 = std::move(streamer1); 421 streamer2.stream() << " world " << 16; 422 } 423 424 TEST(LogStreamerTest, CorrectDefaultFlags) { 425 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 426 427 // The `boolalpha` and `showbase` flags should be set by default, to match 428 // `LOG`. 429 EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("false0xdeadbeef"))))) 430 .Times(2); 431 432 test_sink.StartCapturingLogs(); 433 absl::LogInfoStreamer("path/file.cc", 1234).stream() 434 << false << std::hex << 0xdeadbeef; 435 LOG(INFO) << false << std::hex << 0xdeadbeef; 436 } 437 438 } // namespace