xref: /aosp_15_r20/external/abseil-cpp/absl/log/log_format_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
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