first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
file(GLOB react_renderer_debug_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_renderer_debug OBJECT ${react_renderer_debug_SRC})
target_include_directories(react_renderer_debug PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(react_renderer_debug folly_runtime react_debug)
target_compile_reactnative_options(react_renderer_debug PRIVATE)
target_compile_options(react_renderer_debug PRIVATE -Wpedantic)

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "DebugStringConvertible.h"
#include <array>
#include <cinttypes>
#include <cstdio>
#include <double-conversion/double-conversion.h>
namespace facebook::react {
#if RN_DEBUG_STRING_CONVERTIBLE
std::string DebugStringConvertible::getDebugChildrenDescription(
DebugStringConvertibleOptions options) const {
if (options.depth >= options.maximumDepth) {
return "";
}
options.depth++;
auto trailing = options.format ? std::string{"\n"} : std::string{""};
std::string childrenString;
for (const auto& child : getDebugChildren()) {
if (!child) {
continue;
}
childrenString += child->getDebugDescription(options) + trailing;
}
if (!childrenString.empty() && !trailing.empty()) {
// Removing trailing fragment.
childrenString.erase(childrenString.end() - 1);
}
return childrenString;
}
std::string DebugStringConvertible::getDebugPropsDescription(
DebugStringConvertibleOptions options) const {
if (options.depth >= options.maximumDepth) {
return "";
}
options.depth++;
std::string propsString;
for (const auto& prop : getDebugProps()) {
if (!prop) {
continue;
}
auto name = prop->getDebugName();
auto value = prop->getDebugValue();
auto children = prop->getDebugPropsDescription(options);
auto valueAndChildren =
value + (children.empty() ? "" : "(" + children + ")");
propsString +=
" " + name + (valueAndChildren.empty() ? "" : "=" + valueAndChildren);
}
if (!propsString.empty()) {
// Removing leading space character.
propsString.erase(propsString.begin());
}
return propsString;
}
std::string DebugStringConvertible::getDebugDescription(
DebugStringConvertibleOptions options) const {
auto nameString = getDebugName();
auto valueString = getDebugValue();
// Convention:
// If `name` and `value` are empty, `description` is also empty.
if (nameString.empty() && valueString.empty()) {
return "";
}
// Convention:
// If `name` is empty and `value` isn't empty, `description` equals `value`.
if (nameString.empty()) {
return valueString;
}
auto childrenString = getDebugChildrenDescription(options);
auto propsString = getDebugPropsDescription(options);
auto leading =
options.format ? std::string(options.depth * 2, ' ') : std::string{""};
auto trailing = options.format ? std::string{"\n"} : std::string{""};
return leading + "<" + nameString +
(valueString.empty() ? "" : "=" + valueString) +
(propsString.empty() ? "" : " " + propsString) +
(childrenString.empty() ? "/>"
: ">" + trailing + childrenString + trailing +
leading + "</" + nameString + ">");
}
std::string DebugStringConvertible::getDebugName() const {
return "Node";
}
std::string DebugStringConvertible::getDebugValue() const {
return "";
}
SharedDebugStringConvertibleList DebugStringConvertible::getDebugChildren()
const {
return {};
}
SharedDebugStringConvertibleList DebugStringConvertible::getDebugProps() const {
return {};
}
/*
* `toString`-family implementation.
*/
std::string toString(const double& value) {
// Format taken from folly's toString
static double_conversion::DoubleToStringConverter conv(
0,
"Infinity",
"NaN",
'E',
-6, // detail::kConvMaxDecimalInShortestLow,
21, // detail::kConvMaxDecimalInShortestHigh,
6, // max leading padding zeros
1); // max trailing padding zeros
std::array<char, 256> buffer{};
double_conversion::StringBuilder builder(buffer.data(), buffer.size());
conv.ToShortest(value, &builder);
return builder.Finalize();
}
std::string toString(const void* value) {
if (value == nullptr) {
return "null";
}
std::array<char, 20> buffer{};
std::snprintf(
buffer.data(),
buffer.size(),
"0x%" PRIXPTR,
reinterpret_cast<uintptr_t>(value));
return buffer.data();
}
#endif
} // namespace facebook::react

View File

@@ -0,0 +1,398 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <climits>
#include <memory>
#include <optional>
#include <string>
#include <unordered_set>
#include <vector>
#include <react/renderer/debug/flags.h>
namespace facebook::react {
#if RN_DEBUG_STRING_CONVERTIBLE
class DebugStringConvertible;
using SharedDebugStringConvertible = std::shared_ptr<const DebugStringConvertible>;
using SharedDebugStringConvertibleList = std::vector<SharedDebugStringConvertible>;
struct DebugStringConvertibleOptions {
bool format{true};
int depth{0};
int maximumDepth{INT_MAX};
};
/*
* Abstract class describes conformance to DebugStringConvertible concept
* and implements basic recursive debug string assembly algorithm.
* Use this as a base class for providing a debugging textual representation
* of your class.
*
* The `DebugStringConvertible` *class* is obsolete. Whenever possible prefer
* implementing standalone functions that conform to the informal
* `DebugStringConvertible`-like interface instead of extending this class.
*/
class DebugStringConvertible {
public:
virtual ~DebugStringConvertible() = default;
// Returns a name of the object.
// Default implementation returns "Node".
virtual std::string getDebugName() const;
// Returns a value associate with the object.
// Default implementation returns an empty string.
virtual std::string getDebugValue() const;
// Returns a list of `DebugStringConvertible` objects which can be considered
// as *children* of the object.
// Default implementation returns an empty list.
virtual SharedDebugStringConvertibleList getDebugChildren() const;
// Returns a list of `DebugStringConvertible` objects which can be considered
// as *properties* of the object.
// Default implementation returns an empty list.
virtual SharedDebugStringConvertibleList getDebugProps() const;
// Returns a string which represents the object in a human-readable way.
// Default implementation returns a description of the subtree
// rooted at this node, represented in XML-like format.
virtual std::string getDebugDescription(DebugStringConvertibleOptions options = {}) const;
// Do same as `getDebugDescription` but return only *children* and
// *properties* parts (which are used in `getDebugDescription`).
virtual std::string getDebugPropsDescription(DebugStringConvertibleOptions options = {}) const;
virtual std::string getDebugChildrenDescription(DebugStringConvertibleOptions options = {}) const;
};
#else
struct DebugStringConvertibleOptions {};
class DebugStringConvertible {};
#endif
#if RN_DEBUG_STRING_CONVERTIBLE
/*
* Set of particular-format-opinionated functions that convert base types to
* `std::string`
*/
std::string toString(const double &value);
std::string toString(const void *value);
inline std::string toString(const std::string &value)
{
return value;
}
inline std::string toString(const int &value)
{
return std::to_string(value);
}
inline std::string toString(const unsigned int &value)
{
return std::to_string(value);
}
inline std::string toString(const bool &value)
{
return value ? "true" : "false";
}
inline std::string toString(const float &value)
{
return toString(static_cast<double>(value));
}
template <typename T>
std::string toString(const std::optional<T> &value)
{
if (!value) {
return "null";
}
return toString(value.value());
}
template <typename T>
std::string toString(const std::vector<T> &value)
{
std::string result = "[";
for (size_t i = 0; i < value.size(); i++) {
result += toString(value[i]);
if (i < value.size() - 1) {
result += ", ";
}
}
result += "]";
return result;
}
/*
* *Informal* `DebugStringConvertible` interface.
*
* The interface consts of several functions which are designed to be composable
* and reusable relying on C++ overloading mechanism. Implement appropriate
* versions of those functions for your custom type to enable conformance to the
* interface:
*
* - `getDebugName`: Returns a name of the object. Default implementation
* returns "Node".
*
* - `getDebugValue`: Returns a value associate with the object. Default
* implementation returns an empty string.
*
* - `getDebugChildren`: Returns a list of `DebugStringConvertible`-compatible
* objects which can be considered as *children* of the object. Default
* implementation returns an empty list.
*
* - `getDebugProps`: Returns a list of `DebugStringConvertible` objects which
* can be considered as *properties* of the object. Default implementation
* returns an empty list.
*
* - `getDebugDescription`: Returns a string which represents the object in a
* human-readable way. Default implementation returns a description of the
* subtree rooted at this node, represented in XML-like format using functions
* above to form the tree.
*/
/*
* Universal implementation of `getDebugDescription`-family functions for all
* types.
*/
template <typename T>
std::string getDebugName(const T & /*object*/)
{
return "Node";
}
template <typename T>
std::string getDebugValue(const T & /*object*/)
{
return "";
}
template <typename T>
std::vector<T> getDebugChildren(const T & /*object*/, DebugStringConvertibleOptions /*options*/)
{
return {};
}
template <typename T>
std::vector<T> getDebugProps(const T & /*object*/, DebugStringConvertibleOptions /*options*/)
{
return {};
}
template <typename T>
std::string getDebugPropsDescription(const T &object, DebugStringConvertibleOptions options)
{
if (options.depth >= options.maximumDepth) {
return "";
}
std::string propsString = "";
options.depth++;
for (auto prop : getDebugProps(object, options)) {
auto name = getDebugName(prop);
auto value = getDebugValue(prop);
auto children = getDebugPropsDescription(prop, options);
auto valueAndChildren = value + (children.empty() ? "" : "(" + children + ")");
propsString += " " + name + (valueAndChildren.empty() ? "" : "=" + valueAndChildren);
}
if (!propsString.empty()) {
// Removing leading space character.
propsString.erase(propsString.begin());
}
return propsString;
}
template <typename T>
std::string getDebugChildrenDescription(const T &object, DebugStringConvertibleOptions options)
{
if (options.depth >= options.maximumDepth) {
return "";
}
auto separator = options.format ? std::string{"\n"} : std::string{""};
auto childrenString = std::string{""};
options.depth++;
for (auto child : getDebugChildren(object, options)) {
childrenString += getDebugDescription(child, options) + separator;
}
if (!childrenString.empty() && !separator.empty()) {
// Removing separator fragment.
childrenString.erase(childrenString.end() - 1);
}
return childrenString;
}
template <typename T>
std::string getDebugDescription(const T &object, DebugStringConvertibleOptions options)
{
auto nameString = getDebugName(object);
auto valueString = getDebugValue(object);
// Convention:
// If `name` and `value` are empty, `description` is also empty.
if (nameString.empty() && valueString.empty()) {
return "";
}
// Convention:
// If `name` is empty and `value` isn't empty, `description` equals `value`.
if (nameString.empty()) {
return valueString;
}
auto childrenString = getDebugChildrenDescription(object, options);
auto propsString = getDebugPropsDescription(object, options);
auto prefix = options.format ? std::string(options.depth * 2, ' ') : std::string{""};
auto separator = options.format ? std::string{"\n"} : std::string{""};
return prefix + "<" + nameString + (valueString.empty() ? "" : "=" + valueString) +
(propsString.empty() ? "" : " " + propsString) +
(childrenString.empty() ? "/>" : ">" + separator + childrenString + separator + prefix + "</" + nameString + ">");
}
/*
* Functions of `getDebugDescription`-family for primitive types.
*/
// `int`
inline std::string getDebugDescription(int number, DebugStringConvertibleOptions /*options*/)
{
return toString(number);
}
// `float`
inline std::string getDebugDescription(float number, DebugStringConvertibleOptions /*options*/)
{
return toString(number);
}
// `double`
inline std::string getDebugDescription(double number, DebugStringConvertibleOptions /*options*/)
{
return toString(number);
}
// `bool`
inline std::string getDebugDescription(bool boolean, DebugStringConvertibleOptions /*options*/)
{
return toString(boolean);
}
// `void *`
inline std::string getDebugDescription(void *pointer, DebugStringConvertibleOptions /*options*/)
{
return toString(pointer);
}
// `std::string`
inline std::string getDebugDescription(const std::string &string, DebugStringConvertibleOptions /*options*/)
{
return string;
}
// `std::vector<T>`
template <typename T, typename... Ts>
std::string getDebugName(const std::vector<T, Ts...> & /*vector*/)
{
return "List";
}
template <typename T, typename... Ts>
std::vector<T, Ts...> getDebugChildren(const std::vector<T, Ts...> &vector, DebugStringConvertibleOptions /*options*/)
{
return vector;
}
// `std::array<T, Size>`
template <typename T, size_t Size>
std::string getDebugName(const std::array<T, Size> & /*array*/)
{
return "List";
}
template <typename T, size_t Size>
std::vector<T> getDebugChildren(const std::array<T, Size> &array, DebugStringConvertibleOptions /*options*/)
{
auto vector = std::vector<T>{};
for (const auto &value : array) {
vector.push_back(value);
}
return vector;
}
// `std::unordered_set<T>`
template <typename T, typename... Ts>
std::string getDebugName(const std::unordered_set<T, Ts...> & /*set*/)
{
return "Set";
}
template <typename T, typename... Ts>
std::vector<T> getDebugChildren(const std::unordered_set<T, Ts...> &set, DebugStringConvertibleOptions /*options*/)
{
auto vector = std::vector<T>{};
vector.insert(vector.end(), set.begin(), set.end());
return vector;
}
// `std::shared_ptr<T>`
template <typename T>
inline std::string getDebugDescription(const std::shared_ptr<T> &pointer, DebugStringConvertibleOptions options)
{
return getDebugDescription((void *)pointer.get(), options) + "(shared)";
}
// `std::weak_ptr<T>`
template <typename T>
inline std::string getDebugDescription(const std::weak_ptr<T> &pointer, DebugStringConvertibleOptions options)
{
return getDebugDescription((void *)pointer.lock().get(), options) + "(weak)";
}
// `std::unique_ptr<T>`
template <typename T>
inline std::string getDebugDescription(const std::unique_ptr<const T> &pointer, DebugStringConvertibleOptions options)
{
return getDebugDescription((void *)pointer.get(), options) + "(unique)";
}
/*
* Trivial container for `name` and `value` pair that supports
* static `DebugStringConvertible` informal interface.
*/
struct DebugStringConvertibleObject {
std::string name;
std::string value;
};
inline std::string getDebugName(const DebugStringConvertibleObject &object)
{
return object.name;
}
inline std::string getDebugValue(const DebugStringConvertibleObject &object)
{
return object.value;
}
#endif
} // namespace facebook::react

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "DebugStringConvertibleItem.h"
#include <utility>
namespace facebook::react {
#if RN_DEBUG_STRING_CONVERTIBLE
DebugStringConvertibleItem::DebugStringConvertibleItem(
std::string name,
std::string value,
SharedDebugStringConvertibleList props,
SharedDebugStringConvertibleList children)
: name_(std::move(name)),
value_(std::move(value)),
debugProps_(std::move(props)),
children_(std::move(children)) {}
std::string DebugStringConvertibleItem::getDebugName() const {
return name_;
}
std::string DebugStringConvertibleItem::getDebugValue() const {
return value_;
}
SharedDebugStringConvertibleList DebugStringConvertibleItem::getDebugProps()
const {
return debugProps_;
}
SharedDebugStringConvertibleList DebugStringConvertibleItem::getDebugChildren()
const {
return children_;
}
#endif
} // namespace facebook::react

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <string>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
#if RN_DEBUG_STRING_CONVERTIBLE
// Trivial implementation of `DebugStringConvertible` abstract class
// with a stored output; useful for assembling `DebugStringConvertible` values
// in custom implementations of `getDebugChildren` and `getDebugProps`.
class DebugStringConvertibleItem : public DebugStringConvertible {
public:
DebugStringConvertibleItem(const DebugStringConvertibleItem &item) = default;
DebugStringConvertibleItem(
std::string name = "",
std::string value = "",
SharedDebugStringConvertibleList props = {},
SharedDebugStringConvertibleList children = {});
std::string getDebugName() const override;
std::string getDebugValue() const override;
SharedDebugStringConvertibleList getDebugChildren() const override;
SharedDebugStringConvertibleList getDebugProps() const override;
private:
std::string name_;
std::string value_;
SharedDebugStringConvertibleList debugProps_;
SharedDebugStringConvertibleList children_;
};
#endif
} // namespace facebook::react

View File

@@ -0,0 +1,48 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end
header_search_paths = []
if ENV['USE_FRAMEWORKS']
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../../..\"" # this is needed to allow the Renderer/Debug access its own files
end
Pod::Spec.new do |s|
s.name = "React-rendererdebug"
s.version = version
s.summary = "-" # TODO
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = podspec_sources("**/*.{cpp,h,mm}", "**/*.h")
s.header_dir = "react/renderer/debug"
s.exclude_files = "tests"
s.pod_target_xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES"
}
resolve_use_frameworks(s, header_mappings_dir: "../../..", module_name: "React_rendererdebug")
add_dependency(s, "React-debug")
add_rn_third_party_dependencies(s)
add_rncore_dependency(s)
end

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <memory>
#include <optional>
#include <string>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/debug/DebugStringConvertibleItem.h>
#include <react/utils/FloatComparison.h>
namespace facebook::react {
#if RN_DEBUG_STRING_CONVERTIBLE
inline SharedDebugStringConvertible
debugStringConvertibleItem(const std::string &name, float value, float defaultValue = {})
{
if (floatEquality(value, defaultValue)) {
return nullptr;
}
return std::make_shared<DebugStringConvertibleItem>(name, facebook::react::toString(value));
}
template <typename T>
inline SharedDebugStringConvertible debugStringConvertibleItem(const std::string &name, T value, T defaultValue = {})
{
if (value == defaultValue) {
return nullptr;
}
return std::make_shared<DebugStringConvertibleItem>(name, facebook::react::toString(value));
}
template <typename T>
inline SharedDebugStringConvertible
debugStringConvertibleItem(const std::string &name, std::optional<T> value, T defaultValue = {})
{
if (!value.has_value()) {
return nullptr;
}
return debugStringConvertibleItem(name, value.value_or(defaultValue), defaultValue);
}
inline SharedDebugStringConvertibleList operator+(
const SharedDebugStringConvertibleList &lhs,
const SharedDebugStringConvertibleList &rhs)
{
auto result = SharedDebugStringConvertibleList{};
std::move(lhs.begin(), lhs.end(), std::back_inserter(result));
std::move(rhs.begin(), rhs.end(), std::back_inserter(result));
return result;
}
inline SharedDebugStringConvertible
debugStringConvertibleItem(const std::string &name, DebugStringConvertible value, std::string defaultValue)
{
return debugStringConvertibleItem(name, value.getDebugDescription(), defaultValue);
}
#endif
} // namespace facebook::react

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <react/debug/flags.h>
//
// This file contains flags that should __never__ be enabled for
// release-mode/production builds, unless explicitly noted. You can enable some
// of these for debug or local builds to assist in logging / debugging specific
// features.
//
// Enables verbose logging for the LayoutAnimations subsystem.
// #define LAYOUT_ANIMATION_VERBOSE_LOGGING 1
// Logs information before running `assert` in LayoutAnimations. More useful on
// Android vs other platforms.
// #define VERBOSE_LAYOUT_ANIMATION_ASSERTS 1
// Enables some Shadow Tree introspection features (maintains a StubViewTree,
// and logs prev/next tree and mutations if there are any discrepancies). If you
// define this, also define `RN_DEBUG_STRING_CONVERTIBLE`.
// #define RN_SHADOW_TREE_INTROSPECTION 1
// This enables certain object-to-string debug conversions to be compiled.
// Enable if `REACT_NATIVE_DEBUG` is enabled.
#ifdef REACT_NATIVE_DEBUG
#define RN_DEBUG_STRING_CONVERTIBLE 1
#else
#define RN_DEBUG_STRING_CONVERTIBLE 0
#endif
// Enables *very* verbose, noisy logs in the differ. Useful for debugging
// specifically the differ, but not much else.
// #define DEBUG_LOGS_DIFFER
// Uncomment to enable verbose StubViewTree debug logs. This ensures that errors
// are logged to console before the `assert` is fired. More useful on Android vs
// other platforms.
// #define STUB_VIEW_TREE_VERBOSE 1

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#if RN_DEBUG_STRING_CONVERTIBLE
#include <memory>
#include <gtest/gtest.h>
#include <react/renderer/debug/DebugStringConvertibleItem.h>
using namespace facebook::react;
TEST(DebugStringConvertibleTest, handleSimpleNode) {
SharedDebugStringConvertibleList empty;
auto item = std::make_shared<DebugStringConvertibleItem>(
"View", "hello", empty, empty);
ASSERT_STREQ(item->getDebugName().c_str(), "View");
ASSERT_STREQ(item->getDebugValue().c_str(), "hello");
ASSERT_STREQ(item->getDebugDescription().c_str(), "<View=hello/>");
}
TEST(DebugStringConvertibleTest, handleSimpleNodeWithProps) {
SharedDebugStringConvertibleList empty;
SharedDebugStringConvertibleList props = {
std::make_shared<DebugStringConvertibleItem>("x", "1", empty, empty)};
auto item = std::make_shared<DebugStringConvertibleItem>(
"View", "hello", props, empty);
ASSERT_STREQ(item->getDebugName().c_str(), "View");
ASSERT_STREQ(item->getDebugValue().c_str(), "hello");
ASSERT_STREQ(item->getDebugDescription().c_str(), "<View=hello x=1/>");
}
TEST(DebugStringConvertibleTest, handleSimpleNodeWithChildren) {
SharedDebugStringConvertibleList empty;
SharedDebugStringConvertibleList children = {
std::make_shared<DebugStringConvertibleItem>("Child", "a", empty, empty)};
auto item = std::make_shared<DebugStringConvertibleItem>(
"View", "hello", empty, children);
ASSERT_STREQ(item->getDebugName().c_str(), "View");
ASSERT_STREQ(item->getDebugValue().c_str(), "hello");
ASSERT_STREQ(
item->getDebugDescription().c_str(),
"<View=hello>\n <Child=a/>\n</View>");
}
TEST(DebugStringConvertibleTest, handleNestedNode) {
SharedDebugStringConvertibleList empty;
SharedDebugStringConvertibleList props = {
std::make_shared<DebugStringConvertibleItem>("x", "1", empty, empty)};
SharedDebugStringConvertibleList children = {
std::make_shared<DebugStringConvertibleItem>("Child", "a", props, empty)};
auto item = std::make_shared<DebugStringConvertibleItem>(
"View", "hello", props, children);
ASSERT_STREQ(item->getDebugName().c_str(), "View");
ASSERT_STREQ(item->getDebugValue().c_str(), "hello");
ASSERT_STREQ(
item->getDebugDescription().c_str(),
"<View=hello x=1>\n <Child=a x=1/>\n</View>");
}
TEST(DebugStringConvertibleTest, handleNodeWithComplexProps) {
SharedDebugStringConvertibleList empty;
SharedDebugStringConvertibleList subProps = {
std::make_shared<DebugStringConvertibleItem>(
"height", "100", empty, empty),
std::make_shared<DebugStringConvertibleItem>(
"width", "200", empty, empty)};
SharedDebugStringConvertibleList props = {
std::make_shared<DebugStringConvertibleItem>("x", "1", subProps, empty)};
auto item = std::make_shared<DebugStringConvertibleItem>(
"View", "hello", props, empty);
ASSERT_STREQ(item->getDebugName().c_str(), "View");
ASSERT_STREQ(item->getDebugValue().c_str(), "hello");
ASSERT_STREQ(
item->getDebugDescription().c_str(),
"<View=hello x=1(height=100 width=200)/>");
}
#endif