Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/abseil-cpp/absl/log/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 67 kB image not shown  

Quelle  log_format_test.cc   Sprache: C

 
//
// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <math.h>

#include <iomanip>
#include <ios>
#include <limits>
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>

#ifdef __ANDROID__
#include <android/api-level.h>
#endif
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/log/check.h"
#include "absl/log/internal/test_matchers.h"
#include "absl/log/log.h"
#include "absl/log/scoped_mock_log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"

namespace {
using ::absl::log_internal::AsString;
using ::absl::log_internal::MatchesOstream;
using ::absl::log_internal::RawEncodedMessage;
using ::absl::log_internal::TextMessage;
using ::absl::log_internal::TextPrefix;
using ::testing::AllOf;
using ::testing::AnyOf;
using ::testing::Each;
using ::testing::EndsWith;
using ::testing::Eq;
using ::testing::Ge;
using ::testing::IsEmpty;
using ::testing::Le;
using ::testing::SizeIs;
using ::testing::Types;

// Some aspects of formatting streamed data (e.g. pointer handling) are
// implementation-defined.  Others are buggy in supported implementations.
// These tests validate that the formatting matches that performed by a
// `std::ostream` and also that the result is one of a list of expected formats.

std::ostringstream ComparisonStream() {
  std::ostringstream str;
  str.setf(std::ios_base::showbase | std::ios_base::boolalpha |
           std::ios_base::internal);
  return str;
}

TEST(LogFormatTest, NoMessage) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int log_line = __LINE__ + 1;
  auto do_log = [] { LOG(INFO); };

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(ComparisonStream())),
                         TextPrefix(AsString(EndsWith(absl::StrCat(
                             " log_format_test.cc:", log_line, "] ")))),
                         TextMessage(IsEmpty()),
                         ENCODED_MESSAGE(HasValues(IsEmpty())))));

  test_sink.StartCapturingLogs();
  do_log();
}

template <typename T>
class CharLogFormatTest : public testing::Test {};
using CharTypes = Types<charsigned charunsigned char>;
TYPED_TEST_SUITE(CharLogFormatTest, CharTypes);

TYPED_TEST(CharLogFormatTest, Printable) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = 'x';
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("x")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "x")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(CharLogFormatTest, Unprintable) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  constexpr auto value = static_cast<TypeParam>(0xeeu);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("\xee")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "\xee")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

template <typename T>
class UnsignedIntLogFormatTest : public testing::Test {};
using UnsignedIntTypes = Types<unsigned shortunsigned int,        // NOLINT
                               unsigned longunsigned long long>;  // NOLINT
TYPED_TEST_SUITE(UnsignedIntLogFormatTest, UnsignedIntTypes);

TYPED_TEST(UnsignedIntLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = 224;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("224")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(UnsignedIntLogFormatTest, BitfieldPositive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{42};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("42")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "42")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}

template <typename T>
class SignedIntLogFormatTest : public testing::Test {};
using SignedIntTypes =
    Types<signed shortsigned intsigned longsigned long long>;  // NOLINT
TYPED_TEST_SUITE(SignedIntLogFormatTest, SignedIntTypes);

TYPED_TEST(SignedIntLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = 224;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("224")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(SignedIntLogFormatTest, Negative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = -112;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-112")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-112")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(SignedIntLogFormatTest, BitfieldPositive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{21};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("21")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "21")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}

TYPED_TEST(SignedIntLogFormatTest, BitfieldNegative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{-21};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-21")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "-21")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}

// Ignore these test cases on GCC due to "is too small to hold all values ..."
// warning.
#if !defined(__GNUC__) || defined(__clang__)
// The implementation may choose a signed or unsigned integer type to represent
// this enum, so it may be tested by either `UnsignedEnumLogFormatTest` or
// `SignedEnumLogFormatTest`.
enum MyUnsignedEnum {
  MyUnsignedEnum_ZERO = 0,
  MyUnsignedEnum_FORTY_TWO = 42,
  MyUnsignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
};
enum MyUnsignedIntEnum : unsigned int {
  MyUnsignedIntEnum_ZERO = 0,
  MyUnsignedIntEnum_FORTY_TWO = 42,
  MyUnsignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
};

template <typename T>
class UnsignedEnumLogFormatTest : public testing::Test {};
using UnsignedEnumTypes = std::conditional<
    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,
    Types<MyUnsignedIntEnum>, Types<MyUnsignedEnum, MyUnsignedIntEnum>>::type;
TYPED_TEST_SUITE(UnsignedEnumLogFormatTest, UnsignedEnumTypes);

TYPED_TEST(UnsignedEnumLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = static_cast<TypeParam>(224);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("224")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(UnsignedEnumLogFormatTest, BitfieldPositive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{static_cast<TypeParam>(42)};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("42")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "42")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}

enum MySignedEnum {
  MySignedEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,
  MySignedEnum_NEGATIVE_TWENTY_ONE = -21,
  MySignedEnum_ZERO = 0,
  MySignedEnum_TWENTY_ONE = 21,
  MySignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
};
enum MySignedIntEnum : signed int {
  MySignedIntEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,
  MySignedIntEnum_NEGATIVE_TWENTY_ONE = -21,
  MySignedIntEnum_ZERO = 0,
  MySignedIntEnum_TWENTY_ONE = 21,
  MySignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
};

template <typename T>
class SignedEnumLogFormatTest : public testing::Test {};
using SignedEnumTypes = std::conditional<
    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,
    Types<MyUnsignedEnum, MySignedEnum, MySignedIntEnum>,
    Types<MySignedEnum, MySignedIntEnum>>::type;
TYPED_TEST_SUITE(SignedEnumLogFormatTest, SignedEnumTypes);

TYPED_TEST(SignedEnumLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = static_cast<TypeParam>(224);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("224")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(SignedEnumLogFormatTest, Negative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = static_cast<TypeParam>(-112);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-112")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-112")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(SignedEnumLogFormatTest, BitfieldPositive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{static_cast<TypeParam>(21)};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("21")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "21")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}

TYPED_TEST(SignedEnumLogFormatTest, BitfieldNegative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const struct {
    TypeParam bits : 6;
  } value{static_cast<TypeParam>(-21)};
  auto comparison_stream = ComparisonStream();
  comparison_stream << value.bits;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-21")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "-21")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value.bits;
}
#endif

TEST(FloatLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const float value = 6.02e23f;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("6.02e+23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "6.02e+23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(FloatLogFormatTest, Negative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const float value = -6.02e23f;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-6.02e+23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-6.02e+23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(FloatLogFormatTest, NegativeExponent) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const float value = 6.02e-23f;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("6.02e-23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "6.02e-23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(DoubleLogFormatTest, Positive) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 6.02e23;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("6.02e+23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "6.02e+23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(DoubleLogFormatTest, Negative) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = -6.02e23;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-6.02e+23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-6.02e+23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(DoubleLogFormatTest, NegativeExponent) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 6.02e-23;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("6.02e-23")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "6.02e-23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

template <typename T>
class FloatingPointLogFormatTest : public testing::Test {};
using FloatingPointTypes = Types<floatdouble>;
TYPED_TEST_SUITE(FloatingPointLogFormatTest, FloatingPointTypes);

TYPED_TEST(FloatingPointLogFormatTest, Zero) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = 0.0;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("0")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "0")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(FloatingPointLogFormatTest, Integer) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = 1.0;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("1")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "1")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(FloatingPointLogFormatTest, Infinity) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = std::numeric_limits<TypeParam>::infinity();
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(AnyOf(Eq("inf"), Eq("Inf"))),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "inf")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(FloatingPointLogFormatTest, NegativeInfinity) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = -std::numeric_limits<TypeParam>::infinity();
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(AnyOf(Eq("-inf"), Eq("-Inf"))),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-inf")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(FloatingPointLogFormatTest, NaN) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = std::numeric_limits<TypeParam>::quiet_NaN();
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(AnyOf(Eq("nan"), Eq("NaN"))),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "nan")pb")))))));
  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(FloatingPointLogFormatTest, NegativeNaN) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value =
      std::copysign(std::numeric_limits<TypeParam>::quiet_NaN(), -1.0);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  // On RISC-V, don't expect that formatting -NaN produces the same string as
  // streaming it. #ifdefing out just the relevant line breaks the MSVC build,
  // so duplicate the entire EXPECT_CALL.
#ifdef __riscv
  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), Eq("-nan(ind)"))),
          ENCODED_MESSAGE(HasValues(
              ElementsAre(AnyOf(EqualsProto(R"pb(str: "-nan")pb"),
                                EqualsProto(R"pb(str: "nan")pb"),
                                EqualsProto(R"pb(str: "-nan(ind)")pb"))))))));
#else
  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(MatchesOstream(comparison_stream)),
          TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), Eq("-nan(ind)"))),
          ENCODED_MESSAGE(HasValues(
              ElementsAre(AnyOf(EqualsProto(R"pb(str: "-nan")pb"),
                                EqualsProto(R"pb(str: "nan")pb"),
                                EqualsProto(R"pb(str: "-nan(ind)")pb"))))))));
#endif
  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

template <typename T>
class VoidPtrLogFormatTest : public testing::Test {};
using VoidPtrTypes = Types<void *, const void *>;
TYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes);

TYPED_TEST(VoidPtrLogFormatTest, Null) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = nullptr;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(AnyOf(Eq("(nil)"), Eq("0"), Eq("0x0"),
                                   Eq("00000000"), Eq("0000000000000000"))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(VoidPtrLogFormatTest, NonNull) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefULL);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"),
                                   Eq("00000000DEADBEEF"))),
                 ENCODED_MESSAGE(HasValues(ElementsAre(
                     AnyOf(EqualsProto(R"pb(str: "0xdeadbeef")pb"),
                           EqualsProto(R"pb(str: "00000000DEADBEEF")pb"))))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

template <typename T>
class VolatilePtrLogFormatTest : public testing::Test {};
using VolatilePtrTypes =
    Types<volatile void*, const volatile void*, volatile char*,
          const volatile char*, volatile signed char*,
          const volatile signed char*, volatile unsigned char*,
          const volatile unsigned char*>;
TYPED_TEST_SUITE(VolatilePtrLogFormatTest, VolatilePtrTypes);

TYPED_TEST(VolatilePtrLogFormatTest, Null) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = nullptr;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("false")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "false")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(VolatilePtrLogFormatTest, NonNull) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefLL);
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("true")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "true")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

template <typename T>
class CharPtrLogFormatTest : public testing::Test {};
using CharPtrTypes = Types<charconst charsigned charconst signed char,
                           unsigned charconst unsigned char>;
TYPED_TEST_SUITE(CharPtrLogFormatTest, CharPtrTypes);

TYPED_TEST(CharPtrLogFormatTest, Null) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  // Streaming `([cv] char *)nullptr` into a `std::ostream` is UB, and some C++
  // standard library implementations choose to crash.  We take measures to log
  // something useful instead of crashing, even when that differs from the
  // standard library in use (and thus the behavior of `std::ostream`).
  TypeParam* const value = nullptr;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          // `MatchesOstream` deliberately omitted since we deliberately differ.
          TextMessage(Eq("(null)")),
          ENCODED_MESSAGE(
              HasValues(ElementsAre(EqualsProto(R"pb(str: "(null)")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TYPED_TEST(CharPtrLogFormatTest, NonNull) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  TypeParam data[] = {'v''a''l''u''e''\0'};
  TypeParam* const value = data;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("value")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "value")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(BoolLogFormatTest, True) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const bool value = true;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("true")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "true")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(BoolLogFormatTest, False) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const bool value = false;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("false")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "false")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

TEST(LogFormatTest, StringLiteral) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  auto comparison_stream = ComparisonStream();
  comparison_stream << "value";

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("value")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(literal: "value")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << "value";
}

TEST(LogFormatTest, CharArray) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  char value[] = "value";
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("value")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "value")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

class CustomClass {};
std::ostream& operator<<(std::ostream& os, const CustomClass&) {
  return os << "CustomClass{}";
}

TEST(LogFormatTest, Custom) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  CustomClass value;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("CustomClass{}")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "CustomClass{}")pb")))))));
  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

class CustomClassNonCopyable {
 public:
  CustomClassNonCopyable() = default;
  CustomClassNonCopyable(const CustomClassNonCopyable&) = delete;
  CustomClassNonCopyable& operator=(const CustomClassNonCopyable&) = delete;
};
std::ostream& operator<<(std::ostream& os, const CustomClassNonCopyable&) {
  return os << "CustomClassNonCopyable{}";
}

TEST(LogFormatTest, CustomNonCopyable) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  CustomClassNonCopyable value;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("CustomClassNonCopyable{}")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(
                             R"pb(str: "CustomClassNonCopyable{}")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value;
}

struct Point {
  template <typename Sink>
  friend void AbslStringify(Sink& sink, const Point& p) {
    absl::Format(&sink, "(%d, %d)", p.x, p.y);
  }

  int x = 10;
  int y = 20;
};

TEST(LogFormatTest, AbslStringifyExample) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  Point p;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << p;
}

struct PointWithAbslStringifiyAndOstream {
  template <typename Sink>
  friend void AbslStringify(Sink& sink,
                            const PointWithAbslStringifiyAndOstream& p) {
    absl::Format(&sink, "(%d, %d)", p.x, p.y);
  }

  int x = 10;
  int y = 20;
};

ABSL_ATTRIBUTE_UNUSED std::ostream& operator<<(
    std::ostream& os, const PointWithAbslStringifiyAndOstream&) {
  return os << "Default to AbslStringify()";
}

TEST(LogFormatTest, CustomWithAbslStringifyAndOstream) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  PointWithAbslStringifiyAndOstream p;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << p;
}

struct PointStreamsNothing {
  template <typename Sink>
  friend void AbslStringify(Sink&, const PointStreamsNothing&) {}

  int x = 10;
  int y = 20;
};

TEST(LogFormatTest, AbslStringifyStreamsNothing) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  PointStreamsNothing p;

  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("77")),
                                    TextMessage(Eq(absl::StrCat(p, 77))),
                                    ENCODED_MESSAGE(HasValues(ElementsAre(
                                        EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << p << 77;
}

struct PointMultipleAppend {
  template <typename Sink>
  friend void AbslStringify(Sink& sink, const PointMultipleAppend& p) {
    sink.Append("(");
    sink.Append(absl::StrCat(p.x, ", ", p.y, ")"));
  }

  int x = 10;
  int y = 20;
};

TEST(LogFormatTest, AbslStringifyMultipleAppend) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  PointMultipleAppend p;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "(")pb"),
                                 EqualsProto(R"pb(str: "10, 20)")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << p;
}

TEST(ManipulatorLogFormatTest, BoolAlphaTrue) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const bool value = true;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::noboolalpha << value << " "  //
                    << std::boolalpha << value << " "    //
                    << std::noboolalpha << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("1 true 1")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "1")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "true")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "1")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::noboolalpha << value << " "  //
            << std::boolalpha << value << " "    //
            << std::noboolalpha << value;
}

TEST(ManipulatorLogFormatTest, BoolAlphaFalse) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const bool value = false;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::noboolalpha << value << " "  //
                    << std::boolalpha << value << " "    //
                    << std::noboolalpha << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("0 false 0")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "0")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "false")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "0")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::noboolalpha << value << " "  //
            << std::boolalpha << value << " "    //
            << std::noboolalpha << value;
}

TEST(ManipulatorLogFormatTest, ShowPoint) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 77.0;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::noshowpoint << value << " "  //
                    << std::showpoint << value << " "    //
                    << std::noshowpoint << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77 77.0000 77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "77.0000")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::noshowpoint << value << " "  //
            << std::showpoint << value << " "    //
            << std::noshowpoint << value;
}

TEST(ManipulatorLogFormatTest, ShowPos) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::noshowpos << value << " "  //
                    << std::showpos << value << " "    //
                    << std::noshowpos << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77 +77 77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "+77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::noshowpos << value << " "  //
            << std::showpos << value << " "    //
            << std::noshowpos << value;
}

TEST(ManipulatorLogFormatTest, UppercaseFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::nouppercase << value << " "  //
                    << std::uppercase << value << " "    //
                    << std::nouppercase << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("7.7e+07 7.7E+07 7.7e+07")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "7.7e+07")pb"),
                             EqualsProto(R"pb(literal: " ")pb"),
                             EqualsProto(R"pb(str: "7.7E+07")pb"),
                             EqualsProto(R"pb(literal: " ")pb"),
                             EqualsProto(R"pb(str: "7.7e+07")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::nouppercase << value << " "  //
            << std::uppercase << value << " "    //
            << std::nouppercase << value;
}

TEST(ManipulatorLogFormatTest, Hex) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 0x77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::hex << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("0x77")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "0x77")pb")))))));
  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hex << value;
}

TEST(ManipulatorLogFormatTest, Oct) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 077;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::oct << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("077")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "077")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::oct << value;
}

TEST(ManipulatorLogFormatTest, Dec) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::hex << std::dec << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hex << std::dec << value;
}

TEST(ManipulatorLogFormatTest, ShowbaseHex) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 0x77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::hex                         //
                    << std::noshowbase << value << " "  //
                    << std::showbase << value << " "    //
                    << std::noshowbase << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77 0x77 77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "0x77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hex                         //
            << std::noshowbase << value << " "  //
            << std::showbase << value << " "    //
            << std::noshowbase << value;
}

TEST(ManipulatorLogFormatTest, ShowbaseOct) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 077;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::oct                         //
                    << std::noshowbase << value << " "  //
                    << std::showbase << value << " "    //
                    << std::noshowbase << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77 077 77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "077")pb"),
                                         EqualsProto(R"pb(literal: " ")pb"),
                                         EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::oct                         //
            << std::noshowbase << value << " "  //
            << std::showbase << value << " "    //
            << std::noshowbase << value;
}

TEST(ManipulatorLogFormatTest, UppercaseHex) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 0xbeef;
  auto comparison_stream = ComparisonStream();
  comparison_stream                        //
      << std::hex                          //
      << std::nouppercase << value << " "  //
      << std::uppercase << value << " "    //
      << std::nouppercase << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("0xbeef 0XBEEF 0xbeef")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "0xbeef")pb"),
                             EqualsProto(R"pb(literal: " ")pb"),
                             EqualsProto(R"pb(str: "0XBEEF")pb"),
                             EqualsProto(R"pb(literal: " ")pb"),
                             EqualsProto(R"pb(str: "0xbeef")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hex                          //
            << std::nouppercase << value << " "  //
            << std::uppercase << value << " "    //
            << std::nouppercase << value;
}

TEST(ManipulatorLogFormatTest, FixedFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::fixed << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77000000.000000")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "77000000.000000")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::fixed << value;
}

TEST(ManipulatorLogFormatTest, ScientificFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::scientific << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("7.700000e+07")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "7.700000e+07")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::scientific << value;
}

#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)
// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the
// C++ standard library implements it correctly (by forwarding to printf).
#elif defined(__GLIBCXX__) && __cplusplus < 201402L
// libstdc++ shipped C++11 support without `std::hexfloat`.
#else
TEST(ManipulatorLogFormatTest, FixedAndScientificFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setiosflags(std::ios_base::scientific |
                                        std::ios_base::fixed)
                    << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
                                   Eq("0x1.25bb500000000p+26"))),
                 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
                     EqualsProto(R"pb(str: "0x1.25bb5p+26")pb"),
                     EqualsProto(R"pb(str: "0x1.25bb500000000p+26")pb"))))))));

  test_sink.StartCapturingLogs();

  // This combination should mean the same thing as `std::hexfloat`.
  LOG(INFO) << std::setiosflags(std::ios_base::scientific |
                                std::ios_base::fixed)
            << value;
}
#endif

#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)
// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the C++
// standard library supports `std::hexfloat` (by forwarding to printf).
#elif defined(__GLIBCXX__) && __cplusplus < 201402L
// libstdc++ shipped C++11 support without `std::hexfloat`.
#else
TEST(ManipulatorLogFormatTest, HexfloatFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::hexfloat << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
                                   Eq("0x1.25bb500000000p+26"))),
                 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
                     EqualsProto(R"pb(str: "0x1.25bb5p+26")pb"),
                     EqualsProto(R"pb(str: "0x1.25bb500000000p+26")pb"))))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hexfloat << value;
}
#endif

TEST(ManipulatorLogFormatTest, DefaultFloatFloat) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 7.7e7;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::hexfloat << std::defaultfloat << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("7.7e+07")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "7.7e+07")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hexfloat << std::defaultfloat << value;
}

TEST(ManipulatorLogFormatTest, Ends) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  auto comparison_stream = ComparisonStream();
  comparison_stream << std::ends;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq(absl::string_view("\0", 1))),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "\0")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::ends;
}

TEST(ManipulatorLogFormatTest, Endl) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  auto comparison_stream = ComparisonStream();
  comparison_stream << std::endl;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(MatchesOstream(comparison_stream)),
          TextMessage(Eq("\n")),
          ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(R"pb(str:
          "\n")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::endl;
}

TEST(ManipulatorLogFormatTest, SetIosFlags) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 0x77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::resetiosflags(std::ios_base::basefield)
                    << std::setiosflags(std::ios_base::hex) << value << " "  //
                    << std::resetiosflags(std::ios_base::basefield)
                    << std::setiosflags(std::ios_base::dec) << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(MatchesOstream(comparison_stream)),
          TextMessage(Eq("0x77 119")),
          // `std::setiosflags` and `std::resetiosflags` aren't manipulators.
          // We're unable to distinguish their return type(s) from arbitrary
          // user-defined types and thus don't suppress the empty str value.
          ENCODED_MESSAGE(
              HasValues(ElementsAre(EqualsProto(R"pb(str: "0x77")pb"),
                                    EqualsProto(R"pb(literal: " ")pb"),
                                    EqualsProto(R"pb(str: "119")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::resetiosflags(std::ios_base::basefield)
            << std::setiosflags(std::ios_base::hex) << value << " "  //
            << std::resetiosflags(std::ios_base::basefield)
            << std::setiosflags(std::ios_base::dec) << value;
}

TEST(ManipulatorLogFormatTest, SetBase) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 0x77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setbase(16) << value << " "  //
                    << std::setbase(0) << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(Eq("0x77 119")),
                 // `std::setbase` isn't a manipulator.  We're unable to
                 // distinguish its return type from arbitrary user-defined
                 // types and thus don't suppress the empty str value.
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "0x77")pb"),
                                 EqualsProto(R"pb(literal: " ")pb"),
                                 EqualsProto(R"pb(str: "119")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::setbase(16) << value << " "  //
            << std::setbase(0) << value;
}

TEST(ManipulatorLogFormatTest, SetPrecision) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 6.022140857e23;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setprecision(4) << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(Eq("6.022e+23")),
                 // `std::setprecision` isn't a manipulator.  We're unable to
                 // distinguish its return type from arbitrary user-defined
                 // types and thus don't suppress the empty str value.
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "6.022e+23")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::setprecision(4) << value;
}

TEST(ManipulatorLogFormatTest, SetPrecisionOverflow) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const double value = 6.022140857e23;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setprecision(200) << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("602214085700000015187968")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(
                             R"pb(str: "602214085700000015187968")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::setprecision(200) << value;
}

TEST(ManipulatorLogFormatTest, SetW) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setw(8) << value;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                 TextMessage(Eq(" 77")),
                 // `std::setw` isn't a manipulator.  We're unable to
                 // distinguish its return type from arbitrary user-defined
                 // types and thus don't suppress the empty str value.
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "      77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::setw(8) << value;
}

TEST(ManipulatorLogFormatTest, Left) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = -77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::left << std::setw(8) << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("-77 ")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-77     ")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::left << std::setw(8) << value;
}

TEST(ManipulatorLogFormatTest, Right) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = -77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::right << std::setw(8) << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq(" -77")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "     -77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::right << std::setw(8) << value;
}

TEST(ManipulatorLogFormatTest, Internal) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = -77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::internal << std::setw(8) << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("- 77")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "-     77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::internal << std::setw(8) << value;
}

TEST(ManipulatorLogFormatTest, SetFill) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  const int value = 77;
  auto comparison_stream = ComparisonStream();
  comparison_stream << std::setfill('0') << std::setw(8) << value;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("00000077")),
                         // `std::setfill` isn't a manipulator.  We're
                         // unable to distinguish its return
                         // type from arbitrary user-defined types and
                         // thus don't suppress the empty str value.
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "00000077")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::setfill('0') << std::setw(8) << value;
}

class FromCustomClass {};
std::ostream& operator<<(std::ostream& os, const FromCustomClass&) {
  return os << "FromCustomClass{}" << std::hex;
}

TEST(ManipulatorLogFormatTest, FromCustom) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  FromCustomClass value;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value << " " << 0x77;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("FromCustomClass{} 0x77")),
                         ENCODED_MESSAGE(HasValues(ElementsAre(
                             EqualsProto(R"pb(str: "FromCustomClass{}")pb"),
                             EqualsProto(R"pb(literal: " ")pb"),
                             EqualsProto(R"pb(str: "0x77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value << " " << 0x77;
}

class StreamsNothing {};
std::ostream& operator<<(std::ostream& os, const StreamsNothing&) { return os; }

TEST(ManipulatorLogFormatTest, CustomClassStreamsNothing) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  StreamsNothing value;
  auto comparison_stream = ComparisonStream();
  comparison_stream << value << 77;

  EXPECT_CALL(test_sink,
              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                         TextMessage(Eq("77")),
                         ENCODED_MESSAGE(HasValues(
                             ElementsAre(EqualsProto(R"pb(str: "77")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << value << 77;
}

struct PointPercentV {
  template <typename Sink>
  friend void AbslStringify(Sink& sink, const PointPercentV& p) {
    absl::Format(&sink, "(%v, %v)", p.x, p.y);
  }

  int x = 10;
  int y = 20;
};

TEST(ManipulatorLogFormatTest, IOManipsDoNotAffectAbslStringify) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  PointPercentV p;

  EXPECT_CALL(
      test_sink,
      Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
                 ENCODED_MESSAGE(HasValues(
                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::hex << p;
}

TEST(StructuredLoggingOverflowTest, TruncatesStrings) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  // This message is too long and should be truncated to some unspecified size
  // no greater than the buffer size but not too much less either.  It should be
  // truncated rather than discarded.
  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(AllOf(
              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
                           Le(absl::log_internal::kLogMessageBufferSize))),
              Each(Eq('x')))),
          ENCODED_MESSAGE(HasOneStrThat(AllOf(
              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
                           Le(absl::log_internal::kLogMessageBufferSize))),
              Each(Eq('x'))))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x');
}

struct StringLike {
  absl::string_view data;
};
std::ostream& operator<<(std::ostream& os, StringLike str) {
  return os << str.data;
}

TEST(StructuredLoggingOverflowTest, TruncatesInsertionOperators) {
  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);

  // This message is too long and should be truncated to some unspecified size
  // no greater than the buffer size but not too much less either.  It should be
  // truncated rather than discarded.
  EXPECT_CALL(
      test_sink,
      Send(AllOf(
          TextMessage(AllOf(
              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
                           Le(absl::log_internal::kLogMessageBufferSize))),
              Each(Eq('x')))),
          ENCODED_MESSAGE(HasOneStrThat(AllOf(
              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
                           Le(absl::log_internal::kLogMessageBufferSize))),
              Each(Eq('x'))))))));

  test_sink.StartCapturingLogs();
  LOG(INFO) << StringLike{
      std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x')};
}

// Returns the size of the largest string that will fit in a `LOG` message
// buffer with no prefix.
size_t MaxLogFieldLengthNoPrefix() {
  class StringLengthExtractorSink : public absl::LogSink {
   public:
    void Send(const absl::LogEntry& entry) override {
      CHECK(!size_.has_value());
      CHECK_EQ(entry.text_message().find_first_not_of('x'),
               absl::string_view::npos);
      size_.emplace(entry.text_message().size());
    }
    size_t size() const {
      CHECK(size_.has_value());
      return *size_;
    }

   private:
    absl::optional<size_t> size_;
  } extractor_sink;
  LOG(INFO).NoPrefix().ToSinkOnly(&extractor_sink)
      << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x');
  return extractor_sink.size();
}

TEST(StructuredLoggingOverflowTest, TruncatesStringsCleanly) {
  const size_t longest_fit = MaxLogFieldLengthNoPrefix();
  // To log a second value field, we need four bytes: two tag/type bytes and two
  // sizes.  To put any data in the field we need a fifth byte.
  {
    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
    EXPECT_CALL(test_sink,
                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(
                               AllOf(SizeIs(longest_fit), Each(Eq('x'))))),
                           RawEncodedMessage(AsString(EndsWith("x"))))));
    test_sink.StartCapturingLogs();
    // x fits exactly, no part of y fits.
    LOG(INFO).NoPrefix() << std::string(longest_fit, 'x') << "y";
  }
  {
    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
    EXPECT_CALL(test_sink,
                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(
                               AllOf(SizeIs(longest_fit - 1), Each(Eq('x'))))),
                           RawEncodedMessage(AsString(EndsWith("x"))))));
    test_sink.StartCapturingLogs();
    // x fits, one byte from y's header fits but shouldn't be visible.
    LOG(INFO).NoPrefix() << std::string(longest_fit - 1, 'x') << "y";
  }
  {
    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
    EXPECT_CALL(test_sink,
                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(
                               AllOf(SizeIs(longest_fit - 2), Each(Eq('x'))))),
                           RawEncodedMessage(AsString(EndsWith("x"))))));
    test_sink.StartCapturingLogs();
    // x fits, two bytes from y's header fit but shouldn't be visible.
    LOG(INFO).NoPrefix() << std::string(longest_fit - 2, 'x') << "y";
  }
  {
    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
    EXPECT_CALL(test_sink,
                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(
                               AllOf(SizeIs(longest_fit - 3), Each(Eq('x'))))),
                           RawEncodedMessage(AsString(EndsWith("x"))))));
    test_sink.StartCapturingLogs();
    // x fits, three bytes from y's header fit but shouldn't be visible.
    LOG(INFO).NoPrefix() << std::string(longest_fit - 3, 'x') << "y";
  }
  {
    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
    EXPECT_CALL(test_sink,
                Send(AllOf(ENCODED_MESSAGE(HasOneStrAndOneLiteralThat(
                               AllOf(SizeIs(longest_fit - 4), Each(Eq('x'))),
                               IsEmpty())),
                           RawEncodedMessage(Not(AsString(EndsWith("x")))))));
    test_sink.StartCapturingLogs();
    // x fits, all four bytes from y's header fit but no data bytes do, so we
    // encode an empty string.
    LOG(INFO).NoPrefix() << std::string(longest_fit - 4, 'x') << "y";
  }
  {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=100 G=95

¤ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.