Files
react-native/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/tests/LazyShadowTreeRevisionConsistencyManagerTest.cpp
T
Samuel Susla 3fff4cf966 delete MountingCoordinator::Shared typealias (#47207)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47207

changelog: [internal]

delete typealias `MountingCoordinator::Shared` and use `std::shared_ptr<const MountingCoordinator>` directly.

Reviewed By: christophpurrer

Differential Revision: D64917023

fbshipit-source-id: 586ffcd5d22ea48b22d8a6cf86aa5fdf87fdefd0
2024-10-25 12:51:57 -07:00

396 lines
11 KiB
C++

/*
* 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 <gtest/gtest.h>
#include <react/renderer/components/root/RootShadowNode.h>
#include <react/renderer/element/testUtils.h>
#include <react/renderer/mounting/ShadowTree.h>
#include <react/renderer/mounting/ShadowTreeRegistry.h>
#include <react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h>
namespace facebook::react {
class FakeShadowTreeDelegate : public ShadowTreeDelegate {
public:
RootShadowNode::Unshared shadowTreeWillCommit(
const ShadowTree& /*shadowTree*/,
const RootShadowNode::Shared& /*oldRootShadowNode*/,
const RootShadowNode::Unshared& newRootShadowNode) const override {
return newRootShadowNode;
};
void shadowTreeDidFinishTransaction(
std::shared_ptr<const MountingCoordinator> mountingCoordinator,
bool mountSynchronously) const override {};
};
class LazyShadowTreeRevisionConsistencyManagerTest : public ::testing::Test {
public:
LazyShadowTreeRevisionConsistencyManagerTest()
: consistencyManager_(shadowTreeRegistry_) {}
void TearDown() override {
// this is necessary because otherwise the test will crash with an assertion
// preventing the deallocation of the registry with registered shadow trees.
auto ids = std::vector<SurfaceId>();
shadowTreeRegistry_.enumerate(
[&ids](const ShadowTree& shadowTree, bool& /*stop*/) {
ids.push_back(shadowTree.getSurfaceId());
});
for (auto id : ids) {
shadowTreeRegistry_.remove(id);
}
}
std::unique_ptr<ShadowTree> createShadowTree(SurfaceId surfaceId) {
return std::make_unique<ShadowTree>(
surfaceId,
layoutConstraints_,
layoutContext_,
shadowTreeDelegate_,
contextContainer_);
}
ShadowTreeRegistry shadowTreeRegistry_{};
LazyShadowTreeRevisionConsistencyManager consistencyManager_;
LayoutConstraints layoutConstraints_{};
LayoutContext layoutContext_{};
FakeShadowTreeDelegate shadowTreeDelegate_{};
ContextContainer contextContainer_{};
};
TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testLockedOnNoRevision) {
consistencyManager_.lockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
shadowTreeRegistry_.add(createShadowTree(0));
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
consistencyManager_.unlockRevisions();
}
TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testNotLocked) {
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), newRootShadowNode);
}
TEST_F(
LazyShadowTreeRevisionConsistencyManagerTest,
testLockedOnNoRevisionWithUpdate) {
consistencyManager_.lockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
shadowTreeRegistry_.add(createShadowTree(0));
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
consistencyManager_.updateCurrentRevision(0, newRootShadowNode);
EXPECT_NE(consistencyManager_.getCurrentRevision(0), nullptr);
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
consistencyManager_.unlockRevisions();
}
TEST_F(
LazyShadowTreeRevisionConsistencyManagerTest,
testLockedOnNoRevisionWithMultipleUpdates) {
consistencyManager_.lockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
shadowTreeRegistry_.add(createShadowTree(0));
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
consistencyManager_.updateCurrentRevision(0, newRootShadowNode);
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
auto newRootShadowNode2 = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode2](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode2;
},
{});
});
consistencyManager_.updateCurrentRevision(0, newRootShadowNode2);
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(),
newRootShadowNode2.get());
consistencyManager_.unlockRevisions();
}
TEST_F(
LazyShadowTreeRevisionConsistencyManagerTest,
testLockedOnExistingRevision) {
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
consistencyManager_.lockRevisions();
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
consistencyManager_.unlockRevisions();
}
TEST_F(
LazyShadowTreeRevisionConsistencyManagerTest,
testLockedOnExistingRevisionWithUpdates) {
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
consistencyManager_.lockRevisions();
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
auto newRootShadowNode2 = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode2](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode2;
},
{});
});
// Not updated
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
consistencyManager_.updateCurrentRevision(0, newRootShadowNode2);
// Updated
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(),
newRootShadowNode2.get());
consistencyManager_.unlockRevisions();
}
TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testLockAfterUnlock) {
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
consistencyManager_.lockRevisions();
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
auto newRootShadowNode2 = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode2](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode2;
},
{});
});
// Not updated
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
consistencyManager_.unlockRevisions();
consistencyManager_.lockRevisions();
// Updated
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(),
newRootShadowNode2.get());
consistencyManager_.unlockRevisions();
}
TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testUpdateToUnmounted) {
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
consistencyManager_.lockRevisions();
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
consistencyManager_.updateCurrentRevision(0, nullptr);
// Updated
EXPECT_EQ(consistencyManager_.getCurrentRevision(0).get(), nullptr);
consistencyManager_.unlockRevisions();
}
TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testReentrance) {
consistencyManager_.lockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
shadowTreeRegistry_.add(createShadowTree(0));
auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);
shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
// Re-entrance
consistencyManager_.lockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
// Exit second lock
consistencyManager_.unlockRevisions();
EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr);
// Exit first lock
consistencyManager_.unlockRevisions();
// Updated!
EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());
}
} // namespace facebook::react