diff --git a/tests/YGDirtiedTest.cpp b/tests/YGDirtiedTest.cpp new file mode 100644 index 00000000..87793b4c --- /dev/null +++ b/tests/YGDirtiedTest.cpp @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#include +#include + +static void _dirtied(YGNodeRef node) { + int* dirtiedCount = (int*)node->getContext(); + (*dirtiedCount)++; +} + +TEST(YogaTest, dirtied) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + int dirtiedCount = 0; + root->setContext(&dirtiedCount); + root->setDirtiedFunc(_dirtied); + + ASSERT_EQ(0, dirtiedCount); + + // `_dirtied` MUST be called in case of explicit dirtying. + root->setDirty(true); + ASSERT_EQ(1, dirtiedCount); + + // `_dirtied` MUST be called ONCE. + root->setDirty(true); + ASSERT_EQ(1, dirtiedCount); +} + +TEST(YogaTest, dirtied_propagation) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 20); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + int dirtiedCount = 0; + root->setContext(&dirtiedCount); + root->setDirtiedFunc(_dirtied); + + ASSERT_EQ(0, dirtiedCount); + + // `_dirtied` MUST be called for the first time. + root_child0->markDirtyAndPropogate(); + ASSERT_EQ(1, dirtiedCount); + + // `_dirtied` must NOT be called for the second time. + root_child0->markDirtyAndPropogate(); + ASSERT_EQ(1, dirtiedCount); +} + +TEST(YogaTest, dirtied_hierarchy) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 20); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + int dirtiedCount = 0; + root_child0->setContext(&dirtiedCount); + root_child0->setDirtiedFunc(_dirtied); + + ASSERT_EQ(0, dirtiedCount); + + // `_dirtied` must NOT be called for descendants. + root->markDirtyAndPropogate(); + ASSERT_EQ(0, dirtiedCount); + + // `_dirtied` must NOT be called for the sibling node. + root_child1->markDirtyAndPropogate(); + ASSERT_EQ(0, dirtiedCount); + + // `_dirtied` MUST be called in case of explicit dirtying. + root_child0->markDirtyAndPropogate(); + ASSERT_EQ(1, dirtiedCount); +}