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