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