Summary: `/*` is the standard throughout open source code. For example, Firefox uses single /*: https://hg.mozilla.org/mozilla-central/file/21d22b2f541258d3d1cf96c7ba5ad73e96e616b5/gfx/ipc/CompositorWidgetVsyncObserver.cpp#l3 In addition, Rust considers `/**` to be a doc comment (similar to Javadoc) and having such a comment at the beginning of the file causes `rustc` to barf. Note that some JavaScript tooling requires `/**`. This is OK since JavaScript files were not covered by the linter in the first place, but it would be good to have that tooling fixed too. Reviewed By: zertosh Differential Revision: D15640366 fbshipit-source-id: b4ed4599071516364d6109720750d6a43304c089
288 lines
10 KiB
C++
288 lines
10 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the LICENSE
|
|
* file in the root directory of this source tree.
|
|
*/
|
|
#include <gtest/gtest.h>
|
|
#include <yoga/testutil/testutil.h>
|
|
#include <yoga/Yoga.h>
|
|
#include <yoga/YGNode.h>
|
|
|
|
using facebook::yoga::test::TestUtil;
|
|
|
|
TEST(YogaTest, cloning_shared_root) {
|
|
const YGConfigRef config = YGConfigNew();
|
|
|
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetWidth(root, 100);
|
|
YGNodeStyleSetHeight(root, 100);
|
|
|
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexGrow(root_child0, 1);
|
|
YGNodeStyleSetFlexBasis(root_child0, 50);
|
|
YGNodeInsertChild(root, root_child0, 0);
|
|
|
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexGrow(root_child1, 1);
|
|
YGNodeInsertChild(root, root_child1, 1);
|
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
|
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
|
|
|
|
const YGNodeRef root2 = YGNodeClone(root);
|
|
YGNodeStyleSetWidth(root2, 100);
|
|
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
|
// The children should have referential equality at this point.
|
|
ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
|
|
ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
|
|
|
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
|
// Relayout with no changed input should result in referential equality.
|
|
ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
|
|
ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
|
|
|
|
YGNodeStyleSetWidth(root2, 150);
|
|
YGNodeStyleSetHeight(root2, 200);
|
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
|
// Relayout with changed input should result in cloned children.
|
|
const YGNodeRef root2_child0 = YGNodeGetChild(root2, 0);
|
|
const YGNodeRef root2_child1 = YGNodeGetChild(root2, 1);
|
|
ASSERT_NE(root_child0, root2_child0);
|
|
ASSERT_NE(root_child1, root2_child1);
|
|
|
|
// Everything in the root should remain unchanged.
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
|
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
|
|
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
|
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
|
|
|
|
// The new root now has new layout.
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2));
|
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2));
|
|
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root2));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child0));
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2_child0));
|
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child0));
|
|
ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root2_child0));
|
|
|
|
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child1));
|
|
ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root2_child1));
|
|
ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child1));
|
|
ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root2_child1));
|
|
|
|
YGNodeFreeRecursive(root2);
|
|
|
|
YGNodeFreeRecursive(root);
|
|
|
|
YGConfigFree(config);
|
|
}
|
|
|
|
TEST(YogaTest, mutating_children_of_a_clone_clones_only_after_layout) {
|
|
const YGConfigRef config = YGConfigNew();
|
|
|
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
|
ASSERT_EQ(0, YGNodeGetChildCount(root));
|
|
|
|
const YGNodeRef root2 = YGNodeClone(root);
|
|
ASSERT_EQ(0, YGNodeGetChildCount(root2));
|
|
|
|
const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
|
|
YGNodeInsertChild(root2, root2_child0, 0);
|
|
|
|
ASSERT_EQ(0, YGNodeGetChildCount(root));
|
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
|
|
|
const YGNodeRef root3 = YGNodeClone(root2);
|
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
|
ASSERT_EQ(1, YGNodeGetChildCount(root3));
|
|
ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
|
|
|
const YGNodeRef root3_child1 = YGNodeNewWithConfig(config);
|
|
YGNodeInsertChild(root3, root3_child1, 1);
|
|
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
|
ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
|
|
ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
|
|
|
const YGNodeRef root4 = YGNodeClone(root3);
|
|
ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));
|
|
|
|
YGNodeRemoveChild(root4, root3_child1);
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
|
ASSERT_EQ(1, YGNodeGetChildCount(root4));
|
|
ASSERT_EQ(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
|
|
|
|
YGNodeCalculateLayout(root4, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
|
|
YGNodeCalculateLayout(root3, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
|
|
|
YGNodeFreeRecursive(root4);
|
|
YGNodeFreeRecursive(root3);
|
|
YGNodeFreeRecursive(root2);
|
|
YGNodeFreeRecursive(root);
|
|
|
|
YGConfigFree(config);
|
|
}
|
|
|
|
TEST(YogaTest, cloning_two_levels) {
|
|
const YGConfigRef config = YGConfigNew();
|
|
|
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetWidth(root, 100);
|
|
YGNodeStyleSetHeight(root, 100);
|
|
|
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexGrow(root_child0, 1);
|
|
YGNodeStyleSetFlexBasis(root_child0, 15);
|
|
YGNodeInsertChild(root, root_child0, 0);
|
|
|
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexGrow(root_child1, 1);
|
|
YGNodeInsertChild(root, root_child1, 1);
|
|
|
|
const YGNodeRef root_child1_0 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexBasis(root_child1_0, 10);
|
|
YGNodeStyleSetFlexGrow(root_child1_0, 1);
|
|
YGNodeInsertChild(root_child1, root_child1_0, 0);
|
|
|
|
const YGNodeRef root_child1_1 = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetFlexBasis(root_child1_1, 25);
|
|
YGNodeInsertChild(root_child1, root_child1_1, 1);
|
|
|
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
|
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
|
|
ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
|
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
|
|
|
|
const YGNodeRef root2_child0 = YGNodeClone(root_child0);
|
|
const YGNodeRef root2_child1 = YGNodeClone(root_child1);
|
|
const YGNodeRef root2 = YGNodeClone(root);
|
|
|
|
YGNodeStyleSetFlexGrow(root2_child0, 0);
|
|
YGNodeStyleSetFlexBasis(root2_child0, 40);
|
|
|
|
YGNodeRemoveAllChildren(root2);
|
|
YGNodeInsertChild(root2, root2_child0, 0);
|
|
YGNodeInsertChild(root2, root2_child1, 1);
|
|
ASSERT_EQ(2, YGNodeGetChildCount(root2));
|
|
|
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
// Original root is unchanged
|
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
|
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
|
|
ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
|
|
ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
|
|
|
|
// New root has new layout at the top
|
|
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root2_child0));
|
|
ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root2_child1));
|
|
|
|
// The deeper children are untouched.
|
|
ASSERT_EQ(YGNodeGetChild(root2_child1, 0), root_child1_0);
|
|
ASSERT_EQ(YGNodeGetChild(root2_child1, 1), root_child1_1);
|
|
|
|
YGNodeFreeRecursive(root2);
|
|
YGNodeFreeRecursive(root);
|
|
|
|
YGConfigFree(config);
|
|
}
|
|
|
|
TEST(YogaTest, cloning_and_freeing) {
|
|
TestUtil::startCountingNodes();
|
|
|
|
const YGConfigRef config = YGConfigNew();
|
|
|
|
const YGNodeRef root = YGNodeNewWithConfig(config);
|
|
YGNodeStyleSetWidth(root, 100);
|
|
YGNodeStyleSetHeight(root, 100);
|
|
const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
|
|
YGNodeInsertChild(root, root_child0, 0);
|
|
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
|
|
YGNodeInsertChild(root, root_child1, 1);
|
|
|
|
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
const YGNodeRef root2 = YGNodeClone(root);
|
|
|
|
// Freeing the original root should be safe as long as we don't free its
|
|
// children.
|
|
YGNodeFree(root);
|
|
|
|
YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
|
|
YGNodeFreeRecursive(root2);
|
|
|
|
YGNodeFree(root_child0);
|
|
YGNodeFree(root_child1);
|
|
|
|
YGConfigFree(config);
|
|
|
|
ASSERT_EQ(0, TestUtil::stopCountingNodes());
|
|
}
|
|
|
|
TEST(YogaTest, mixed_shared_and_owned_children) {
|
|
// Don't try this at home!
|
|
|
|
YGNodeRef root0 = YGNodeNew();
|
|
YGNodeRef root1 = YGNodeNew();
|
|
|
|
YGNodeRef root0_child0 = YGNodeNew();
|
|
YGNodeRef root0_child0_0 = YGNodeNew();
|
|
YGNodeInsertChild(root0, root0_child0, 0);
|
|
YGNodeInsertChild(root0_child0, root0_child0_0, 0);
|
|
|
|
YGNodeRef root1_child0 = YGNodeNew();
|
|
YGNodeRef root1_child2 = YGNodeNew();
|
|
YGNodeInsertChild(root1, root1_child0, 0);
|
|
YGNodeInsertChild(root1, root1_child2, 1);
|
|
|
|
auto children = root1->getChildren();
|
|
children.insert(children.begin() + 1, root0_child0);
|
|
root1->setChildren(children);
|
|
auto secondChild = YGNodeGetChild(root1, 1);
|
|
ASSERT_EQ(secondChild, YGNodeGetChild(root0, 0));
|
|
ASSERT_EQ(YGNodeGetChild(secondChild, 0), YGNodeGetChild(root0_child0, 0));
|
|
|
|
YGNodeCalculateLayout(root1, YGUndefined, YGUndefined, YGDirectionLTR);
|
|
secondChild = YGNodeGetChild(root1, 1);
|
|
ASSERT_NE(secondChild, YGNodeGetChild(root0, 0));
|
|
ASSERT_EQ(YGNodeGetOwner(secondChild), root1);
|
|
ASSERT_NE(YGNodeGetChild(secondChild, 0), YGNodeGetChild(root0_child0, 0));
|
|
ASSERT_EQ(YGNodeGetOwner(YGNodeGetChild(secondChild, 0)), secondChild);
|
|
}
|