Skip to content

Commit d2a7e7f

Browse files
javachefacebook-github-bot
authored andcommitted
Add instrumentation tests for FabricMountingManager view lifecycle
Summary: Add Android instrumentation tests that validate the Java-side and C++ registry behavior around view preallocation, destruction, and recreation — the core scenario fixed by D98729251. Two layers of tests: 1. **Java-side tests** (IntBufferBatchMountItem): Construct mount item int/obj buffers manually and execute against MountingManager. Validates CREATE→INSERT and Preallocate→Delete→CREATE→INSERT sequences through the Java mount system. 2. **Native registry tests** (FabricMountingManagerTestHelper): JNI hybrid class that creates a real C++ FabricMountingManager and exercises the allocatedViewRegistry_ lifecycle. Validates that after preallocate + destroy, the tag is removed from the registry (the D98729251 fix), so executeMount would correctly emit a CREATE instruction. The native test helper is built as a separate library (libfabricjni_test_helper.so) under jni/react/fabric/test/, with friend access to FabricMountingManager internals. Changelog: [Internal] Differential Revision: D98935855
1 parent 3b634bc commit d2a7e7f

File tree

8 files changed

+549
-6
lines changed

8 files changed

+549
-6
lines changed

packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ void FabricMountingManager::onSurfaceStop(SurfaceId surfaceId) {
5252
allocatedViewRegistry_.erase(surfaceId);
5353
}
5454

55+
bool FabricMountingManager::isViewAllocated(SurfaceId surfaceId, Tag tag) {
56+
std::lock_guard lock(allocatedViewsMutex_);
57+
auto it = allocatedViewRegistry_.find(surfaceId);
58+
if (it == allocatedViewRegistry_.end()) {
59+
return false;
60+
}
61+
return it->second.count(tag) > 0;
62+
}
63+
5564
namespace {
5665

5766
#ifdef REACT_NATIVE_DEBUG

packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ class FabricMountingManager final {
4040
*/
4141
void drainPreallocateViewsQueue();
4242

43+
/*
44+
* Preallocates a view on the Java side and registers the tag in
45+
* allocatedViewRegistry_ so that executeMount skips the redundant Create
46+
* mount item for this tag.
47+
*/
48+
void preallocateShadowView(const ShadowView &shadowView);
49+
50+
/*
51+
* Returns true if the given tag is registered in allocatedViewRegistry_
52+
* for the given surface. A registered tag means executeMount will skip
53+
* the Create mount item (the view was already preallocated).
54+
*/
55+
bool isViewAllocated(SurfaceId surfaceId, Tag tag);
56+
4357
void executeMount(const MountingTransaction &transaction);
4458

4559
void dispatchCommand(const ShadowView &shadowView, const std::string &commandName, const folly::dynamic &args);
@@ -75,12 +89,6 @@ class FabricMountingManager final {
7589

7690
std::unordered_map<SurfaceId, std::unordered_set<Tag>> allocatedViewRegistry_{};
7791
std::recursive_mutex allocatedViewsMutex_;
78-
79-
/*
80-
* Calls FabricUIManager.preallocateView() on the Java side if view needs to
81-
* be preallocated.
82-
*/
83-
void preallocateShadowView(const ShadowView &shadowView);
8492
};
8593

8694
} // namespace facebook::react
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and 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+
8+
#include "FabricMountingManagerTestHelper.h"
9+
10+
#include <react/renderer/components/view/ViewComponentDescriptor.h>
11+
#include <react/renderer/components/view/ViewProps.h>
12+
#include <react/renderer/core/ComponentDescriptor.h>
13+
#include <react/renderer/mounting/ShadowView.h>
14+
15+
namespace facebook::react {
16+
17+
FabricMountingManagerTestHelper::FabricMountingManagerTestHelper(
18+
jni::alias_ref<JFabricUIManager::javaobject> jFabricUIManager)
19+
: javaUIManager_(jni::make_global(jFabricUIManager)) {
20+
mountingManager_ = std::make_shared<FabricMountingManager>(javaUIManager_);
21+
22+
auto params = ComponentDescriptorParameters{
23+
.eventDispatcher = EventDispatcher::Shared{},
24+
.contextContainer = std::make_shared<ContextContainer>(),
25+
.flavor = nullptr};
26+
viewComponentDescriptor_ = std::make_unique<ViewComponentDescriptor>(params);
27+
}
28+
29+
void FabricMountingManagerTestHelper::initHybrid(
30+
jni::alias_ref<jhybridobject> jobj,
31+
jni::alias_ref<JFabricUIManager::javaobject> jFabricUIManager) {
32+
setCxxInstance(jobj, jFabricUIManager);
33+
}
34+
35+
void FabricMountingManagerTestHelper::startSurface(jint surfaceId) {
36+
mountingManager_->onSurfaceStart(surfaceId);
37+
}
38+
39+
void FabricMountingManagerTestHelper::stopSurface(jint surfaceId) {
40+
mountingManager_->onSurfaceStop(surfaceId);
41+
}
42+
43+
void FabricMountingManagerTestHelper::preallocateView(
44+
jint surfaceId,
45+
jint tag) {
46+
ShadowView sv{};
47+
sv.componentName = "View";
48+
sv.surfaceId = surfaceId;
49+
sv.tag = tag;
50+
sv.props = std::make_shared<const ViewProps>();
51+
sv.layoutMetrics.frame.size = {100, 100};
52+
mountingManager_->preallocateShadowView(sv);
53+
}
54+
55+
void FabricMountingManagerTestHelper::destroyUnmountedView(
56+
jint surfaceId,
57+
jint tag) {
58+
auto family = viewComponentDescriptor_->createFamily(
59+
{.tag = tag, .surfaceId = surfaceId, .instanceHandle = nullptr});
60+
mountingManager_->destroyUnmountedShadowNode(*family);
61+
}
62+
63+
bool FabricMountingManagerTestHelper::wouldSkipCreate(
64+
jint surfaceId,
65+
jint tag) {
66+
return mountingManager_->isViewAllocated(surfaceId, tag);
67+
}
68+
69+
bool FabricMountingManagerTestHelper::isTagAllocated(jint surfaceId, jint tag) {
70+
return mountingManager_->isViewAllocated(surfaceId, tag);
71+
}
72+
73+
void FabricMountingManagerTestHelper::registerNatives() {
74+
registerHybrid({
75+
makeNativeMethod(
76+
"initHybrid", FabricMountingManagerTestHelper::initHybrid),
77+
makeNativeMethod(
78+
"startSurface", FabricMountingManagerTestHelper::startSurface),
79+
makeNativeMethod(
80+
"stopSurface", FabricMountingManagerTestHelper::stopSurface),
81+
makeNativeMethod(
82+
"preallocateView", FabricMountingManagerTestHelper::preallocateView),
83+
makeNativeMethod(
84+
"destroyUnmountedView",
85+
FabricMountingManagerTestHelper::destroyUnmountedView),
86+
makeNativeMethod(
87+
"wouldSkipCreate", FabricMountingManagerTestHelper::wouldSkipCreate),
88+
makeNativeMethod(
89+
"isTagAllocated", FabricMountingManagerTestHelper::isTagAllocated),
90+
});
91+
}
92+
93+
} // namespace facebook::react
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and 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+
8+
#pragma once
9+
10+
#include <fbjni/fbjni.h>
11+
#include <react/renderer/components/view/ViewComponentDescriptor.h>
12+
13+
#include <react/fabric/FabricMountingManager.h>
14+
15+
namespace facebook::react {
16+
17+
/**
18+
* JNI test helper that wraps a real FabricMountingManager
19+
*/
20+
class FabricMountingManagerTestHelper : public jni::HybridClass<FabricMountingManagerTestHelper> {
21+
public:
22+
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/fabric/FabricMountingManagerTestHelper;";
23+
24+
void startSurface(jint surfaceId);
25+
void stopSurface(jint surfaceId);
26+
void preallocateView(jint surfaceId, jint tag);
27+
void destroyUnmountedView(jint surfaceId, jint tag);
28+
bool wouldSkipCreate(jint surfaceId, jint tag);
29+
bool isTagAllocated(jint surfaceId, jint tag);
30+
31+
static void registerNatives();
32+
33+
private:
34+
friend HybridBase;
35+
36+
explicit FabricMountingManagerTestHelper(jni::alias_ref<JFabricUIManager::javaobject> jFabricUIManager);
37+
38+
static void initHybrid(
39+
jni::alias_ref<jhybridobject> jobj,
40+
jni::alias_ref<JFabricUIManager::javaobject> jFabricUIManager);
41+
42+
jni::global_ref<JFabricUIManager::javaobject> javaUIManager_;
43+
std::shared_ptr<FabricMountingManager> mountingManager_;
44+
std::unique_ptr<ViewComponentDescriptor> viewComponentDescriptor_;
45+
};
46+
47+
} // namespace facebook::react
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and 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+
8+
#include <fbjni/fbjni.h>
9+
10+
#include "FabricMountingManagerTestHelper.h"
11+
12+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
13+
return facebook::jni::initialize(vm, [] {
14+
facebook::react::FabricMountingManagerTestHelper::registerNatives();
15+
});
16+
}

0 commit comments

Comments
 (0)