From 6b0dd30c69b965a7e3e9edfb182f50c6743cd751 Mon Sep 17 00:00:00 2001 From: DevmateUtgenCppGeneralFBOrg Bot Date: Tue, 8 Sep 2026 03:10:59 -0700 Subject: [PATCH] xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/jni/react/fabric/AndroidEventBeat.cpp Reviewed By: cortinico Differential Revision: D119132731 --- .../fabric/test/AndroidEventBeatTest.cpp | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/fabric/test/AndroidEventBeatTest.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/test/AndroidEventBeatTest.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/test/AndroidEventBeatTest.cpp new file mode 100644 index 000000000000..954a711883fb --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/test/AndroidEventBeatTest.cpp @@ -0,0 +1,137 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace facebook::react { + +class EventBeatTestAccess : public EventBeat { + public: + using EventBeat::EventBeat; + + static void markRequested(EventBeat& eventBeat) { + eventBeat.*requestedMember() = true; + } + + private: + static std::atomic EventBeat::* requestedMember() { + return &EventBeatTestAccess::isEventBeatRequested_; + } +}; + +class AndroidEventBeatTestFeatureFlags + : public ReactNativeFeatureFlagsDefaults { + public: + bool enableBridgelessArchitecture() override { + return false; + } +}; + +class AndroidEventBeatTest : public ::testing::Test { + protected: + void SetUp() override { + ReactNativeFeatureFlags::dangerouslyReset(); + ReactNativeFeatureFlags::override( + std::make_unique()); + + runtime_ = facebook::hermes::makeHermesRuntime(); + runtimeScheduler_ = std::make_unique( + [this](std::function&& callback) { + callback(*runtime_); + }); + } + + void TearDown() override { + runtimeScheduler_.reset(); + runtime_.reset(); + ReactNativeFeatureFlags::dangerouslyReset(); + } + + std::unique_ptr makeEventBeat( + std::shared_ptr owner) { + auto ownerBox = std::make_shared(); + ownerBox->owner = owner; + return std::make_unique( + std::move(ownerBox), + &eventBeatManager_, + *runtimeScheduler_, + jni::global_ref{}); + } + + EventBeatManager eventBeatManager_; + std::unique_ptr runtime_; + std::unique_ptr runtimeScheduler_; +}; + +TEST_F(AndroidEventBeatTest, testTickRunsCallbackForPendingBeat) { + auto owner = std::make_shared(1); + auto eventBeat = makeEventBeat(owner); + std::vector calls; + + eventBeat->unstable_setInduceCallback( + [&calls]() { calls.push_back("induce"); }); + eventBeat->setBeatCallback([&](jsi::Runtime& runtime) { + EXPECT_EQ(&runtime, runtime_.get()); + calls.push_back("beat"); + }); + + EventBeatTestAccess::markRequested(*eventBeat); + eventBeat->tick(); + + EXPECT_EQ(calls, (std::vector{"induce", "beat"})); +} + +TEST_F(AndroidEventBeatTest, testTickConsumesOnlyOnePendingBeat) { + auto owner = std::make_shared(1); + auto eventBeat = makeEventBeat(owner); + int beatCallbackCount = 0; + int induceCallbackCount = 0; + + eventBeat->unstable_setInduceCallback( + [&induceCallbackCount]() { ++induceCallbackCount; }); + eventBeat->setBeatCallback( + [&beatCallbackCount](jsi::Runtime& /*runtime*/) { ++beatCallbackCount; }); + + EventBeatTestAccess::markRequested(*eventBeat); + eventBeat->tick(); + eventBeat->tick(); + + EXPECT_EQ(induceCallbackCount, 1); + EXPECT_EQ(beatCallbackCount, 1); +} + +TEST_F(AndroidEventBeatTest, testTickDoesNotRunBeatCallbackAfterOwnerExpires) { + auto owner = std::make_shared(1); + auto eventBeat = makeEventBeat(owner); + int induceCallbackCount = 0; + int beatCallbackCount = 0; + + eventBeat->unstable_setInduceCallback( + [&induceCallbackCount]() { ++induceCallbackCount; }); + eventBeat->setBeatCallback( + [&beatCallbackCount](jsi::Runtime& /*runtime*/) { ++beatCallbackCount; }); + + EventBeatTestAccess::markRequested(*eventBeat); + owner.reset(); + eventBeat->tick(); + + EXPECT_EQ(induceCallbackCount, 1); + EXPECT_EQ(beatCallbackCount, 0); +} + +} // namespace facebook::react