Allow RTC_LOG and RTC_CHECK to accept types that implements absl stringify
Bug: None Change-Id: If99eb0e3e285c13d81cd2bbb56163c2c2311d43a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/364201 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43119}
This commit is contained in:
parent
789a54a0c4
commit
8652855872
@ -441,6 +441,7 @@ rtc_library("logging") {
|
|||||||
"synchronization:mutex",
|
"synchronization:mutex",
|
||||||
"//third_party/abseil-cpp/absl/base:core_headers",
|
"//third_party/abseil-cpp/absl/base:core_headers",
|
||||||
"//third_party/abseil-cpp/absl/meta:type_traits",
|
"//third_party/abseil-cpp/absl/meta:type_traits",
|
||||||
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -489,6 +490,7 @@ rtc_library("checks") {
|
|||||||
"system:inline",
|
"system:inline",
|
||||||
"system:rtc_export",
|
"system:rtc_export",
|
||||||
"//third_party/abseil-cpp/absl/meta:type_traits",
|
"//third_party/abseil-cpp/absl/meta:type_traits",
|
||||||
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||||
]
|
]
|
||||||
if (build_with_chromium) {
|
if (build_with_chromium) {
|
||||||
|
|||||||
@ -6,6 +6,10 @@ include_rules = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
specific_include_rules = {
|
specific_include_rules = {
|
||||||
|
"checks.h": [
|
||||||
|
"+absl/strings/has_absl_stringify.h",
|
||||||
|
"+absl/strings/str_cat.h",
|
||||||
|
],
|
||||||
"protobuf_utils.h": [
|
"protobuf_utils.h": [
|
||||||
"+third_party/protobuf",
|
"+third_party/protobuf",
|
||||||
],
|
],
|
||||||
@ -18,6 +22,10 @@ specific_include_rules = {
|
|||||||
"event_tracer\.cc": [
|
"event_tracer\.cc": [
|
||||||
"+third_party/perfetto",
|
"+third_party/perfetto",
|
||||||
],
|
],
|
||||||
|
"logging.h": [
|
||||||
|
"+absl/strings/has_absl_stringify.h",
|
||||||
|
"+absl/strings/str_cat.h",
|
||||||
|
],
|
||||||
"trace_event\.h": [
|
"trace_event\.h": [
|
||||||
"+third_party/perfetto",
|
"+third_party/perfetto",
|
||||||
],
|
],
|
||||||
|
|||||||
@ -55,6 +55,8 @@ RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "absl/meta/type_traits.h"
|
#include "absl/meta/type_traits.h"
|
||||||
|
#include "absl/strings/has_absl_stringify.h"
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "rtc_base/numerics/safe_compare.h"
|
#include "rtc_base/numerics/safe_compare.h"
|
||||||
@ -220,6 +222,12 @@ ToStringVal MakeVal(const T& x) {
|
|||||||
return {ToLogString(x)};
|
return {ToLogString(x)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
std::enable_if_t<absl::HasAbslStringify<T>::value>* = nullptr>
|
||||||
|
ToStringVal MakeVal(const T& x) {
|
||||||
|
return {absl::StrCat(x)};
|
||||||
|
}
|
||||||
|
|
||||||
// Ephemeral type that represents the result of the logging << operator.
|
// Ephemeral type that represents the result of the logging << operator.
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
class LogStreamer;
|
class LogStreamer;
|
||||||
|
|||||||
@ -10,8 +10,14 @@
|
|||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
#include "test/gmock.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
using ::testing::Not;
|
||||||
|
|
||||||
TEST(ChecksTest, ExpressionNotEvaluatedWhenCheckPassing) {
|
TEST(ChecksTest, ExpressionNotEvaluatedWhenCheckPassing) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
RTC_CHECK(true) << "i=" << ++i;
|
RTC_CHECK(true) << "i=" << ++i;
|
||||||
@ -19,6 +25,14 @@ TEST(ChecksTest, ExpressionNotEvaluatedWhenCheckPassing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||||
|
|
||||||
|
struct StructWithStringfy {
|
||||||
|
template <typename Sink>
|
||||||
|
friend void AbslStringify(Sink& sink, const StructWithStringfy& /*self*/) {
|
||||||
|
sink.Append("absl-stringify");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TEST(ChecksDeathTest, Checks) {
|
TEST(ChecksDeathTest, Checks) {
|
||||||
#if RTC_CHECK_MSG_ENABLED
|
#if RTC_CHECK_MSG_ENABLED
|
||||||
EXPECT_DEATH(RTC_FATAL() << "message",
|
EXPECT_DEATH(RTC_FATAL() << "message",
|
||||||
@ -44,6 +58,9 @@ TEST(ChecksDeathTest, Checks) {
|
|||||||
"# last system error: \\w+\n"
|
"# last system error: \\w+\n"
|
||||||
"# Check failed: false\n"
|
"# Check failed: false\n"
|
||||||
"# Hi there!");
|
"# Hi there!");
|
||||||
|
|
||||||
|
StructWithStringfy t;
|
||||||
|
EXPECT_DEATH(RTC_CHECK(false) << t, HasSubstr("absl-stringify"));
|
||||||
#else
|
#else
|
||||||
EXPECT_DEATH(RTC_FATAL() << "message",
|
EXPECT_DEATH(RTC_FATAL() << "message",
|
||||||
"\n\n#\n"
|
"\n\n#\n"
|
||||||
@ -68,6 +85,12 @@ TEST(ChecksDeathTest, Checks) {
|
|||||||
"# last system error: \\w+\n"
|
"# last system error: \\w+\n"
|
||||||
"# Check failed.\n"
|
"# Check failed.\n"
|
||||||
"# ");
|
"# ");
|
||||||
|
|
||||||
|
// Should compile, but shouldn't try to stringify 't'
|
||||||
|
StructWithStringfy t;
|
||||||
|
EXPECT_DEATH(RTC_CHECK(false) << t, Not(HasSubstr("absl-stringify")));
|
||||||
#endif // RTC_CHECK_MSG_ENABLED
|
#endif // RTC_CHECK_MSG_ENABLED
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|||||||
@ -59,6 +59,8 @@
|
|||||||
|
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/meta/type_traits.h"
|
#include "absl/meta/type_traits.h"
|
||||||
|
#include "absl/strings/has_absl_stringify.h"
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
#include "rtc_base/platform_thread_types.h"
|
#include "rtc_base/platform_thread_types.h"
|
||||||
@ -340,18 +342,24 @@ ToStringVal MakeVal(const T& x) {
|
|||||||
return {ToLogString(x)};
|
return {ToLogString(x)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
std::enable_if_t<absl::HasAbslStringify<T>::value>* = nullptr>
|
||||||
|
ToStringVal MakeVal(const T& x) {
|
||||||
|
return {absl::StrCat(x)};
|
||||||
|
}
|
||||||
|
|
||||||
// Handle arbitrary types other than the above by falling back to stringstream.
|
// Handle arbitrary types other than the above by falling back to stringstream.
|
||||||
// TODO(bugs.webrtc.org/9278): Get rid of this overload when callers don't need
|
// TODO(bugs.webrtc.org/9278): Get rid of this overload when callers don't need
|
||||||
// it anymore. No in-tree caller does, but some external callers still do.
|
// it anymore. No in-tree caller does, but some external callers still do.
|
||||||
template <
|
template <typename T,
|
||||||
typename T,
|
|
||||||
typename T1 = absl::decay_t<T>,
|
typename T1 = absl::decay_t<T>,
|
||||||
absl::enable_if_t<std::is_class<T1>::value &&
|
std::enable_if_t<std::is_class<T1>::value && //
|
||||||
!std::is_same<T1, std::string>::value &&
|
!std::is_same<T1, std::string>::value && //
|
||||||
!std::is_same<T1, LogMetadata>::value &&
|
!std::is_same<T1, LogMetadata>::value && //
|
||||||
!has_to_log_string<T1>::value &&
|
!has_to_log_string<T1>::value && //
|
||||||
|
!absl::HasAbslStringify<T1>::value &&
|
||||||
#ifdef WEBRTC_ANDROID
|
#ifdef WEBRTC_ANDROID
|
||||||
!std::is_same<T1, LogMetadataTag>::value &&
|
!std::is_same<T1, LogMetadataTag>::value && //
|
||||||
#endif
|
#endif
|
||||||
!std::is_same<T1, LogMetadataErr>::value>* = nullptr>
|
!std::is_same<T1, LogMetadataErr>::value>* = nullptr>
|
||||||
ToStringVal MakeVal(const T& x) {
|
ToStringVal MakeVal(const T& x) {
|
||||||
|
|||||||
@ -29,6 +29,8 @@ namespace rtc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
|
||||||
#if defined(WEBRTC_WIN)
|
#if defined(WEBRTC_WIN)
|
||||||
constexpr char kFakeFilePath[] = "some\\path\\myfile.cc";
|
constexpr char kFakeFilePath[] = "some\\path\\myfile.cc";
|
||||||
#else
|
#else
|
||||||
@ -367,6 +369,26 @@ TEST(LogTest, NoopSeverityDoesNotRunStringFormatting) {
|
|||||||
EXPECT_FALSE(was_called);
|
EXPECT_FALSE(was_called);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StructWithStringfy {
|
||||||
|
template <typename Sink>
|
||||||
|
friend void AbslStringify(Sink& sink, const StructWithStringfy& /*self*/) {
|
||||||
|
sink.Append("absl-stringify");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(LogTest, UseAbslStringForCustomTypes) {
|
||||||
|
std::string str;
|
||||||
|
LogSinkImpl stream(&str);
|
||||||
|
LogMessage::AddLogToStream(&stream, LS_INFO);
|
||||||
|
StructWithStringfy t;
|
||||||
|
|
||||||
|
RTC_LOG(LS_INFO) << t;
|
||||||
|
|
||||||
|
EXPECT_THAT(str, HasSubstr("absl-stringify"));
|
||||||
|
|
||||||
|
LogMessage::RemoveLogToStream(&stream);
|
||||||
|
}
|
||||||
|
|
||||||
struct TestStruct {};
|
struct TestStruct {};
|
||||||
std::string ToLogString(TestStruct foo) {
|
std::string ToLogString(TestStruct foo) {
|
||||||
return "bar";
|
return "bar";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user