Commit 0ad61817 authored by Karel Král's avatar Karel Král Committed by Commit Bot

Enable tracing mojo typemapped parameters

Implement a helper to get string representation out of C++ types. Use
this to provide tracing of typemapped parameters of mojo
auto-generated methods.

TBR=fdoray@chromium.org

Bug: 1103623
Change-Id: I61e1422bae5647e042aaf1f2718682323fba2db6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2324846
Commit-Queue: Karel Král <karelkral@google.com>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarOksana Zhuravlova <oksamyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795016}
parent af1cd3b7
......@@ -2124,6 +2124,7 @@ jumbo_component("base") {
"trace_event/trace_config.h",
"trace_event/trace_config_category_filter.cc",
"trace_event/trace_config_category_filter.h",
"trace_event/trace_conversion_helper.h",
"trace_event/trace_event.h",
"trace_event/trace_event_filter.cc",
"trace_event/trace_event_filter.h",
......@@ -3323,6 +3324,7 @@ test("base_unittests") {
"trace_event/trace_arguments_unittest.cc",
"trace_event/trace_category_unittest.cc",
"trace_event/trace_config_unittest.cc",
"trace_event/trace_conversion_helper_unittest.cc",
"trace_event/trace_event_filter_test_utils.cc",
"trace_event/trace_event_filter_test_utils.h",
"trace_event/trace_event_unittest.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TRACE_EVENT_TRACE_CONVERSION_HELPER_H_
#define BASE_TRACE_EVENT_TRACE_CONVERSION_HELPER_H_
#include <sstream>
#include <string>
#include "base/strings/string_number_conversions.h"
namespace base {
namespace trace_event {
// Helpers for base::trace_event::ValueToString.
namespace internal {
// Return std::string representation given by |value|'s ostream operator<<.
template <typename ValueType>
std::string OstreamValueToString(const ValueType& value) {
std::stringstream ss;
ss << value;
return ss.str();
}
// Helper class to mark call priority. Lower number has precedence:
//
// Example:
// void foo(ValueToStringPriority<1>);
// void foo(ValueToStringPriority<3>);
// foo(ValueToStringPriority<0>()); // Calls |foo(ValueToStringPriority<1>)|.
template <int N>
class ValueToStringPriority : public ValueToStringPriority<N + 1> {};
template <>
// The number must be the same as in the fallback version of
// |ValueToStringHelper|.
class ValueToStringPriority<4> {};
// Use SFINAE to decide how to extract a string from the given parameter.
// Check if |value| can be used as a parameter of |base::NumberToString|. If
// std::string is not constructible from the returned value of
// |base::NumberToString| cause compilation error.
//
// |base::NumberToString| does not do locale specific formatting and should be
// faster than using |std::ostream::operator<<|.
template <typename ValueType>
decltype(base::NumberToString(std::declval<const ValueType>()), std::string())
ValueToStringHelper(ValueToStringPriority<0>,
const ValueType& value,
std::string /* unused */) {
return base::NumberToString(value);
}
// If there is |ValueType::ToString| whose return value can be used to construct
// |std::string|, use this. Else use other methods.
template <typename ValueType>
decltype(std::string(std::declval<const ValueType>().ToString()))
ValueToStringHelper(ValueToStringPriority<1>,
const ValueType& value,
std::string /* unused */) {
return value.ToString();
}
// If |std::ostream::operator<<| can be used, use it. Useful for |void*|.
template <typename ValueType>
decltype(
std::declval<std::ostream>().operator<<(std::declval<const ValueType>()),
std::string())
ValueToStringHelper(ValueToStringPriority<2>,
const ValueType& value,
std::string /* unused */) {
return OstreamValueToString(value);
}
// Use |ValueType::operator<<| if applicable.
template <typename ValueType>
decltype(operator<<(std::declval<std::ostream&>(),
std::declval<const ValueType>()),
std::string())
ValueToStringHelper(ValueToStringPriority<3>,
const ValueType& value,
std::string /* unused */) {
return OstreamValueToString(value);
}
// Fallback returns the |fallback_value|. Needs to have |ValueToStringPriority|
// with the highest number (to be called last).
template <typename ValueType>
std::string ValueToStringHelper(ValueToStringPriority<4>,
const ValueType& /* unused */,
std::string fallback_value) {
return fallback_value;
}
} // namespace internal
// The function to be used.
template <typename ValueType>
std::string ValueToString(const ValueType& value,
std::string fallback_value = "<value>") {
return internal::ValueToStringHelper(internal::ValueToStringPriority<0>(),
value, std::move(fallback_value));
}
} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_TRACE_CONVERSION_HELPER_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/trace_conversion_helper.h"
#include <stddef.h>
#include <utility>
#include "base/strings/string_util.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace trace_event {
TEST(TraceEventConversionHelperTest, OstreamValueToString) {
std::string zero = internal::OstreamValueToString(0);
EXPECT_EQ("0", zero);
}
class UseFallback {};
TEST(TraceEventConversionHelperTest, UseFallback) {
std::string answer = ValueToString(UseFallback(), "fallback");
EXPECT_EQ("fallback", answer);
}
// std::ostream::operator<<
TEST(TraceEventConversionHelperTest, StdOstream) {
const char* literal = "hello literal";
EXPECT_EQ(literal, ValueToString(literal));
std::string str = "hello std::string";
EXPECT_EQ(str, ValueToString(str));
EXPECT_EQ("1", ValueToString(true));
}
// base::NumberToString
TEST(TraceEventConversionHelperTest, Number) {
EXPECT_EQ("3.14159", ValueToString(3.14159));
EXPECT_EQ("0", ValueToString(0.f));
EXPECT_EQ("42", ValueToString(42));
}
class UseToString {
public:
std::string ToString() const { return "UseToString::ToString"; }
};
TEST(TraceEventConversionHelperTest, UseToString) {
std::string answer = ValueToString(UseToString());
EXPECT_EQ("UseToString::ToString", answer);
}
class UseFallbackNonConstTostring {
public:
std::string ToString() { return "don't return me, not const"; }
};
TEST(TraceEventConversionHelperTest, UseFallbackNonConstToString) {
std::string answer = ValueToString(UseFallbackNonConstTostring(), "fallback");
EXPECT_EQ("fallback", answer);
}
class ConfusingToStringAPI {
public:
ConfusingToStringAPI ToString() const { return ConfusingToStringAPI(); }
};
TEST(TraceEventConversionHelperTest, ConfusingToStringAPI) {
std::string answer = ValueToString(ConfusingToStringAPI(), "fallback");
EXPECT_EQ("fallback", answer);
}
// std::ostream::operator<<
TEST(TraceEventConversionHelperTest, UseOstreamOperator) {
// Test that the output is the same as when calling OstreamValueToString.
// Different platforms may represent the pointer differently, thus we don't
// compare with a value.
EXPECT_EQ(internal::OstreamValueToString((void*)0x123),
ValueToString((void*)0x123));
}
class UseOperatorLessLess {};
std::ostream& operator<<(std::ostream& os, const UseOperatorLessLess&) {
os << "UseOperatorLessLess";
return os;
}
TEST(TraceEventConversionHelperTest, UseOperatorLessLess) {
std::string answer = ValueToString(UseOperatorLessLess());
EXPECT_EQ("UseOperatorLessLess", answer);
}
class HasBoth {
public:
std::string ToString() const { return "HasBoth::ToString"; }
};
std::ostream& operator<<(std::ostream& os, const HasBoth&) {
os << "HasBoth::OperatorLessLess";
return os;
}
TEST(TraceEventConversionHelperTest, HasBoth) {
std::string answer = ValueToString(HasBoth());
EXPECT_EQ("HasBoth::ToString", answer);
}
} // namespace trace_event
} // namespace base
......@@ -231,14 +231,6 @@ class BASE_EXPORT TracedValueJSON : public TracedValue {
std::string ToFormattedJSON() const;
};
// Return std::string representation given by |value|'s ostream operator<<.
template <typename T>
std::string ValueToString(const T& value) {
std::stringstream ss;
ss << value;
return ss.str();
}
} // namespace trace_event
} // namespace base
......
......@@ -15,11 +15,6 @@
namespace base {
namespace trace_event {
TEST(TraceEventArgumentTest, ValueToString) {
std::string zero = ValueToString(0);
EXPECT_EQ("0", zero);
}
TEST(TraceEventArgumentTest, InitializerListCreatedFlatDictionary) {
std::string json;
TracedValue::Build({{"bool_var", true},
......
......@@ -51,6 +51,8 @@ namespace {{variant}} {
#include "mojo/public/cpp/bindings/mojo_buildflags.h"
#if BUILDFLAG(MOJO_TRACE_ENABLED)
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_conversion_helper.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#endif
......
......@@ -776,7 +776,8 @@ class Generator(generator.Generator):
yield _AddSingleValue('Integer', cpp_parameter_name)
return
if kind in [mojom.UINT32, mojom.INT64, mojom.UINT64]:
yield _AddSingleValue('String', 'std::to_string(%s)' % cpp_parameter_name)
yield _AddSingleValue('String',
'base::NumberToString(%s)' % cpp_parameter_name)
return
if mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind):
yield _AddSingleValue('Double', cpp_parameter_name)
......@@ -834,8 +835,12 @@ class Generator(generator.Generator):
loop_body=loop_body)):
yield line
return
yield _AddSingleValue(
'String', ' "<value of type %s>"' % self._GetCppWrapperParamType(kind))
def _TraceEventToString(cpp_parameter_name=cpp_parameter_name, kind=kind):
return 'base::trace_event::ValueToString(%s, "<value of type %s>")' % (
cpp_parameter_name, self._GetCppWrapperParamType(kind))
yield _AddSingleValue('String', _TraceEventToString())
def _GetCppWrapperType(self,
kind,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment