log_format_test.cc (66885B)
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 <math.h> 17 18 #include <iomanip> 19 #include <ios> 20 #include <limits> 21 #include <ostream> 22 #include <sstream> 23 #include <string> 24 #include <type_traits> 25 26 #ifdef __ANDROID__ 27 #include <android/api-level.h> 28 #endif 29 #include "gmock/gmock.h" 30 #include "gtest/gtest.h" 31 #include "absl/log/check.h" 32 #include "absl/log/internal/test_matchers.h" 33 #include "absl/log/log.h" 34 #include "absl/log/scoped_mock_log.h" 35 #include "absl/strings/match.h" 36 #include "absl/strings/str_cat.h" 37 #include "absl/strings/str_format.h" 38 #include "absl/strings/string_view.h" 39 #include "absl/types/optional.h" 40 41 namespace { 42 using ::absl::log_internal::AsString; 43 using ::absl::log_internal::MatchesOstream; 44 using ::absl::log_internal::RawEncodedMessage; 45 using ::absl::log_internal::TextMessage; 46 using ::absl::log_internal::TextPrefix; 47 using ::testing::AllOf; 48 using ::testing::AnyOf; 49 using ::testing::Each; 50 using ::testing::EndsWith; 51 using ::testing::Eq; 52 using ::testing::Ge; 53 using ::testing::IsEmpty; 54 using ::testing::Le; 55 using ::testing::SizeIs; 56 using ::testing::Types; 57 58 // Some aspects of formatting streamed data (e.g. pointer handling) are 59 // implementation-defined. Others are buggy in supported implementations. 60 // These tests validate that the formatting matches that performed by a 61 // `std::ostream` and also that the result is one of a list of expected formats. 62 63 std::ostringstream ComparisonStream() { 64 std::ostringstream str; 65 str.setf(std::ios_base::showbase | std::ios_base::boolalpha | 66 std::ios_base::internal); 67 return str; 68 } 69 70 TEST(LogFormatTest, NoMessage) { 71 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 72 73 const int log_line = __LINE__ + 1; 74 auto do_log = [] { LOG(INFO); }; 75 76 EXPECT_CALL(test_sink, 77 Send(AllOf(TextMessage(MatchesOstream(ComparisonStream())), 78 TextPrefix(AsString(EndsWith(absl::StrCat( 79 " log_format_test.cc:", log_line, "] ")))), 80 TextMessage(IsEmpty()), 81 ENCODED_MESSAGE(HasValues(IsEmpty()))))); 82 83 test_sink.StartCapturingLogs(); 84 do_log(); 85 } 86 87 template <typename T> 88 class CharLogFormatTest : public testing::Test {}; 89 using CharTypes = Types<char, signed char, unsigned char>; 90 TYPED_TEST_SUITE(CharLogFormatTest, CharTypes); 91 92 TYPED_TEST(CharLogFormatTest, Printable) { 93 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 94 95 const TypeParam value = 'x'; 96 auto comparison_stream = ComparisonStream(); 97 comparison_stream << value; 98 99 EXPECT_CALL( 100 test_sink, 101 Send(AllOf( 102 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("x")), 103 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("x")))))))); 104 105 test_sink.StartCapturingLogs(); 106 LOG(INFO) << value; 107 } 108 109 TYPED_TEST(CharLogFormatTest, Unprintable) { 110 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 111 112 constexpr auto value = static_cast<TypeParam>(0xeeu); 113 auto comparison_stream = ComparisonStream(); 114 comparison_stream << value; 115 116 EXPECT_CALL( 117 test_sink, 118 Send(AllOf( 119 TextMessage(MatchesOstream(comparison_stream)), 120 TextMessage(Eq("\xee")), 121 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("\xee")))))))); 122 123 test_sink.StartCapturingLogs(); 124 LOG(INFO) << value; 125 } 126 127 template <typename T> 128 class UnsignedIntLogFormatTest : public testing::Test {}; 129 using UnsignedIntTypes = Types<unsigned short, unsigned int, // NOLINT 130 unsigned long, unsigned long long>; // NOLINT 131 TYPED_TEST_SUITE(UnsignedIntLogFormatTest, UnsignedIntTypes); 132 133 TYPED_TEST(UnsignedIntLogFormatTest, Positive) { 134 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 135 136 const TypeParam value = 224; 137 auto comparison_stream = ComparisonStream(); 138 comparison_stream << value; 139 140 EXPECT_CALL( 141 test_sink, 142 Send(AllOf( 143 TextMessage(MatchesOstream(comparison_stream)), 144 TextMessage(Eq("224")), 145 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224")))))))); 146 147 test_sink.StartCapturingLogs(); 148 LOG(INFO) << value; 149 } 150 151 TYPED_TEST(UnsignedIntLogFormatTest, BitfieldPositive) { 152 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 153 154 const struct { 155 TypeParam bits : 6; 156 } value{42}; 157 auto comparison_stream = ComparisonStream(); 158 comparison_stream << value.bits; 159 160 EXPECT_CALL( 161 test_sink, 162 Send(AllOf( 163 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("42")), 164 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("42")))))))); 165 166 test_sink.StartCapturingLogs(); 167 LOG(INFO) << value.bits; 168 } 169 170 template <typename T> 171 class SignedIntLogFormatTest : public testing::Test {}; 172 using SignedIntTypes = 173 Types<signed short, signed int, signed long, signed long long>; // NOLINT 174 TYPED_TEST_SUITE(SignedIntLogFormatTest, SignedIntTypes); 175 176 TYPED_TEST(SignedIntLogFormatTest, Positive) { 177 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 178 179 const TypeParam value = 224; 180 auto comparison_stream = ComparisonStream(); 181 comparison_stream << value; 182 183 EXPECT_CALL( 184 test_sink, 185 Send(AllOf( 186 TextMessage(MatchesOstream(comparison_stream)), 187 TextMessage(Eq("224")), 188 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224")))))))); 189 190 test_sink.StartCapturingLogs(); 191 LOG(INFO) << value; 192 } 193 194 TYPED_TEST(SignedIntLogFormatTest, Negative) { 195 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 196 197 const TypeParam value = -112; 198 auto comparison_stream = ComparisonStream(); 199 comparison_stream << value; 200 201 EXPECT_CALL( 202 test_sink, 203 Send(AllOf( 204 TextMessage(MatchesOstream(comparison_stream)), 205 TextMessage(Eq("-112")), 206 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-112")))))))); 207 208 test_sink.StartCapturingLogs(); 209 LOG(INFO) << value; 210 } 211 212 TYPED_TEST(SignedIntLogFormatTest, BitfieldPositive) { 213 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 214 215 const struct { 216 TypeParam bits : 6; 217 } value{21}; 218 auto comparison_stream = ComparisonStream(); 219 comparison_stream << value.bits; 220 221 EXPECT_CALL( 222 test_sink, 223 Send(AllOf( 224 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("21")), 225 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("21")))))))); 226 227 test_sink.StartCapturingLogs(); 228 LOG(INFO) << value.bits; 229 } 230 231 TYPED_TEST(SignedIntLogFormatTest, BitfieldNegative) { 232 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 233 234 const struct { 235 TypeParam bits : 6; 236 } value{-21}; 237 auto comparison_stream = ComparisonStream(); 238 comparison_stream << value.bits; 239 240 EXPECT_CALL( 241 test_sink, 242 Send(AllOf( 243 TextMessage(MatchesOstream(comparison_stream)), 244 TextMessage(Eq("-21")), 245 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-21")))))))); 246 247 test_sink.StartCapturingLogs(); 248 LOG(INFO) << value.bits; 249 } 250 251 // Ignore these test cases on GCC due to "is too small to hold all values ..." 252 // warning. 253 #if !defined(__GNUC__) || defined(__clang__) 254 // The implementation may choose a signed or unsigned integer type to represent 255 // this enum, so it may be tested by either `UnsignedEnumLogFormatTest` or 256 // `SignedEnumLogFormatTest`. 257 enum MyUnsignedEnum { 258 MyUnsignedEnum_ZERO = 0, 259 MyUnsignedEnum_FORTY_TWO = 42, 260 MyUnsignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224, 261 }; 262 enum MyUnsignedIntEnum : unsigned int { 263 MyUnsignedIntEnum_ZERO = 0, 264 MyUnsignedIntEnum_FORTY_TWO = 42, 265 MyUnsignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224, 266 }; 267 268 template <typename T> 269 class UnsignedEnumLogFormatTest : public testing::Test {}; 270 using UnsignedEnumTypes = std::conditional< 271 std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value, 272 Types<MyUnsignedIntEnum>, Types<MyUnsignedEnum, MyUnsignedIntEnum>>::type; 273 TYPED_TEST_SUITE(UnsignedEnumLogFormatTest, UnsignedEnumTypes); 274 275 TYPED_TEST(UnsignedEnumLogFormatTest, Positive) { 276 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 277 278 const TypeParam value = static_cast<TypeParam>(224); 279 auto comparison_stream = ComparisonStream(); 280 comparison_stream << value; 281 282 EXPECT_CALL( 283 test_sink, 284 Send(AllOf( 285 TextMessage(MatchesOstream(comparison_stream)), 286 TextMessage(Eq("224")), 287 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224")))))))); 288 289 test_sink.StartCapturingLogs(); 290 LOG(INFO) << value; 291 } 292 293 TYPED_TEST(UnsignedEnumLogFormatTest, BitfieldPositive) { 294 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 295 296 const struct { 297 TypeParam bits : 6; 298 } value{static_cast<TypeParam>(42)}; 299 auto comparison_stream = ComparisonStream(); 300 comparison_stream << value.bits; 301 302 EXPECT_CALL( 303 test_sink, 304 Send(AllOf( 305 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("42")), 306 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("42")))))))); 307 308 test_sink.StartCapturingLogs(); 309 LOG(INFO) << value.bits; 310 } 311 312 enum MySignedEnum { 313 MySignedEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112, 314 MySignedEnum_NEGATIVE_TWENTY_ONE = -21, 315 MySignedEnum_ZERO = 0, 316 MySignedEnum_TWENTY_ONE = 21, 317 MySignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224, 318 }; 319 enum MySignedIntEnum : signed int { 320 MySignedIntEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112, 321 MySignedIntEnum_NEGATIVE_TWENTY_ONE = -21, 322 MySignedIntEnum_ZERO = 0, 323 MySignedIntEnum_TWENTY_ONE = 21, 324 MySignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224, 325 }; 326 327 template <typename T> 328 class SignedEnumLogFormatTest : public testing::Test {}; 329 using SignedEnumTypes = std::conditional< 330 std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value, 331 Types<MyUnsignedEnum, MySignedEnum, MySignedIntEnum>, 332 Types<MySignedEnum, MySignedIntEnum>>::type; 333 TYPED_TEST_SUITE(SignedEnumLogFormatTest, SignedEnumTypes); 334 335 TYPED_TEST(SignedEnumLogFormatTest, Positive) { 336 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 337 338 const TypeParam value = static_cast<TypeParam>(224); 339 auto comparison_stream = ComparisonStream(); 340 comparison_stream << value; 341 342 EXPECT_CALL( 343 test_sink, 344 Send(AllOf( 345 TextMessage(MatchesOstream(comparison_stream)), 346 TextMessage(Eq("224")), 347 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224")))))))); 348 349 test_sink.StartCapturingLogs(); 350 LOG(INFO) << value; 351 } 352 353 TYPED_TEST(SignedEnumLogFormatTest, Negative) { 354 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 355 356 const TypeParam value = static_cast<TypeParam>(-112); 357 auto comparison_stream = ComparisonStream(); 358 comparison_stream << value; 359 360 EXPECT_CALL( 361 test_sink, 362 Send(AllOf( 363 TextMessage(MatchesOstream(comparison_stream)), 364 TextMessage(Eq("-112")), 365 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-112")))))))); 366 367 test_sink.StartCapturingLogs(); 368 LOG(INFO) << value; 369 } 370 371 TYPED_TEST(SignedEnumLogFormatTest, BitfieldPositive) { 372 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 373 374 const struct { 375 TypeParam bits : 6; 376 } value{static_cast<TypeParam>(21)}; 377 auto comparison_stream = ComparisonStream(); 378 comparison_stream << value.bits; 379 380 EXPECT_CALL( 381 test_sink, 382 Send(AllOf( 383 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("21")), 384 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("21")))))))); 385 386 test_sink.StartCapturingLogs(); 387 LOG(INFO) << value.bits; 388 } 389 390 TYPED_TEST(SignedEnumLogFormatTest, BitfieldNegative) { 391 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 392 393 const struct { 394 TypeParam bits : 6; 395 } value{static_cast<TypeParam>(-21)}; 396 auto comparison_stream = ComparisonStream(); 397 comparison_stream << value.bits; 398 399 EXPECT_CALL( 400 test_sink, 401 Send(AllOf( 402 TextMessage(MatchesOstream(comparison_stream)), 403 TextMessage(Eq("-21")), 404 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-21")))))))); 405 406 test_sink.StartCapturingLogs(); 407 LOG(INFO) << value.bits; 408 } 409 #endif 410 411 TEST(FloatLogFormatTest, Positive) { 412 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 413 414 const float value = 6.02e23f; 415 auto comparison_stream = ComparisonStream(); 416 comparison_stream << value; 417 418 EXPECT_CALL(test_sink, 419 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 420 TextMessage(Eq("6.02e+23")), 421 ENCODED_MESSAGE(HasValues( 422 ElementsAre(ValueWithStr(Eq("6.02e+23")))))))); 423 424 test_sink.StartCapturingLogs(); 425 LOG(INFO) << value; 426 } 427 428 TEST(FloatLogFormatTest, Negative) { 429 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 430 431 const float value = -6.02e23f; 432 auto comparison_stream = ComparisonStream(); 433 comparison_stream << value; 434 435 EXPECT_CALL(test_sink, 436 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 437 TextMessage(Eq("-6.02e+23")), 438 ENCODED_MESSAGE(HasValues( 439 ElementsAre(ValueWithStr(Eq("-6.02e+23")))))))); 440 441 test_sink.StartCapturingLogs(); 442 LOG(INFO) << value; 443 } 444 445 TEST(FloatLogFormatTest, NegativeExponent) { 446 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 447 448 const float value = 6.02e-23f; 449 auto comparison_stream = ComparisonStream(); 450 comparison_stream << value; 451 452 EXPECT_CALL(test_sink, 453 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 454 TextMessage(Eq("6.02e-23")), 455 ENCODED_MESSAGE(HasValues( 456 ElementsAre(ValueWithStr(Eq("6.02e-23")))))))); 457 458 test_sink.StartCapturingLogs(); 459 LOG(INFO) << value; 460 } 461 462 TEST(DoubleLogFormatTest, Positive) { 463 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 464 465 const double value = 6.02e23; 466 auto comparison_stream = ComparisonStream(); 467 comparison_stream << value; 468 469 EXPECT_CALL(test_sink, 470 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 471 TextMessage(Eq("6.02e+23")), 472 ENCODED_MESSAGE(HasValues( 473 ElementsAre(ValueWithStr(Eq("6.02e+23")))))))); 474 475 test_sink.StartCapturingLogs(); 476 LOG(INFO) << value; 477 } 478 479 TEST(DoubleLogFormatTest, Negative) { 480 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 481 482 const double value = -6.02e23; 483 auto comparison_stream = ComparisonStream(); 484 comparison_stream << value; 485 486 EXPECT_CALL(test_sink, 487 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 488 TextMessage(Eq("-6.02e+23")), 489 ENCODED_MESSAGE(HasValues( 490 ElementsAre(ValueWithStr(Eq("-6.02e+23")))))))); 491 492 test_sink.StartCapturingLogs(); 493 LOG(INFO) << value; 494 } 495 496 TEST(DoubleLogFormatTest, NegativeExponent) { 497 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 498 499 const double value = 6.02e-23; 500 auto comparison_stream = ComparisonStream(); 501 comparison_stream << value; 502 503 EXPECT_CALL(test_sink, 504 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 505 TextMessage(Eq("6.02e-23")), 506 ENCODED_MESSAGE(HasValues( 507 ElementsAre(ValueWithStr(Eq("6.02e-23")))))))); 508 509 test_sink.StartCapturingLogs(); 510 LOG(INFO) << value; 511 } 512 513 template <typename T> 514 class FloatingPointLogFormatTest : public testing::Test {}; 515 using FloatingPointTypes = Types<float, double>; 516 TYPED_TEST_SUITE(FloatingPointLogFormatTest, FloatingPointTypes); 517 518 TYPED_TEST(FloatingPointLogFormatTest, Zero) { 519 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 520 521 const TypeParam value = 0.0; 522 auto comparison_stream = ComparisonStream(); 523 comparison_stream << value; 524 525 EXPECT_CALL( 526 test_sink, 527 Send(AllOf( 528 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("0")), 529 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0")))))))); 530 531 test_sink.StartCapturingLogs(); 532 LOG(INFO) << value; 533 } 534 535 TYPED_TEST(FloatingPointLogFormatTest, Integer) { 536 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 537 538 const TypeParam value = 1.0; 539 auto comparison_stream = ComparisonStream(); 540 comparison_stream << value; 541 542 EXPECT_CALL( 543 test_sink, 544 Send(AllOf( 545 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("1")), 546 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("1")))))))); 547 548 test_sink.StartCapturingLogs(); 549 LOG(INFO) << value; 550 } 551 552 TYPED_TEST(FloatingPointLogFormatTest, Infinity) { 553 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 554 555 const TypeParam value = std::numeric_limits<TypeParam>::infinity(); 556 auto comparison_stream = ComparisonStream(); 557 comparison_stream << value; 558 559 EXPECT_CALL( 560 test_sink, 561 Send(AllOf( 562 TextMessage(MatchesOstream(comparison_stream)), 563 TextMessage(AnyOf(Eq("inf"), Eq("Inf"))), 564 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("inf")))))))); 565 566 test_sink.StartCapturingLogs(); 567 LOG(INFO) << value; 568 } 569 570 TYPED_TEST(FloatingPointLogFormatTest, NegativeInfinity) { 571 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 572 573 const TypeParam value = -std::numeric_limits<TypeParam>::infinity(); 574 auto comparison_stream = ComparisonStream(); 575 comparison_stream << value; 576 577 EXPECT_CALL( 578 test_sink, 579 Send(AllOf( 580 TextMessage(MatchesOstream(comparison_stream)), 581 TextMessage(AnyOf(Eq("-inf"), Eq("-Inf"))), 582 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-inf")))))))); 583 584 test_sink.StartCapturingLogs(); 585 LOG(INFO) << value; 586 } 587 588 TYPED_TEST(FloatingPointLogFormatTest, NaN) { 589 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 590 591 const TypeParam value = std::numeric_limits<TypeParam>::quiet_NaN(); 592 auto comparison_stream = ComparisonStream(); 593 comparison_stream << value; 594 595 EXPECT_CALL( 596 test_sink, 597 Send(AllOf( 598 TextMessage(MatchesOstream(comparison_stream)), 599 TextMessage(AnyOf(Eq("nan"), Eq("NaN"))), 600 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("nan")))))))); 601 test_sink.StartCapturingLogs(); 602 LOG(INFO) << value; 603 } 604 605 TYPED_TEST(FloatingPointLogFormatTest, NegativeNaN) { 606 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 607 608 const TypeParam value = 609 std::copysign(std::numeric_limits<TypeParam>::quiet_NaN(), -1.0); 610 auto comparison_stream = ComparisonStream(); 611 comparison_stream << value; 612 613 // On RISC-V, don't expect that formatting -NaN produces the same string as 614 // streaming it. #ifdefing out just the relevant line breaks the MSVC build, 615 // so duplicate the entire EXPECT_CALL. 616 #ifdef __riscv 617 EXPECT_CALL(test_sink, 618 Send(AllOf(TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), 619 Eq("-nan(ind)"))), 620 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf( 621 ValueWithStr(Eq("-nan")), ValueWithStr(Eq("nan")), 622 ValueWithStr(Eq("-nan(ind)"))))))))); 623 #else 624 EXPECT_CALL(test_sink, 625 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 626 TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), 627 Eq("-nan(ind)"))), 628 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf( 629 ValueWithStr(Eq("-nan")), ValueWithStr(Eq("nan")), 630 ValueWithStr(Eq("-nan(ind)"))))))))); 631 #endif 632 test_sink.StartCapturingLogs(); 633 LOG(INFO) << value; 634 } 635 636 template <typename T> 637 class VoidPtrLogFormatTest : public testing::Test {}; 638 using VoidPtrTypes = Types<void *, const void *>; 639 TYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes); 640 641 TYPED_TEST(VoidPtrLogFormatTest, Null) { 642 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 643 644 const TypeParam value = nullptr; 645 auto comparison_stream = ComparisonStream(); 646 comparison_stream << value; 647 648 EXPECT_CALL( 649 test_sink, 650 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 651 TextMessage(AnyOf(Eq("(nil)"), Eq("0"), Eq("0x0"), 652 Eq("00000000"), Eq("0000000000000000")))))); 653 654 test_sink.StartCapturingLogs(); 655 LOG(INFO) << value; 656 } 657 658 TYPED_TEST(VoidPtrLogFormatTest, NonNull) { 659 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 660 661 const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefULL); 662 auto comparison_stream = ComparisonStream(); 663 comparison_stream << value; 664 665 EXPECT_CALL(test_sink, 666 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 667 TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"), 668 Eq("00000000DEADBEEF"))), 669 ENCODED_MESSAGE(HasValues(ElementsAre( 670 AnyOf(ValueWithStr(Eq("0xdeadbeef")), 671 ValueWithStr(Eq("00000000DEADBEEF"))))))))); 672 673 test_sink.StartCapturingLogs(); 674 LOG(INFO) << value; 675 } 676 677 template <typename T> 678 class VolatilePtrLogFormatTest : public testing::Test {}; 679 using VolatilePtrTypes = 680 Types<volatile void*, const volatile void*, volatile char*, 681 const volatile char*, volatile signed char*, 682 const volatile signed char*, volatile unsigned char*, 683 const volatile unsigned char*>; 684 TYPED_TEST_SUITE(VolatilePtrLogFormatTest, VolatilePtrTypes); 685 686 TYPED_TEST(VolatilePtrLogFormatTest, Null) { 687 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 688 689 const TypeParam value = nullptr; 690 auto comparison_stream = ComparisonStream(); 691 comparison_stream << value; 692 693 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html 694 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L 695 EXPECT_CALL( 696 test_sink, 697 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 698 TextMessage(AnyOf(Eq("(nil)"), Eq("0"), Eq("0x0"), 699 Eq("00000000"), Eq("0000000000000000")))))); 700 #else 701 EXPECT_CALL( 702 test_sink, 703 Send(AllOf( 704 TextMessage(MatchesOstream(comparison_stream)), 705 TextMessage(Eq("false")), 706 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("false")))))))); 707 #endif 708 709 test_sink.StartCapturingLogs(); 710 LOG(INFO) << value; 711 } 712 713 TYPED_TEST(VolatilePtrLogFormatTest, NonNull) { 714 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 715 716 const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefLL); 717 auto comparison_stream = ComparisonStream(); 718 comparison_stream << value; 719 720 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html 721 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L 722 EXPECT_CALL(test_sink, 723 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 724 TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"), 725 Eq("00000000DEADBEEF"))), 726 ENCODED_MESSAGE(HasValues(ElementsAre( 727 AnyOf(ValueWithStr(Eq("0xdeadbeef")), 728 ValueWithStr(Eq("00000000DEADBEEF"))))))))); 729 #else 730 EXPECT_CALL( 731 test_sink, 732 Send(AllOf( 733 TextMessage(MatchesOstream(comparison_stream)), 734 TextMessage(Eq("true")), 735 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("true")))))))); 736 #endif 737 738 test_sink.StartCapturingLogs(); 739 LOG(INFO) << value; 740 } 741 742 template <typename T> 743 class CharPtrLogFormatTest : public testing::Test {}; 744 using CharPtrTypes = Types<char, const char, signed char, const signed char, 745 unsigned char, const unsigned char>; 746 TYPED_TEST_SUITE(CharPtrLogFormatTest, CharPtrTypes); 747 748 TYPED_TEST(CharPtrLogFormatTest, Null) { 749 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 750 751 // Streaming `([cv] char *)nullptr` into a `std::ostream` is UB, and some C++ 752 // standard library implementations choose to crash. We take measures to log 753 // something useful instead of crashing, even when that differs from the 754 // standard library in use (and thus the behavior of `std::ostream`). 755 TypeParam* const value = nullptr; 756 757 EXPECT_CALL( 758 test_sink, 759 Send(AllOf( 760 // `MatchesOstream` deliberately omitted since we deliberately differ. 761 TextMessage(Eq("(null)")), ENCODED_MESSAGE(HasValues(ElementsAre( 762 ValueWithStr(Eq("(null)")))))))); 763 764 test_sink.StartCapturingLogs(); 765 LOG(INFO) << value; 766 } 767 768 TYPED_TEST(CharPtrLogFormatTest, NonNull) { 769 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 770 771 TypeParam data[] = {'v', 'a', 'l', 'u', 'e', '\0'}; 772 TypeParam* const value = data; 773 auto comparison_stream = ComparisonStream(); 774 comparison_stream << value; 775 776 EXPECT_CALL( 777 test_sink, 778 Send(AllOf( 779 TextMessage(MatchesOstream(comparison_stream)), 780 TextMessage(Eq("value")), 781 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("value")))))))); 782 783 test_sink.StartCapturingLogs(); 784 LOG(INFO) << value; 785 } 786 787 TEST(BoolLogFormatTest, True) { 788 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 789 790 const bool value = true; 791 auto comparison_stream = ComparisonStream(); 792 comparison_stream << value; 793 794 EXPECT_CALL( 795 test_sink, 796 Send(AllOf( 797 TextMessage(MatchesOstream(comparison_stream)), 798 TextMessage(Eq("true")), 799 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("true")))))))); 800 801 test_sink.StartCapturingLogs(); 802 LOG(INFO) << value; 803 } 804 805 TEST(BoolLogFormatTest, False) { 806 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 807 808 const bool value = false; 809 auto comparison_stream = ComparisonStream(); 810 comparison_stream << value; 811 812 EXPECT_CALL( 813 test_sink, 814 Send(AllOf( 815 TextMessage(MatchesOstream(comparison_stream)), 816 TextMessage(Eq("false")), 817 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("false")))))))); 818 819 test_sink.StartCapturingLogs(); 820 LOG(INFO) << value; 821 } 822 823 TEST(LogFormatTest, StringLiteral) { 824 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 825 826 auto comparison_stream = ComparisonStream(); 827 comparison_stream << "value"; 828 829 EXPECT_CALL(test_sink, 830 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 831 TextMessage(Eq("value")), 832 ENCODED_MESSAGE(HasValues( 833 ElementsAre(ValueWithLiteral(Eq("value")))))))); 834 835 test_sink.StartCapturingLogs(); 836 LOG(INFO) << "value"; 837 } 838 839 TEST(LogFormatTest, CharArray) { 840 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 841 842 char value[] = "value"; 843 auto comparison_stream = ComparisonStream(); 844 comparison_stream << value; 845 846 EXPECT_CALL( 847 test_sink, 848 Send(AllOf( 849 TextMessage(MatchesOstream(comparison_stream)), 850 TextMessage(Eq("value")), 851 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("value")))))))); 852 853 test_sink.StartCapturingLogs(); 854 LOG(INFO) << value; 855 } 856 857 class CustomClass {}; 858 std::ostream& operator<<(std::ostream& os, const CustomClass&) { 859 return os << "CustomClass{}"; 860 } 861 862 TEST(LogFormatTest, Custom) { 863 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 864 865 CustomClass value; 866 auto comparison_stream = ComparisonStream(); 867 comparison_stream << value; 868 869 EXPECT_CALL(test_sink, 870 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 871 TextMessage(Eq("CustomClass{}")), 872 ENCODED_MESSAGE(HasValues(ElementsAre( 873 ValueWithStr(Eq("CustomClass{}")))))))); 874 test_sink.StartCapturingLogs(); 875 LOG(INFO) << value; 876 } 877 878 class CustomClassNonCopyable { 879 public: 880 CustomClassNonCopyable() = default; 881 CustomClassNonCopyable(const CustomClassNonCopyable&) = delete; 882 CustomClassNonCopyable& operator=(const CustomClassNonCopyable&) = delete; 883 }; 884 std::ostream& operator<<(std::ostream& os, const CustomClassNonCopyable&) { 885 return os << "CustomClassNonCopyable{}"; 886 } 887 888 TEST(LogFormatTest, CustomNonCopyable) { 889 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 890 891 CustomClassNonCopyable value; 892 auto comparison_stream = ComparisonStream(); 893 comparison_stream << value; 894 895 EXPECT_CALL(test_sink, 896 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 897 TextMessage(Eq("CustomClassNonCopyable{}")), 898 ENCODED_MESSAGE(HasValues(ElementsAre( 899 ValueWithStr(Eq("CustomClassNonCopyable{}")))))))); 900 901 test_sink.StartCapturingLogs(); 902 LOG(INFO) << value; 903 } 904 905 struct Point { 906 template <typename Sink> 907 friend void AbslStringify(Sink& sink, const Point& p) { 908 absl::Format(&sink, "(%d, %d)", p.x, p.y); 909 } 910 911 int x = 10; 912 int y = 20; 913 }; 914 915 TEST(LogFormatTest, AbslStringifyExample) { 916 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 917 918 Point p; 919 920 EXPECT_CALL( 921 test_sink, 922 Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))), 923 ENCODED_MESSAGE( 924 HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)")))))))); 925 926 test_sink.StartCapturingLogs(); 927 LOG(INFO) << p; 928 } 929 930 struct PointWithAbslStringifiyAndOstream { 931 template <typename Sink> 932 friend void AbslStringify(Sink& sink, 933 const PointWithAbslStringifiyAndOstream& p) { 934 absl::Format(&sink, "(%d, %d)", p.x, p.y); 935 } 936 937 int x = 10; 938 int y = 20; 939 }; 940 941 ABSL_ATTRIBUTE_UNUSED std::ostream& operator<<( 942 std::ostream& os, const PointWithAbslStringifiyAndOstream&) { 943 return os << "Default to AbslStringify()"; 944 } 945 946 TEST(LogFormatTest, CustomWithAbslStringifyAndOstream) { 947 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 948 949 PointWithAbslStringifiyAndOstream p; 950 951 EXPECT_CALL( 952 test_sink, 953 Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))), 954 ENCODED_MESSAGE( 955 HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)")))))))); 956 957 test_sink.StartCapturingLogs(); 958 LOG(INFO) << p; 959 } 960 961 struct PointStreamsNothing { 962 template <typename Sink> 963 friend void AbslStringify(Sink&, const PointStreamsNothing&) {} 964 965 int x = 10; 966 int y = 20; 967 }; 968 969 TEST(LogFormatTest, AbslStringifyStreamsNothing) { 970 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 971 972 PointStreamsNothing p; 973 974 EXPECT_CALL( 975 test_sink, 976 Send(AllOf( 977 TextMessage(Eq("77")), TextMessage(Eq(absl::StrCat(p, 77))), 978 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77")))))))); 979 980 test_sink.StartCapturingLogs(); 981 LOG(INFO) << p << 77; 982 } 983 984 struct PointMultipleAppend { 985 template <typename Sink> 986 friend void AbslStringify(Sink& sink, const PointMultipleAppend& p) { 987 sink.Append("("); 988 sink.Append(absl::StrCat(p.x, ", ", p.y, ")")); 989 } 990 991 int x = 10; 992 int y = 20; 993 }; 994 995 TEST(LogFormatTest, AbslStringifyMultipleAppend) { 996 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 997 998 PointMultipleAppend p; 999 1000 EXPECT_CALL( 1001 test_sink, 1002 Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))), 1003 ENCODED_MESSAGE(HasValues(ElementsAre( 1004 ValueWithStr(Eq("(")), ValueWithStr(Eq("10, 20)")))))))); 1005 1006 test_sink.StartCapturingLogs(); 1007 LOG(INFO) << p; 1008 } 1009 1010 TEST(ManipulatorLogFormatTest, BoolAlphaTrue) { 1011 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1012 1013 const bool value = true; 1014 auto comparison_stream = ComparisonStream(); 1015 comparison_stream << std::noboolalpha << value << " " // 1016 << std::boolalpha << value << " " // 1017 << std::noboolalpha << value; 1018 1019 EXPECT_CALL( 1020 test_sink, 1021 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1022 TextMessage(Eq("1 true 1")), 1023 ENCODED_MESSAGE(HasValues(ElementsAre( 1024 ValueWithStr(Eq("1")), ValueWithLiteral(Eq(" ")), 1025 ValueWithStr(Eq("true")), ValueWithLiteral(Eq(" ")), 1026 ValueWithStr(Eq("1")))))))); 1027 1028 test_sink.StartCapturingLogs(); 1029 LOG(INFO) << std::noboolalpha << value << " " // 1030 << std::boolalpha << value << " " // 1031 << std::noboolalpha << value; 1032 } 1033 1034 TEST(ManipulatorLogFormatTest, BoolAlphaFalse) { 1035 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1036 1037 const bool value = false; 1038 auto comparison_stream = ComparisonStream(); 1039 comparison_stream << std::noboolalpha << value << " " // 1040 << std::boolalpha << value << " " // 1041 << std::noboolalpha << value; 1042 1043 EXPECT_CALL( 1044 test_sink, 1045 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1046 TextMessage(Eq("0 false 0")), 1047 ENCODED_MESSAGE(HasValues(ElementsAre( 1048 ValueWithStr(Eq("0")), ValueWithLiteral(Eq(" ")), 1049 ValueWithStr(Eq("false")), ValueWithLiteral(Eq(" ")), 1050 ValueWithStr(Eq("0")))))))); 1051 1052 test_sink.StartCapturingLogs(); 1053 LOG(INFO) << std::noboolalpha << value << " " // 1054 << std::boolalpha << value << " " // 1055 << std::noboolalpha << value; 1056 } 1057 1058 TEST(ManipulatorLogFormatTest, ShowPoint) { 1059 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1060 1061 const double value = 77.0; 1062 auto comparison_stream = ComparisonStream(); 1063 comparison_stream << std::noshowpoint << value << " " // 1064 << std::showpoint << value << " " // 1065 << std::noshowpoint << value; 1066 1067 EXPECT_CALL( 1068 test_sink, 1069 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1070 TextMessage(Eq("77 77.0000 77")), 1071 ENCODED_MESSAGE(HasValues(ElementsAre( 1072 ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")), 1073 ValueWithStr(Eq("77.0000")), ValueWithLiteral(Eq(" ")), 1074 ValueWithStr(Eq("77")))))))); 1075 1076 test_sink.StartCapturingLogs(); 1077 LOG(INFO) << std::noshowpoint << value << " " // 1078 << std::showpoint << value << " " // 1079 << std::noshowpoint << value; 1080 } 1081 1082 TEST(ManipulatorLogFormatTest, ShowPos) { 1083 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1084 1085 const int value = 77; 1086 auto comparison_stream = ComparisonStream(); 1087 comparison_stream << std::noshowpos << value << " " // 1088 << std::showpos << value << " " // 1089 << std::noshowpos << value; 1090 1091 EXPECT_CALL(test_sink, 1092 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1093 TextMessage(Eq("77 +77 77")), 1094 ENCODED_MESSAGE(HasValues(ElementsAre( 1095 ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")), 1096 ValueWithStr(Eq("+77")), ValueWithLiteral(Eq(" ")), 1097 ValueWithStr(Eq("77")))))))); 1098 1099 test_sink.StartCapturingLogs(); 1100 LOG(INFO) << std::noshowpos << value << " " // 1101 << std::showpos << value << " " // 1102 << std::noshowpos << value; 1103 } 1104 1105 TEST(ManipulatorLogFormatTest, UppercaseFloat) { 1106 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1107 1108 const double value = 7.7e7; 1109 auto comparison_stream = ComparisonStream(); 1110 comparison_stream << std::nouppercase << value << " " // 1111 << std::uppercase << value << " " // 1112 << std::nouppercase << value; 1113 1114 EXPECT_CALL( 1115 test_sink, 1116 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1117 TextMessage(Eq("7.7e+07 7.7E+07 7.7e+07")), 1118 ENCODED_MESSAGE(HasValues(ElementsAre( 1119 ValueWithStr(Eq("7.7e+07")), ValueWithLiteral(Eq(" ")), 1120 ValueWithStr(Eq("7.7E+07")), ValueWithLiteral(Eq(" ")), 1121 ValueWithStr(Eq("7.7e+07")))))))); 1122 1123 test_sink.StartCapturingLogs(); 1124 LOG(INFO) << std::nouppercase << value << " " // 1125 << std::uppercase << value << " " // 1126 << std::nouppercase << value; 1127 } 1128 1129 TEST(ManipulatorLogFormatTest, Hex) { 1130 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1131 1132 const int value = 0x77; 1133 auto comparison_stream = ComparisonStream(); 1134 comparison_stream << std::hex << value; 1135 1136 EXPECT_CALL( 1137 test_sink, 1138 Send(AllOf( 1139 TextMessage(MatchesOstream(comparison_stream)), 1140 TextMessage(Eq("0x77")), 1141 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0x77")))))))); 1142 test_sink.StartCapturingLogs(); 1143 LOG(INFO) << std::hex << value; 1144 } 1145 1146 TEST(ManipulatorLogFormatTest, Oct) { 1147 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1148 1149 const int value = 077; 1150 auto comparison_stream = ComparisonStream(); 1151 comparison_stream << std::oct << value; 1152 1153 EXPECT_CALL( 1154 test_sink, 1155 Send(AllOf( 1156 TextMessage(MatchesOstream(comparison_stream)), 1157 TextMessage(Eq("077")), 1158 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("077")))))))); 1159 1160 test_sink.StartCapturingLogs(); 1161 LOG(INFO) << std::oct << value; 1162 } 1163 1164 TEST(ManipulatorLogFormatTest, Dec) { 1165 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1166 1167 const int value = 77; 1168 auto comparison_stream = ComparisonStream(); 1169 comparison_stream << std::hex << std::dec << value; 1170 1171 EXPECT_CALL( 1172 test_sink, 1173 Send(AllOf( 1174 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("77")), 1175 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77")))))))); 1176 1177 test_sink.StartCapturingLogs(); 1178 LOG(INFO) << std::hex << std::dec << value; 1179 } 1180 1181 TEST(ManipulatorLogFormatTest, ShowbaseHex) { 1182 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1183 1184 const int value = 0x77; 1185 auto comparison_stream = ComparisonStream(); 1186 comparison_stream << std::hex // 1187 << std::noshowbase << value << " " // 1188 << std::showbase << value << " " // 1189 << std::noshowbase << value; 1190 1191 EXPECT_CALL( 1192 test_sink, 1193 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1194 TextMessage(Eq("77 0x77 77")), 1195 ENCODED_MESSAGE(HasValues(ElementsAre( 1196 ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")), 1197 ValueWithStr(Eq("0x77")), ValueWithLiteral(Eq(" ")), 1198 ValueWithStr(Eq("77")))))))); 1199 1200 test_sink.StartCapturingLogs(); 1201 LOG(INFO) << std::hex // 1202 << std::noshowbase << value << " " // 1203 << std::showbase << value << " " // 1204 << std::noshowbase << value; 1205 } 1206 1207 TEST(ManipulatorLogFormatTest, ShowbaseOct) { 1208 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1209 1210 const int value = 077; 1211 auto comparison_stream = ComparisonStream(); 1212 comparison_stream << std::oct // 1213 << std::noshowbase << value << " " // 1214 << std::showbase << value << " " // 1215 << std::noshowbase << value; 1216 1217 EXPECT_CALL(test_sink, 1218 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1219 TextMessage(Eq("77 077 77")), 1220 ENCODED_MESSAGE(HasValues(ElementsAre( 1221 ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")), 1222 ValueWithStr(Eq("077")), ValueWithLiteral(Eq(" ")), 1223 ValueWithStr(Eq("77")))))))); 1224 1225 test_sink.StartCapturingLogs(); 1226 LOG(INFO) << std::oct // 1227 << std::noshowbase << value << " " // 1228 << std::showbase << value << " " // 1229 << std::noshowbase << value; 1230 } 1231 1232 TEST(ManipulatorLogFormatTest, UppercaseHex) { 1233 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1234 1235 const int value = 0xbeef; 1236 auto comparison_stream = ComparisonStream(); 1237 comparison_stream // 1238 << std::hex // 1239 << std::nouppercase << value << " " // 1240 << std::uppercase << value << " " // 1241 << std::nouppercase << value; 1242 1243 EXPECT_CALL( 1244 test_sink, 1245 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1246 TextMessage(Eq("0xbeef 0XBEEF 0xbeef")), 1247 ENCODED_MESSAGE(HasValues(ElementsAre( 1248 ValueWithStr(Eq("0xbeef")), ValueWithLiteral(Eq(" ")), 1249 ValueWithStr(Eq("0XBEEF")), ValueWithLiteral(Eq(" ")), 1250 ValueWithStr(Eq("0xbeef")))))))); 1251 1252 test_sink.StartCapturingLogs(); 1253 LOG(INFO) << std::hex // 1254 << std::nouppercase << value << " " // 1255 << std::uppercase << value << " " // 1256 << std::nouppercase << value; 1257 } 1258 1259 TEST(ManipulatorLogFormatTest, FixedFloat) { 1260 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1261 1262 const double value = 7.7e7; 1263 auto comparison_stream = ComparisonStream(); 1264 comparison_stream << std::fixed << value; 1265 1266 EXPECT_CALL(test_sink, 1267 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1268 TextMessage(Eq("77000000.000000")), 1269 ENCODED_MESSAGE(HasValues(ElementsAre( 1270 ValueWithStr(Eq("77000000.000000")))))))); 1271 1272 test_sink.StartCapturingLogs(); 1273 LOG(INFO) << std::fixed << value; 1274 } 1275 1276 TEST(ManipulatorLogFormatTest, ScientificFloat) { 1277 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1278 1279 const double value = 7.7e7; 1280 auto comparison_stream = ComparisonStream(); 1281 comparison_stream << std::scientific << value; 1282 1283 EXPECT_CALL(test_sink, 1284 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1285 TextMessage(Eq("7.700000e+07")), 1286 ENCODED_MESSAGE(HasValues( 1287 ElementsAre(ValueWithStr(Eq("7.700000e+07")))))))); 1288 1289 test_sink.StartCapturingLogs(); 1290 LOG(INFO) << std::scientific << value; 1291 } 1292 1293 #if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22) 1294 // Bionic doesn't support `%a` until API 22, so this prints 'a' even if the 1295 // C++ standard library implements it correctly (by forwarding to printf). 1296 #elif defined(__GLIBCXX__) && __cplusplus < 201402L 1297 // libstdc++ shipped C++11 support without `std::hexfloat`. 1298 #else 1299 TEST(ManipulatorLogFormatTest, FixedAndScientificFloat) { 1300 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1301 1302 const double value = 7.7e7; 1303 auto comparison_stream = ComparisonStream(); 1304 comparison_stream << std::setiosflags(std::ios_base::scientific | 1305 std::ios_base::fixed) 1306 << value; 1307 1308 EXPECT_CALL( 1309 test_sink, 1310 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1311 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"), 1312 Eq("0x1.25bb500000000p+26"))), 1313 ENCODED_MESSAGE(HasValues(ElementsAre( 1314 AnyOf(ValueWithStr(Eq("0x1.25bb5p+26")), 1315 ValueWithStr(Eq("0x1.25bb500000000p+26"))))))))); 1316 1317 test_sink.StartCapturingLogs(); 1318 1319 // This combination should mean the same thing as `std::hexfloat`. 1320 LOG(INFO) << std::setiosflags(std::ios_base::scientific | 1321 std::ios_base::fixed) 1322 << value; 1323 } 1324 #endif 1325 1326 #if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22) 1327 // Bionic doesn't support `%a` until API 22, so this prints 'a' even if the C++ 1328 // standard library supports `std::hexfloat` (by forwarding to printf). 1329 #elif defined(__GLIBCXX__) && __cplusplus < 201402L 1330 // libstdc++ shipped C++11 support without `std::hexfloat`. 1331 #else 1332 TEST(ManipulatorLogFormatTest, HexfloatFloat) { 1333 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1334 1335 const double value = 7.7e7; 1336 auto comparison_stream = ComparisonStream(); 1337 comparison_stream << std::hexfloat << value; 1338 1339 EXPECT_CALL( 1340 test_sink, 1341 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1342 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"), 1343 Eq("0x1.25bb500000000p+26"))), 1344 ENCODED_MESSAGE(HasValues(ElementsAre( 1345 AnyOf(ValueWithStr(Eq("0x1.25bb5p+26")), 1346 ValueWithStr(Eq("0x1.25bb500000000p+26"))))))))); 1347 1348 test_sink.StartCapturingLogs(); 1349 LOG(INFO) << std::hexfloat << value; 1350 } 1351 #endif 1352 1353 TEST(ManipulatorLogFormatTest, DefaultFloatFloat) { 1354 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1355 1356 const double value = 7.7e7; 1357 auto comparison_stream = ComparisonStream(); 1358 comparison_stream << std::hexfloat << std::defaultfloat << value; 1359 1360 EXPECT_CALL(test_sink, 1361 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1362 TextMessage(Eq("7.7e+07")), 1363 ENCODED_MESSAGE(HasValues( 1364 ElementsAre(ValueWithStr(Eq("7.7e+07")))))))); 1365 1366 test_sink.StartCapturingLogs(); 1367 LOG(INFO) << std::hexfloat << std::defaultfloat << value; 1368 } 1369 1370 TEST(ManipulatorLogFormatTest, Ends) { 1371 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1372 1373 auto comparison_stream = ComparisonStream(); 1374 comparison_stream << std::ends; 1375 1376 EXPECT_CALL(test_sink, 1377 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1378 TextMessage(Eq(absl::string_view("\0", 1))), 1379 ENCODED_MESSAGE(HasValues(ElementsAre( 1380 ValueWithStr(Eq(absl::string_view("\0", 1))))))))); 1381 1382 test_sink.StartCapturingLogs(); 1383 LOG(INFO) << std::ends; 1384 } 1385 1386 TEST(ManipulatorLogFormatTest, Endl) { 1387 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1388 1389 auto comparison_stream = ComparisonStream(); 1390 comparison_stream << std::endl; 1391 1392 EXPECT_CALL( 1393 test_sink, 1394 Send(AllOf( 1395 TextMessage(MatchesOstream(comparison_stream)), 1396 TextMessage(Eq("\n")), 1397 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("\n")))))))); 1398 1399 test_sink.StartCapturingLogs(); 1400 LOG(INFO) << std::endl; 1401 } 1402 1403 TEST(ManipulatorLogFormatTest, SetIosFlags) { 1404 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1405 1406 const int value = 0x77; 1407 auto comparison_stream = ComparisonStream(); 1408 comparison_stream << std::resetiosflags(std::ios_base::basefield) 1409 << std::setiosflags(std::ios_base::hex) << value << " " // 1410 << std::resetiosflags(std::ios_base::basefield) 1411 << std::setiosflags(std::ios_base::dec) << value; 1412 1413 EXPECT_CALL( 1414 test_sink, 1415 Send(AllOf( 1416 TextMessage(MatchesOstream(comparison_stream)), 1417 TextMessage(Eq("0x77 119")), 1418 // `std::setiosflags` and `std::resetiosflags` aren't manipulators. 1419 // We're unable to distinguish their return type(s) from arbitrary 1420 // user-defined types and thus don't suppress the empty str value. 1421 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0x77")), 1422 ValueWithLiteral(Eq(" ")), 1423 ValueWithStr(Eq("119")))))))); 1424 1425 test_sink.StartCapturingLogs(); 1426 LOG(INFO) << std::resetiosflags(std::ios_base::basefield) 1427 << std::setiosflags(std::ios_base::hex) << value << " " // 1428 << std::resetiosflags(std::ios_base::basefield) 1429 << std::setiosflags(std::ios_base::dec) << value; 1430 } 1431 1432 TEST(ManipulatorLogFormatTest, SetBase) { 1433 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1434 1435 const int value = 0x77; 1436 auto comparison_stream = ComparisonStream(); 1437 comparison_stream << std::setbase(16) << value << " " // 1438 << std::setbase(0) << value; 1439 1440 EXPECT_CALL( 1441 test_sink, 1442 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1443 TextMessage(Eq("0x77 119")), 1444 // `std::setbase` isn't a manipulator. We're unable to 1445 // distinguish its return type from arbitrary user-defined 1446 // types and thus don't suppress the empty str value. 1447 ENCODED_MESSAGE(HasValues(ElementsAre( 1448 ValueWithStr(Eq("0x77")), ValueWithLiteral(Eq(" ")), 1449 ValueWithStr(Eq("119")))))))); 1450 1451 test_sink.StartCapturingLogs(); 1452 LOG(INFO) << std::setbase(16) << value << " " // 1453 << std::setbase(0) << value; 1454 } 1455 1456 TEST(ManipulatorLogFormatTest, SetPrecision) { 1457 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1458 1459 const double value = 6.022140857e23; 1460 auto comparison_stream = ComparisonStream(); 1461 comparison_stream << std::setprecision(4) << value; 1462 1463 EXPECT_CALL( 1464 test_sink, 1465 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1466 TextMessage(Eq("6.022e+23")), 1467 // `std::setprecision` isn't a manipulator. We're unable to 1468 // distinguish its return type from arbitrary user-defined 1469 // types and thus don't suppress the empty str value. 1470 ENCODED_MESSAGE( 1471 HasValues(ElementsAre(ValueWithStr(Eq("6.022e+23")))))))); 1472 1473 test_sink.StartCapturingLogs(); 1474 LOG(INFO) << std::setprecision(4) << value; 1475 } 1476 1477 TEST(ManipulatorLogFormatTest, SetPrecisionOverflow) { 1478 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1479 1480 const double value = 6.022140857e23; 1481 auto comparison_stream = ComparisonStream(); 1482 comparison_stream << std::setprecision(200) << value; 1483 1484 EXPECT_CALL(test_sink, 1485 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1486 TextMessage(Eq("602214085700000015187968")), 1487 ENCODED_MESSAGE(HasValues(ElementsAre( 1488 ValueWithStr(Eq("602214085700000015187968")))))))); 1489 1490 test_sink.StartCapturingLogs(); 1491 LOG(INFO) << std::setprecision(200) << value; 1492 } 1493 1494 TEST(ManipulatorLogFormatTest, SetW) { 1495 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1496 1497 const int value = 77; 1498 auto comparison_stream = ComparisonStream(); 1499 comparison_stream << std::setw(8) << value; 1500 1501 EXPECT_CALL( 1502 test_sink, 1503 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1504 TextMessage(Eq(" 77")), 1505 // `std::setw` isn't a manipulator. We're unable to 1506 // distinguish its return type from arbitrary user-defined 1507 // types and thus don't suppress the empty str value. 1508 ENCODED_MESSAGE( 1509 HasValues(ElementsAre(ValueWithStr(Eq(" 77")))))))); 1510 1511 test_sink.StartCapturingLogs(); 1512 LOG(INFO) << std::setw(8) << value; 1513 } 1514 1515 TEST(ManipulatorLogFormatTest, Left) { 1516 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1517 1518 const int value = -77; 1519 auto comparison_stream = ComparisonStream(); 1520 comparison_stream << std::left << std::setw(8) << value; 1521 1522 EXPECT_CALL(test_sink, 1523 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1524 TextMessage(Eq("-77 ")), 1525 ENCODED_MESSAGE(HasValues( 1526 ElementsAre(ValueWithStr(Eq("-77 ")))))))); 1527 1528 test_sink.StartCapturingLogs(); 1529 LOG(INFO) << std::left << std::setw(8) << value; 1530 } 1531 1532 TEST(ManipulatorLogFormatTest, Right) { 1533 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1534 1535 const int value = -77; 1536 auto comparison_stream = ComparisonStream(); 1537 comparison_stream << std::right << std::setw(8) << value; 1538 1539 EXPECT_CALL(test_sink, 1540 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1541 TextMessage(Eq(" -77")), 1542 ENCODED_MESSAGE(HasValues( 1543 ElementsAre(ValueWithStr(Eq(" -77")))))))); 1544 1545 test_sink.StartCapturingLogs(); 1546 LOG(INFO) << std::right << std::setw(8) << value; 1547 } 1548 1549 TEST(ManipulatorLogFormatTest, Internal) { 1550 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1551 1552 const int value = -77; 1553 auto comparison_stream = ComparisonStream(); 1554 comparison_stream << std::internal << std::setw(8) << value; 1555 1556 EXPECT_CALL(test_sink, 1557 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1558 TextMessage(Eq("- 77")), 1559 ENCODED_MESSAGE(HasValues( 1560 ElementsAre(ValueWithStr(Eq("- 77")))))))); 1561 1562 test_sink.StartCapturingLogs(); 1563 LOG(INFO) << std::internal << std::setw(8) << value; 1564 } 1565 1566 TEST(ManipulatorLogFormatTest, SetFill) { 1567 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1568 1569 const int value = 77; 1570 auto comparison_stream = ComparisonStream(); 1571 comparison_stream << std::setfill('0') << std::setw(8) << value; 1572 1573 EXPECT_CALL(test_sink, 1574 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1575 TextMessage(Eq("00000077")), 1576 // `std::setfill` isn't a manipulator. We're 1577 // unable to distinguish its return 1578 // type from arbitrary user-defined types and 1579 // thus don't suppress the empty str value. 1580 ENCODED_MESSAGE(HasValues( 1581 ElementsAre(ValueWithStr(Eq("00000077")))))))); 1582 1583 test_sink.StartCapturingLogs(); 1584 LOG(INFO) << std::setfill('0') << std::setw(8) << value; 1585 } 1586 1587 class FromCustomClass {}; 1588 std::ostream& operator<<(std::ostream& os, const FromCustomClass&) { 1589 return os << "FromCustomClass{}" << std::hex; 1590 } 1591 1592 TEST(ManipulatorLogFormatTest, FromCustom) { 1593 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1594 1595 FromCustomClass value; 1596 auto comparison_stream = ComparisonStream(); 1597 comparison_stream << value << " " << 0x77; 1598 1599 EXPECT_CALL( 1600 test_sink, 1601 Send(AllOf(TextMessage(MatchesOstream(comparison_stream)), 1602 TextMessage(Eq("FromCustomClass{} 0x77")), 1603 ENCODED_MESSAGE(HasValues(ElementsAre( 1604 ValueWithStr(Eq("FromCustomClass{}")), 1605 ValueWithLiteral(Eq(" ")), ValueWithStr(Eq("0x77")))))))); 1606 1607 test_sink.StartCapturingLogs(); 1608 LOG(INFO) << value << " " << 0x77; 1609 } 1610 1611 class StreamsNothing {}; 1612 std::ostream& operator<<(std::ostream& os, const StreamsNothing&) { return os; } 1613 1614 TEST(ManipulatorLogFormatTest, CustomClassStreamsNothing) { 1615 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1616 1617 StreamsNothing value; 1618 auto comparison_stream = ComparisonStream(); 1619 comparison_stream << value << 77; 1620 1621 EXPECT_CALL( 1622 test_sink, 1623 Send(AllOf( 1624 TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("77")), 1625 ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77")))))))); 1626 1627 test_sink.StartCapturingLogs(); 1628 LOG(INFO) << value << 77; 1629 } 1630 1631 struct PointPercentV { 1632 template <typename Sink> 1633 friend void AbslStringify(Sink& sink, const PointPercentV& p) { 1634 absl::Format(&sink, "(%v, %v)", p.x, p.y); 1635 } 1636 1637 int x = 10; 1638 int y = 20; 1639 }; 1640 1641 TEST(ManipulatorLogFormatTest, IOManipsDoNotAffectAbslStringify) { 1642 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1643 1644 PointPercentV p; 1645 1646 EXPECT_CALL( 1647 test_sink, 1648 Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))), 1649 ENCODED_MESSAGE( 1650 HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)")))))))); 1651 1652 test_sink.StartCapturingLogs(); 1653 LOG(INFO) << std::hex << p; 1654 } 1655 1656 TEST(StructuredLoggingOverflowTest, TruncatesStrings) { 1657 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1658 1659 // This message is too long and should be truncated to some unspecified size 1660 // no greater than the buffer size but not too much less either. It should be 1661 // truncated rather than discarded. 1662 EXPECT_CALL( 1663 test_sink, 1664 Send(AllOf( 1665 TextMessage(AllOf( 1666 SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), 1667 Le(absl::log_internal::kLogMessageBufferSize))), 1668 Each(Eq('x')))), 1669 ENCODED_MESSAGE(HasOneStrThat(AllOf( 1670 SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), 1671 Le(absl::log_internal::kLogMessageBufferSize))), 1672 Each(Eq('x')))))))); 1673 1674 test_sink.StartCapturingLogs(); 1675 LOG(INFO) << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x'); 1676 } 1677 1678 struct StringLike { 1679 absl::string_view data; 1680 }; 1681 std::ostream& operator<<(std::ostream& os, StringLike str) { 1682 return os << str.data; 1683 } 1684 1685 TEST(StructuredLoggingOverflowTest, TruncatesInsertionOperators) { 1686 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1687 1688 // This message is too long and should be truncated to some unspecified size 1689 // no greater than the buffer size but not too much less either. It should be 1690 // truncated rather than discarded. 1691 EXPECT_CALL( 1692 test_sink, 1693 Send(AllOf( 1694 TextMessage(AllOf( 1695 SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), 1696 Le(absl::log_internal::kLogMessageBufferSize))), 1697 Each(Eq('x')))), 1698 ENCODED_MESSAGE(HasOneStrThat(AllOf( 1699 SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256), 1700 Le(absl::log_internal::kLogMessageBufferSize))), 1701 Each(Eq('x')))))))); 1702 1703 test_sink.StartCapturingLogs(); 1704 LOG(INFO) << StringLike{ 1705 std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x')}; 1706 } 1707 1708 // Returns the size of the largest string that will fit in a `LOG` message 1709 // buffer with no prefix. 1710 size_t MaxLogFieldLengthNoPrefix() { 1711 class StringLengthExtractorSink : public absl::LogSink { 1712 public: 1713 void Send(const absl::LogEntry& entry) override { 1714 CHECK(!size_.has_value()); 1715 CHECK_EQ(entry.text_message().find_first_not_of('x'), 1716 absl::string_view::npos); 1717 size_.emplace(entry.text_message().size()); 1718 } 1719 size_t size() const { 1720 CHECK(size_.has_value()); 1721 return *size_; 1722 } 1723 1724 private: 1725 absl::optional<size_t> size_; 1726 } extractor_sink; 1727 LOG(INFO).NoPrefix().ToSinkOnly(&extractor_sink) 1728 << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x'); 1729 return extractor_sink.size(); 1730 } 1731 1732 TEST(StructuredLoggingOverflowTest, TruncatesStringsCleanly) { 1733 const size_t longest_fit = MaxLogFieldLengthNoPrefix(); 1734 // To log a second value field, we need four bytes: two tag/type bytes and two 1735 // sizes. To put any data in the field we need a fifth byte. 1736 { 1737 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1738 EXPECT_CALL(test_sink, 1739 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1740 AllOf(SizeIs(longest_fit), Each(Eq('x'))))), 1741 RawEncodedMessage(AsString(EndsWith("x")))))); 1742 test_sink.StartCapturingLogs(); 1743 // x fits exactly, no part of y fits. 1744 LOG(INFO).NoPrefix() << std::string(longest_fit, 'x') << "y"; 1745 } 1746 { 1747 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1748 EXPECT_CALL(test_sink, 1749 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1750 AllOf(SizeIs(longest_fit - 1), Each(Eq('x'))))), 1751 RawEncodedMessage(AsString(EndsWith("x")))))); 1752 test_sink.StartCapturingLogs(); 1753 // x fits, one byte from y's header fits but shouldn't be visible. 1754 LOG(INFO).NoPrefix() << std::string(longest_fit - 1, 'x') << "y"; 1755 } 1756 { 1757 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1758 EXPECT_CALL(test_sink, 1759 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1760 AllOf(SizeIs(longest_fit - 2), Each(Eq('x'))))), 1761 RawEncodedMessage(AsString(EndsWith("x")))))); 1762 test_sink.StartCapturingLogs(); 1763 // x fits, two bytes from y's header fit but shouldn't be visible. 1764 LOG(INFO).NoPrefix() << std::string(longest_fit - 2, 'x') << "y"; 1765 } 1766 { 1767 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1768 EXPECT_CALL(test_sink, 1769 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1770 AllOf(SizeIs(longest_fit - 3), Each(Eq('x'))))), 1771 RawEncodedMessage(AsString(EndsWith("x")))))); 1772 test_sink.StartCapturingLogs(); 1773 // x fits, three bytes from y's header fit but shouldn't be visible. 1774 LOG(INFO).NoPrefix() << std::string(longest_fit - 3, 'x') << "y"; 1775 } 1776 { 1777 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1778 EXPECT_CALL(test_sink, 1779 Send(AllOf(ENCODED_MESSAGE(HasOneStrAndOneLiteralThat( 1780 AllOf(SizeIs(longest_fit - 4), Each(Eq('x'))), 1781 IsEmpty())), 1782 RawEncodedMessage(Not(AsString(EndsWith("x"))))))); 1783 test_sink.StartCapturingLogs(); 1784 // x fits, all four bytes from y's header fit but no data bytes do, so we 1785 // encode an empty string. 1786 LOG(INFO).NoPrefix() << std::string(longest_fit - 4, 'x') << "y"; 1787 } 1788 { 1789 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1790 EXPECT_CALL( 1791 test_sink, 1792 Send(AllOf(ENCODED_MESSAGE(HasOneStrAndOneLiteralThat( 1793 AllOf(SizeIs(longest_fit - 5), Each(Eq('x'))), Eq("y"))), 1794 RawEncodedMessage(AsString(EndsWith("y")))))); 1795 test_sink.StartCapturingLogs(); 1796 // x fits, y fits exactly. 1797 LOG(INFO).NoPrefix() << std::string(longest_fit - 5, 'x') << "y"; 1798 } 1799 } 1800 1801 TEST(StructuredLoggingOverflowTest, TruncatesInsertionOperatorsCleanly) { 1802 const size_t longest_fit = MaxLogFieldLengthNoPrefix(); 1803 // To log a second value field, we need four bytes: two tag/type bytes and two 1804 // sizes. To put any data in the field we need a fifth byte. 1805 { 1806 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1807 EXPECT_CALL(test_sink, 1808 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1809 AllOf(SizeIs(longest_fit), Each(Eq('x'))))), 1810 RawEncodedMessage(AsString(EndsWith("x")))))); 1811 test_sink.StartCapturingLogs(); 1812 // x fits exactly, no part of y fits. 1813 LOG(INFO).NoPrefix() << std::string(longest_fit, 'x') << StringLike{"y"}; 1814 } 1815 { 1816 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1817 EXPECT_CALL(test_sink, 1818 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1819 AllOf(SizeIs(longest_fit - 1), Each(Eq('x'))))), 1820 RawEncodedMessage(AsString(EndsWith("x")))))); 1821 test_sink.StartCapturingLogs(); 1822 // x fits, one byte from y's header fits but shouldn't be visible. 1823 LOG(INFO).NoPrefix() << std::string(longest_fit - 1, 'x') 1824 << StringLike{"y"}; 1825 } 1826 { 1827 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1828 EXPECT_CALL(test_sink, 1829 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1830 AllOf(SizeIs(longest_fit - 2), Each(Eq('x'))))), 1831 RawEncodedMessage(AsString(EndsWith("x")))))); 1832 test_sink.StartCapturingLogs(); 1833 // x fits, two bytes from y's header fit but shouldn't be visible. 1834 LOG(INFO).NoPrefix() << std::string(longest_fit - 2, 'x') 1835 << StringLike{"y"}; 1836 } 1837 { 1838 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1839 EXPECT_CALL(test_sink, 1840 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1841 AllOf(SizeIs(longest_fit - 3), Each(Eq('x'))))), 1842 RawEncodedMessage(AsString(EndsWith("x")))))); 1843 test_sink.StartCapturingLogs(); 1844 // x fits, three bytes from y's header fit but shouldn't be visible. 1845 LOG(INFO).NoPrefix() << std::string(longest_fit - 3, 'x') 1846 << StringLike{"y"}; 1847 } 1848 { 1849 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1850 EXPECT_CALL(test_sink, 1851 Send(AllOf(ENCODED_MESSAGE(HasOneStrThat( 1852 AllOf(SizeIs(longest_fit - 4), Each(Eq('x'))))), 1853 RawEncodedMessage(AsString(EndsWith("x")))))); 1854 test_sink.StartCapturingLogs(); 1855 // x fits, all four bytes from y's header fit but no data bytes do. We 1856 // don't encode an empty string here because every I/O manipulator hits this 1857 // codepath and those shouldn't leave empty strings behind. 1858 LOG(INFO).NoPrefix() << std::string(longest_fit - 4, 'x') 1859 << StringLike{"y"}; 1860 } 1861 { 1862 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected); 1863 EXPECT_CALL( 1864 test_sink, 1865 Send(AllOf(ENCODED_MESSAGE(HasTwoStrsThat( 1866 AllOf(SizeIs(longest_fit - 5), Each(Eq('x'))), Eq("y"))), 1867 RawEncodedMessage(AsString(EndsWith("y")))))); 1868 test_sink.StartCapturingLogs(); 1869 // x fits, y fits exactly. 1870 LOG(INFO).NoPrefix() << std::string(longest_fit - 5, 'x') 1871 << StringLike{"y"}; 1872 } 1873 } 1874 1875 } // namespace