ShadowTreeLifeCycleTest.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include <glog/logging.h>
  8. #include <gtest/gtest.h>
  9. #include <react/components/root/RootComponentDescriptor.h>
  10. #include <react/components/view/ViewComponentDescriptor.h>
  11. #include <react/mounting/Differentiator.h>
  12. #include <react/mounting/stubs.h>
  13. #include "Entropy.h"
  14. #include "shadowTreeGeneration.h"
  15. namespace facebook {
  16. namespace react {
  17. static void testShadowNodeTreeLifeCycle(
  18. DifferentiatorMode differentiatorMode,
  19. uint_fast32_t seed,
  20. int treeSize,
  21. int repeats,
  22. int stages) {
  23. auto entropy = seed == 0 ? Entropy() : Entropy(seed);
  24. auto eventDispatcher = EventDispatcher::Shared{};
  25. auto contextContainer = std::make_shared<ContextContainer>();
  26. auto componentDescriptorParameters =
  27. ComponentDescriptorParameters{eventDispatcher, contextContainer, nullptr};
  28. auto viewComponentDescriptor =
  29. ViewComponentDescriptor(componentDescriptorParameters);
  30. auto rootComponentDescriptor =
  31. RootComponentDescriptor(componentDescriptorParameters);
  32. auto noopEventEmitter =
  33. std::make_shared<ViewEventEmitter const>(nullptr, -1, eventDispatcher);
  34. auto allNodes = std::vector<ShadowNode::Shared>{};
  35. for (int i = 0; i < repeats; i++) {
  36. allNodes.clear();
  37. auto family = rootComponentDescriptor.createFamily(
  38. {Tag(1), SurfaceId(1), nullptr}, nullptr);
  39. // Creating an initial root shadow node.
  40. auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
  41. std::static_pointer_cast<RootShadowNode const>(
  42. rootComponentDescriptor.createShadowNode(
  43. ShadowNodeFragment{RootShadowNode::defaultSharedProps()},
  44. family)));
  45. // Applying size constraints.
  46. emptyRootNode = emptyRootNode->clone(
  47. LayoutConstraints{Size{512, 0},
  48. Size{512, std::numeric_limits<Float>::infinity()}},
  49. LayoutContext{});
  50. // Generation of a random tree.
  51. auto singleRootChildNode =
  52. generateShadowNodeTree(entropy, viewComponentDescriptor, treeSize);
  53. // Injecting a tree into the root node.
  54. auto currentRootNode = std::static_pointer_cast<RootShadowNode const>(
  55. emptyRootNode->ShadowNode::clone(ShadowNodeFragment{
  56. ShadowNodeFragment::propsPlaceholder(),
  57. std::make_shared<SharedShadowNodeList>(
  58. SharedShadowNodeList{singleRootChildNode})}));
  59. // Building an initial view hierarchy.
  60. auto viewTree = stubViewTreeFromShadowNode(*emptyRootNode);
  61. viewTree.mutate(calculateShadowViewMutations(
  62. differentiatorMode, *emptyRootNode, *currentRootNode));
  63. for (int j = 0; j < stages; j++) {
  64. auto nextRootNode = currentRootNode;
  65. // Mutating the tree.
  66. alterShadowTree(
  67. entropy,
  68. nextRootNode,
  69. {
  70. &messWithChildren,
  71. &messWithYogaStyles,
  72. &messWithLayotableOnlyFlag,
  73. });
  74. std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
  75. affectedLayoutableNodes.reserve(1024);
  76. // Laying out the tree.
  77. std::const_pointer_cast<RootShadowNode>(nextRootNode)
  78. ->layoutIfNeeded(&affectedLayoutableNodes);
  79. nextRootNode->sealRecursive();
  80. allNodes.push_back(nextRootNode);
  81. // Calculating mutations.
  82. auto mutations = calculateShadowViewMutations(
  83. differentiatorMode, *currentRootNode, *nextRootNode);
  84. // Mutating the view tree.
  85. viewTree.mutate(mutations);
  86. // Building a view tree to compare with.
  87. auto rebuiltViewTree = stubViewTreeFromShadowNode(*nextRootNode);
  88. // Comparing the newly built tree with the updated one.
  89. if (rebuiltViewTree != viewTree) {
  90. // Something went wrong.
  91. LOG(ERROR) << "Entropy seed: " << entropy.getSeed() << "\n";
  92. LOG(ERROR) << "Shadow Tree before: \n"
  93. << currentRootNode->getDebugDescription();
  94. LOG(ERROR) << "Shadow Tree after: \n"
  95. << nextRootNode->getDebugDescription();
  96. LOG(ERROR) << "View Tree before: \n"
  97. << getDebugDescription(viewTree.getRootStubView(), {});
  98. LOG(ERROR) << "View Tree after: \n"
  99. << getDebugDescription(
  100. rebuiltViewTree.getRootStubView(), {});
  101. LOG(ERROR) << "Mutations:"
  102. << "\n"
  103. << getDebugDescription(mutations, {});
  104. FAIL();
  105. }
  106. currentRootNode = nextRootNode;
  107. }
  108. }
  109. SUCCEED();
  110. }
  111. } // namespace react
  112. } // namespace facebook
  113. using namespace facebook::react;
  114. TEST(MountingTest, stableBiggerTreeFewerIterationsClassic) {
  115. testShadowNodeTreeLifeCycle(
  116. DifferentiatorMode::Classic,
  117. /* seed */ 1,
  118. /* size */ 512,
  119. /* repeats */ 32,
  120. /* stages */ 32);
  121. }
  122. TEST(MountingTest, stableSmallerTreeMoreIterationsClassic) {
  123. testShadowNodeTreeLifeCycle(
  124. DifferentiatorMode::Classic,
  125. /* seed */ 1,
  126. /* size */ 16,
  127. /* repeats */ 512,
  128. /* stages */ 32);
  129. }
  130. TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMoves) {
  131. testShadowNodeTreeLifeCycle(
  132. DifferentiatorMode::OptimizedMoves,
  133. /* seed */ 1,
  134. /* size */ 512,
  135. /* repeats */ 32,
  136. /* stages */ 32);
  137. }
  138. TEST(MountingTest, stableSmallerTreeMoreIterationsOptimizedMoves) {
  139. testShadowNodeTreeLifeCycle(
  140. DifferentiatorMode::OptimizedMoves,
  141. /* seed */ 1,
  142. /* size */ 16,
  143. /* repeats */ 512,
  144. /* stages */ 32);
  145. }