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 3 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", ":log",
"//absl/base:config", "//absl/base:config",
"//absl/base:log_severity", "//absl/base:log_severity",
"//absl/memory",
"//absl/strings", "//absl/strings",
"//absl/strings:internal", "//absl/strings:internal",
"//absl/types:optional",
"//absl/utility",
], ],
) )

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

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

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

Loading…
Cancel
Save