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:
Danil Chapovalov 2024-09-30 15:12:43 +02:00 committed by WebRTC LUCI CQ
parent 789a54a0c4
commit 8652855872
6 changed files with 80 additions and 9 deletions

View File

@ -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) {

View File

@ -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",
], ],

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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";