summaryrefslogtreecommitdiffstats
path: root/cc/test/ordered_simple_task_runner.h
blob: 91ea4be75cdc67f99e607ff90af27bb3cf2171c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
#define CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_

#include <limits>
#include <set>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_simple_task_runner.h"
#include "base/trace_event/trace_event.h"

namespace cc {

// Subclass of TestPendingTask which has a unique ID for every task, supports
// being used inside a std::set and has debug tracing support.
class TestOrderablePendingTask : public base::TestPendingTask {
 public:
  TestOrderablePendingTask();
  TestOrderablePendingTask(const tracked_objects::Location& location,
                           const base::Closure& task,
                           base::TimeTicks post_time,
                           base::TimeDelta delay,
                           TestNestability nestability);
  ~TestOrderablePendingTask();

  // operators needed by std::set and comparison
  bool operator==(const TestOrderablePendingTask& other) const;
  bool operator<(const TestOrderablePendingTask& other) const;

  // base::trace_event tracing functionality
  scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
  void AsValueInto(base::trace_event::TracedValue* state) const;

 private:
  static size_t task_id_counter;
  const size_t task_id_;
};

// This runs pending tasks based on task's post_time + delay.
// We should not execute a delayed task sooner than some of the queued tasks
// which don't have a delay even though it is queued early.
class OrderedSimpleTaskRunner : public base::SingleThreadTaskRunner {
 public:
  OrderedSimpleTaskRunner(base::SimpleTestTickClock* now_src, bool advance_now);

  // base::TestSimpleTaskRunner implementation:
  bool PostDelayedTask(const tracked_objects::Location& from_here,
                       const base::Closure& task,
                       base::TimeDelta delay) override;
  bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
                                  const base::Closure& task,
                                  base::TimeDelta delay) override;

  bool RunsTasksOnCurrentThread() const override;

  static base::TimeTicks AbsoluteMaxNow();

  // Set a maximum number of tasks to run at once. Useful as a timeout to
  // prevent infinite task loops.
  static const size_t kAbsoluteMaxTasks;
  void SetRunTaskLimit(size_t max_tasks) { max_tasks_ = max_tasks; }
  void ClearRunTaskLimit() { max_tasks_ = kAbsoluteMaxTasks; }

  // Allow task runner to advance now when running tasks.
  void SetAutoAdvanceNowToPendingTasks(bool advance_now) {
    advance_now_ = advance_now;
  }

  size_t NumPendingTasks() const;
  bool HasPendingTasks() const;
  base::TimeTicks NextTaskTime();
  base::TimeDelta DelayToNextTaskTime();

  // Run tasks while the callback returns true or too many tasks have been run.
  // Returns true if there are still pending tasks left.
  bool RunTasksWhile(base::Callback<bool(void)> condition);

  // Run tasks while *all* of the callbacks return true or too many tasks have
  // been run. Exits on the *first* condition which returns false, skipping
  // calling all remaining conditions. Conditions can have side effects,
  // including modifying the task queue.
  // Returns true if there are still pending tasks left.
  bool RunTasksWhile(const std::vector<base::Callback<bool(void)>>& conditions);

  // Convenience functions to run tasks with common conditions.

  // Run tasks which existed at the start of this call.
  // Return code indicates tasks still exist to run.
  bool RunPendingTasks();
  // Keep running tasks until no tasks are left.
  // Return code indicates tasks still exist to run which also indicates if
  // runner reached idle.
  bool RunUntilIdle();
  // Keep running tasks until given time period.
  // Return code indicates tasks still exist to run.
  bool RunUntilTime(base::TimeTicks time);
  bool RunForPeriod(base::TimeDelta period);

  // base::trace_event tracing functionality
  scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
  virtual void AsValueInto(base::trace_event::TracedValue* state) const;

  // Common conditions to run for, exposed publicly to allow external users to
  // use their own combinations.
  // -------------------------------------------------------------------------

  // Keep running until the given number of tasks have run.
  // You generally shouldn't use this check as it will cause your tests to fail
  // when code is changed adding a new task. It is useful as a "timeout" type
  // solution.
  base::Callback<bool(void)> TaskRunCountBelow(size_t max_tasks);

  // Keep running until a task which didn't exist initially would run.
  base::Callback<bool(void)> TaskExistedInitially();

  // Stop running tasks when NextTaskTime() >= stop_at
  base::Callback<bool(void)> NowBefore(base::TimeTicks stop_at);

  // Advance Now() to the next task to run.
  base::Callback<bool(void)> AdvanceNow();

 protected:
  static bool TaskRunCountBelowCallback(size_t max_tasks, size_t* task_run);
  bool TaskExistedInitiallyCallback(
      const std::set<TestOrderablePendingTask>& existing_tasks);
  bool NowBeforeCallback(base::TimeTicks stop_at);
  bool AdvanceNowCallback();

  ~OrderedSimpleTaskRunner() override;

  base::ThreadChecker thread_checker_;

  bool advance_now_;
  // Not owned.
  base::SimpleTestTickClock* now_src_;

  size_t max_tasks_;

  bool inside_run_tasks_until_;
  std::set<TestOrderablePendingTask> pending_tasks_;

 private:
  DISALLOW_COPY_AND_ASSIGN(OrderedSimpleTaskRunner);
};

}  // namespace cc

#endif  // CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_