Skip to content

Commit 2543587

Browse files
DevmateUtgenCppGeneralFBOrg Botfacebook-github-bot
authored andcommitted
xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/mounting/MountingTransaction.cpp
Reviewed By: cortinico Differential Revision: D112079573
1 parent 3f8f5c2 commit 2543587

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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 <gtest/gtest.h>
9+
10+
#include <react/renderer/mounting/MountingTransaction.h>
11+
#include <react/renderer/mounting/ShadowView.h>
12+
#include <react/renderer/mounting/ShadowViewMutation.h>
13+
#include <react/renderer/telemetry/TransactionTelemetry.h>
14+
15+
namespace facebook::react {
16+
17+
namespace {
18+
19+
ShadowView makeShadowView(Tag tag) {
20+
ShadowView view;
21+
view.tag = tag;
22+
return view;
23+
}
24+
25+
MountingTransaction makeTransaction(
26+
SurfaceId surfaceId,
27+
MountingTransaction::Number number,
28+
const std::vector<Tag>& createTags,
29+
int telemetryRevision = 0) {
30+
ShadowViewMutationList mutations;
31+
mutations.reserve(createTags.size());
32+
for (auto tag : createTags) {
33+
mutations.push_back(
34+
ShadowViewMutation::CreateMutation(makeShadowView(tag)));
35+
}
36+
TransactionTelemetry telemetry;
37+
telemetry.setRevisionNumber(telemetryRevision);
38+
return MountingTransaction{
39+
surfaceId, number, std::move(mutations), std::move(telemetry)};
40+
}
41+
42+
} // namespace
43+
44+
// Verifies that `mergeWith` concatenates mutations from the incoming
45+
// transaction after the existing ones, preserving relative order across both.
46+
// Catches regressions where the merged list is reversed, overwrites the
47+
// original, or drops mutations from either side.
48+
TEST(MountingTransactionTest, testMergeWithAppendsMutationsInOrder) {
49+
auto transaction = makeTransaction(
50+
/* surfaceId */ 1, /* number */ 1, /* tags */ {10, 11});
51+
auto incoming = makeTransaction(
52+
/* surfaceId */ 1, /* number */ 2, /* tags */ {20, 21, 22});
53+
54+
transaction.mergeWith(std::move(incoming));
55+
56+
const auto& merged = transaction.getMutations();
57+
ASSERT_EQ(merged.size(), 5u);
58+
EXPECT_EQ(merged[0].newChildShadowView.tag, 10);
59+
EXPECT_EQ(merged[1].newChildShadowView.tag, 11);
60+
EXPECT_EQ(merged[2].newChildShadowView.tag, 20);
61+
EXPECT_EQ(merged[3].newChildShadowView.tag, 21);
62+
EXPECT_EQ(merged[4].newChildShadowView.tag, 22);
63+
}
64+
65+
// Verifies that `mergeWith` advances `number` to that of the incoming
66+
// transaction while leaving `surfaceId` untouched. Catches regressions where
67+
// the number is not updated or the surfaceId is accidentally overwritten.
68+
TEST(MountingTransactionTest, testMergeWithUpdatesNumberButPreservesSurfaceId) {
69+
auto transaction = makeTransaction(
70+
/* surfaceId */ 7, /* number */ 3, /* tags */ {100});
71+
auto incoming = makeTransaction(
72+
/* surfaceId */ 7, /* number */ 42, /* tags */ {200});
73+
74+
transaction.mergeWith(std::move(incoming));
75+
76+
EXPECT_EQ(transaction.getSurfaceId(), 7);
77+
EXPECT_EQ(transaction.getNumber(), 42);
78+
}
79+
80+
// Verifies that `mergeWith` replaces the existing telemetry with that of the
81+
// incoming transaction (per the documented "use the latest instance"
82+
// behavior). We use a distinguishing revision number so the assertion checks a
83+
// computed value rather than restating a source constant.
84+
TEST(MountingTransactionTest, testMergeWithAdoptsIncomingTelemetry) {
85+
auto transaction = makeTransaction(
86+
/* surfaceId */ 1,
87+
/* number */ 1,
88+
/* tags */ {},
89+
/* telemetryRevision */ 5);
90+
auto incoming = makeTransaction(
91+
/* surfaceId */ 1,
92+
/* number */ 2,
93+
/* tags */ {},
94+
/* telemetryRevision */ 99);
95+
96+
transaction.mergeWith(std::move(incoming));
97+
98+
EXPECT_EQ(transaction.getTelemetry().getRevisionNumber(), 99);
99+
}
100+
101+
// Verifies that merging an empty incoming transaction is a no-op for the
102+
// mutation list — the existing mutations remain intact, just with the number
103+
// bumped. Guards against a naive `= std::move(other.mutations_)` implementation
104+
// that would clobber the original list.
105+
TEST(
106+
MountingTransactionTest,
107+
testMergeWithEmptyIncomingPreservesOriginalMutations) {
108+
auto transaction = makeTransaction(
109+
/* surfaceId */ 1, /* number */ 1, /* tags */ {10, 11, 12});
110+
auto incoming = makeTransaction(
111+
/* surfaceId */ 1, /* number */ 2, /* tags */ {});
112+
113+
transaction.mergeWith(std::move(incoming));
114+
115+
const auto& merged = transaction.getMutations();
116+
ASSERT_EQ(merged.size(), 3u);
117+
EXPECT_EQ(merged[0].newChildShadowView.tag, 10);
118+
EXPECT_EQ(merged[1].newChildShadowView.tag, 11);
119+
EXPECT_EQ(merged[2].newChildShadowView.tag, 12);
120+
EXPECT_EQ(transaction.getNumber(), 2);
121+
}
122+
123+
} // namespace facebook::react

0 commit comments

Comments
 (0)