• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 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#import "base/test/ios/wait_util.h"
6
7#import <Foundation/Foundation.h>
8
9#include "base/check.h"
10#include "base/mac/scoped_nsobject.h"
11#include "base/run_loop.h"
12#include "base/test/test_timeouts.h"
13#include "base/timer/elapsed_timer.h"
14
15namespace base {
16namespace test {
17namespace ios {
18
19bool WaitUntilConditionOrTimeout(TimeDelta timeout, ConditionBlock condition) {
20  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:timeout.InSecondsF()];
21  bool success = condition();
22  while (!success && [[NSDate date] compare:deadline] != NSOrderedDescending) {
23    base::test::ios::SpinRunLoopWithMaxDelay(kSpinDelaySeconds);
24    success = condition();
25  }
26  return success;
27}
28
29TimeDelta TimeUntilCondition(ProceduralBlock action,
30                             ConditionBlock condition,
31                             bool run_message_loop,
32                             TimeDelta timeout) {
33  ElapsedTimer timer;
34  if (action)
35    action();
36  if (timeout.is_zero())
37    timeout = TestTimeouts::action_timeout();
38  constexpr TimeDelta kSpinDelay(Milliseconds(10));
39  bool condition_evaluation_result = false;
40  while (timer.Elapsed() < timeout &&
41         (!condition || !(condition_evaluation_result = condition()))) {
42    SpinRunLoopWithMaxDelay(kSpinDelay);
43    if (run_message_loop)
44      RunLoop().RunUntilIdle();
45  }
46  const TimeDelta elapsed = timer.Elapsed();
47  // If DCHECK is ever hit, check if |action| is doing something that is
48  // taking an unreasonably long time, or if |condition| does not come
49  // true quickly enough. Increase |timeout| only if necessary.
50  DCHECK(!condition || condition_evaluation_result);
51  return elapsed;
52}
53
54void WaitUntilCondition(ConditionBlock condition,
55                        bool run_message_loop,
56                        TimeDelta timeout) {
57  TimeUntilCondition(nil, condition, run_message_loop, timeout);
58}
59
60void WaitUntilCondition(ConditionBlock condition) {
61  WaitUntilCondition(condition, false, TimeDelta());
62}
63
64void SpinRunLoopWithMaxDelay(TimeDelta max_delay) {
65  scoped_nsobject<NSDate> beforeDate(
66      [[NSDate alloc] initWithTimeIntervalSinceNow:max_delay.InSecondsF()]);
67  [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
68                           beforeDate:beforeDate];
69}
70
71void SpinRunLoopWithMinDelay(TimeDelta min_delay) {
72  ElapsedTimer timer;
73  while (timer.Elapsed() < min_delay) {
74    SpinRunLoopWithMaxDelay(Milliseconds(10));
75  }
76}
77
78}  // namespace ios
79}  // namespace test
80}  // namespace base
81