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