1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/test/run_until.h" 6 7 #include <functional> 8 9 #include "base/functional/callback.h" 10 #include "base/functional/callback_forward.h" 11 #include "base/task/current_thread.h" 12 #include "base/test/scoped_run_loop_timeout.h" 13 #include "base/test/test_future.h" 14 #include "base/time/time_override.h" 15 16 namespace base::test { 17 18 namespace { 19 TestPredicateOrRegisterOnNextIdleCallback(base::FunctionRef<bool (void)> condition,OnceClosure ready_callback)20void TestPredicateOrRegisterOnNextIdleCallback( 21 base::FunctionRef<bool(void)> condition, 22 OnceClosure ready_callback) { 23 if (condition()) { 24 // Invoke `ready_callback` if `condition` evaluates to true. 25 std::move(ready_callback).Run(); 26 } else { 27 // Otherwise try again the next time the thread is idle. 28 CurrentThread::Get().RegisterOnNextIdleCallback( 29 BindOnce(TestPredicateOrRegisterOnNextIdleCallback, condition, 30 std::move(ready_callback))); 31 } 32 } 33 34 } // namespace 35 RunUntil(base::FunctionRef<bool (void)> condition)36bool RunUntil(base::FunctionRef<bool(void)> condition) { 37 CHECK(!subtle::ScopedTimeClockOverrides::overrides_active()) 38 << "Mocked timesource detected, which would cause `RunUntil` to hang " 39 "forever on failure."; 40 CHECK(test::ScopedRunLoopTimeout::ExistsForCurrentThread()) 41 << "No RunLoop timeout set, meaning `RunUntil` will hang forever on " 42 "failure."; 43 44 test::TestFuture<void> ready_signal; 45 46 CurrentThread::Get().RegisterOnNextIdleCallback( 47 BindOnce(TestPredicateOrRegisterOnNextIdleCallback, condition, 48 ready_signal.GetCallback())); 49 50 return ready_signal.Wait(); 51 } 52 53 } // namespace base::test 54