mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add test for LazyShadowTreeRevisionConsistencyManager and fix bugs
Summary: Changelog: [internal] `LazyShadowTreeRevisionConsistencyManager` wasn't correctly updating the locked revision, because `emplace` is a no-op if there's already a value for the key in the `unordered_map`. This fixes the issue and adds tests that actually showed it. Reviewed By: sammy-SC Differential Revision: D56761941 fbshipit-source-id: 340e9195b14460a591c48186bd365688c74ade04
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9cfc71dc66
commit
cfbee0b7ec
+2
-3
@@ -18,8 +18,7 @@ LazyShadowTreeRevisionConsistencyManager::
|
||||
void LazyShadowTreeRevisionConsistencyManager::updateCurrentRevision(
|
||||
SurfaceId surfaceId,
|
||||
RootShadowNode::Shared rootShadowNode) {
|
||||
capturedRootShadowNodesForConsistency_.emplace(
|
||||
surfaceId, std::move(rootShadowNode));
|
||||
capturedRootShadowNodesForConsistency_[surfaceId] = std::move(rootShadowNode);
|
||||
}
|
||||
|
||||
#pragma mark - ShadowTreeRevisionProvider
|
||||
@@ -38,7 +37,7 @@ LazyShadowTreeRevisionConsistencyManager::getCurrentRevision(
|
||||
rootShadowNode = shadowTree.getCurrentRevision().rootShadowNode;
|
||||
});
|
||||
|
||||
capturedRootShadowNodesForConsistency_.emplace(surfaceId, rootShadowNode);
|
||||
capturedRootShadowNodesForConsistency_[surfaceId] = rootShadowNode;
|
||||
|
||||
return rootShadowNode;
|
||||
}
|
||||
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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(
|
||||
MountingCoordinator::Shared 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,
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
Reference in New Issue
Block a user