From 8e6dab83501fd9745c72df73dfbd41395aa1f579 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 2 Jun 2026 03:45:31 -0700 Subject: [PATCH] Fix flaky `TaskDispatchThreadTest/RunAsyncWithDelay` timing test Summary: Replace tight `sleep_for` margins with a `std::promise`/`std::future` synchronization pattern. The old test used `sleep_for(50ms)` and `sleep_for(70ms)` to bracket a 100ms delayed task, which failed on loaded CI machines when timers fired early or late (98.7% flakiness score). The new approach uses `sleep_for(20ms)` for the "not yet executed" check (well before the 200ms delay) and `future.wait_for(5s)` for the "completed" check, eliminating timing sensitivity entirely. Changelog: [Internal] Differential Revision: D107232190 --- .../tests/TaskDispatchThreadTests.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCxxPlatform/react/threading/tests/TaskDispatchThreadTests.cpp b/packages/react-native/ReactCxxPlatform/react/threading/tests/TaskDispatchThreadTests.cpp index 13b732874b5c..99e35cd516b4 100644 --- a/packages/react-native/ReactCxxPlatform/react/threading/tests/TaskDispatchThreadTests.cpp +++ b/packages/react-native/ReactCxxPlatform/react/threading/tests/TaskDispatchThreadTests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace facebook::react { @@ -52,11 +53,19 @@ TEST_F(TaskDispatchThreadTest, RunSyncExecutesTask) { // Test: runAsync with delay TEST_F(TaskDispatchThreadTest, RunAsyncWithDelay) { std::atomic counter{0}; - dispatcher->runAsync([&] { counter++; }, std::chrono::milliseconds(100)); - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - EXPECT_EQ(counter.load(), 0); // Not yet executed - std::this_thread::sleep_for(std::chrono::milliseconds(70)); - EXPECT_EQ(counter.load(), 1); // Should be executed now + std::promise taskDone; + auto future = taskDone.get_future(); + dispatcher->runAsync( + [&] { + counter++; + taskDone.set_value(); + }, + std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + EXPECT_EQ(counter.load(), 0); // 20ms << 200ms, not yet executed + ASSERT_EQ( + future.wait_for(std::chrono::seconds(5)), std::future_status::ready); + EXPECT_EQ(counter.load(), 1); // Task completed } // Test: Multiple delayed tasks execute in order