De-pointerize LogStreamer::stream_, and fix move ctor/assign preservation of flags and other stream properties.

PiperOrigin-RevId: 475643360
Change-Id: I061c167da8e45f79c2487f172190adb0177a6c10
pull/1283/head
Andy Getzendanner 2 years ago committed by Copybara-Service
parent 55996e2e30
commit d54fd91c4e
  1. 3
      absl/log/BUILD.bazel
  2. 3
      absl/log/CMakeLists.txt
  3. 29
      absl/log/log_streamer.h
  4. 48
      absl/log/log_streamer_test.cc

@ -169,9 +169,10 @@ cc_library(
":log",
"//absl/base:config",
"//absl/base:log_severity",
"//absl/memory",
"//absl/strings",
"//absl/strings:internal",
"//absl/types:optional",
"//absl/utility",
],
)

@ -506,9 +506,10 @@ absl_cc_library(
absl::config
absl::log
absl::log_severity
absl::memory
absl::optional
absl::strings
absl::strings_internal
absl::utility
PUBLIC
)

@ -31,9 +31,10 @@
#include "absl/base/config.h"
#include "absl/base/log_severity.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/strings/internal/ostringstream.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@ -81,8 +82,7 @@ class LogStreamer final {
: severity_(severity),
line_(line),
file_(file),
stream_(
absl::make_unique<absl::strings_internal::OStringStream>(&buf_)) {
stream_(absl::in_place, &buf_) {
// To match `LOG`'s defaults:
stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
}
@ -94,10 +94,8 @@ class LogStreamer final {
line_(that.line_),
file_(std::move(that.file_)),
buf_(std::move(that.buf_)),
stream_(that.stream_
? absl::make_unique<absl::strings_internal::OStringStream>(
&buf_)
: nullptr) {
stream_(std::move(that.stream_)) {
if (stream_.has_value()) stream_->str(&buf_);
that.stream_.reset();
}
LogStreamer& operator=(LogStreamer&& that) {
@ -106,10 +104,8 @@ class LogStreamer final {
file_ = std::move(that.file_);
line_ = that.line_;
buf_ = std::move(that.buf_);
stream_ =
that.stream_
? absl::make_unique<absl::strings_internal::OStringStream>(&buf_)
: nullptr;
stream_ = std::move(that.stream_);
if (stream_.has_value()) stream_->str(&buf_);
that.stream_.reset();
return *this;
}
@ -118,7 +114,8 @@ class LogStreamer final {
//
// Logs this LogStreamer's buffered content as if by LOG.
~LogStreamer() {
LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)
<< buf_;
}
// LogStreamer::stream()
@ -132,11 +129,9 @@ class LogStreamer final {
int line_;
std::string file_;
std::string buf_;
// TODO(durandal): de-pointerize this once we are off of our old mostly-C++11
// libstdc++ (which lacks move constructors for std streams).
// `stream_` is null in a moved-from `LogStreamer`; this is in fact how we
// recognize one to avoid logging when it is destroyed or reassigned.
std::unique_ptr<absl::strings_internal::OStringStream> stream_;
// A disengaged `stream_` indicates a moved-from `LogStreamer` that should not
// `LOG` upon destruction.
absl::optional<absl::strings_internal::OStringStream> stream_;
};
// LogInfoStreamer()

@ -15,6 +15,7 @@
#include "absl/log/log_streamer.h"
#include <ios>
#include <iostream>
#include <utility>
@ -300,48 +301,51 @@ TEST(LogStreamerTest, MoveConstruction) {
EXPECT_CALL(
test_sink,
Send(AllOf(
SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
LogSeverity(Eq(absl::LogSeverity::kInfo)),
TextMessage(Eq("hello world")),
ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "hello world" })pb")),
Stacktrace(IsEmpty()))));
Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
LogSeverity(Eq(absl::LogSeverity::kInfo)),
TextMessage(Eq("hello 0x10 world 0x10")),
ENCODED_MESSAGE(EqualsProto(R"pb(value {
str: "hello 0x10 world 0x10"
})pb")),
Stacktrace(IsEmpty()))));
test_sink.StartCapturingLogs();
auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
streamer1.stream() << "hello";
streamer1.stream() << "hello " << std::hex << 16;
absl::LogStreamer streamer2(std::move(streamer1));
streamer2.stream() << " world";
streamer2.stream() << " world " << 16;
}
TEST(LogStreamerTest, MoveAssignment) {
absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
testing::InSequence seq;
EXPECT_CALL(
test_sink,
Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
LogSeverity(Eq(absl::LogSeverity::kInfo)),
TextMessage(Eq("hello")),
ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "hello" })pb")),
Send(AllOf(SourceFilename(Eq("path/file2.cc")), SourceLine(Eq(5678)),
LogSeverity(Eq(absl::LogSeverity::kWarning)),
TextMessage(Eq("something else")),
ENCODED_MESSAGE(EqualsProto(R"pb(value {
str: "something else"
})pb")),
Stacktrace(IsEmpty()))));
EXPECT_CALL(
test_sink,
Send(AllOf(SourceFilename(Eq("elsewhere/name.cc")), SourceLine(Eq(5678)),
LogSeverity(Eq(absl::LogSeverity::kWarning)),
TextMessage(Eq("world; goodbye")),
Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
LogSeverity(Eq(absl::LogSeverity::kInfo)),
TextMessage(Eq("hello 0x10 world 0x10")),
ENCODED_MESSAGE(EqualsProto(R"pb(value {
str: "world; goodbye"
str: "hello 0x10 world 0x10"
})pb")),
Stacktrace(IsEmpty()))));
test_sink.StartCapturingLogs();
auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
streamer1.stream() << "hello";
auto streamer2 = absl::LogWarningStreamer("elsewhere/name.cc", 5678);
streamer2.stream() << "world";
streamer1 = std::move(streamer2);
streamer1.stream() << "; goodbye";
streamer1.stream() << "hello " << std::hex << 16;
auto streamer2 = absl::LogWarningStreamer("path/file2.cc", 5678);
streamer2.stream() << "something else";
streamer2 = std::move(streamer1);
streamer2.stream() << " world " << 16;
}
TEST(LogStreamerTest, CorrectDefaultFlags) {

Loading…
Cancel
Save