Update optimize_png_files.sh to work on msysgit bash.
[chromium-blink-merge.git] / content / browser / startup_task_runner_unittest.cc
blobfcd2b3d1da64eefc89a56cb7ff1880fbce8892f8
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/startup_task_runner.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/location.h"
11 #include "base/run_loop.h"
12 #include "base/task_runner.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace content {
18 namespace {
20 using base::Closure;
21 using testing::_;
22 using testing::Assign;
23 using testing::Invoke;
24 using testing::WithArg;
26 int observer_calls = 0;
27 int task_count = 0;
28 int observer_result;
29 base::Closure task;
31 // I couldn't get gMock's SaveArg to compile, hence had to save the argument
32 // this way
33 bool SaveTaskArg(const Closure& arg) {
34 task = arg;
35 return true;
38 void Observer(int result) {
39 observer_calls++;
40 observer_result = result;
43 class StartupTaskRunnerTest : public testing::Test {
44 public:
46 virtual void SetUp() {
47 last_task_ = 0;
48 observer_calls = 0;
49 task_count = 0;
52 int Task1() {
53 last_task_ = 1;
54 task_count++;
55 return 0;
58 int Task2() {
59 last_task_ = 2;
60 task_count++;
61 return 0;
64 int FailingTask() {
65 // Task returning failure
66 last_task_ = 3;
67 task_count++;
68 return 1;
71 int GetLastTask() { return last_task_; }
73 private:
75 int last_task_;
78 // We can't use the real message loop, even if we want to, since doing so on
79 // Android requires a complex Java infrastructure. The test would have to built
80 // as a content_shell test; but content_shell startup invokes the class we are
81 // trying to test.
83 // The mocks are not directly in TaskRunnerProxy because reference counted
84 // objects seem to confuse the mocking framework
86 class MockTaskRunner {
87 public:
88 MOCK_METHOD3(
89 PostDelayedTask,
90 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
91 MOCK_METHOD3(
92 PostNonNestableDelayedTask,
93 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
96 class TaskRunnerProxy : public base::SingleThreadTaskRunner {
97 public:
98 TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
99 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { return true; }
100 virtual bool PostDelayedTask(const tracked_objects::Location& location,
101 const Closure& closure,
102 base::TimeDelta delta) OVERRIDE {
103 return mock_->PostDelayedTask(location, closure, delta);
105 virtual bool PostNonNestableDelayedTask(
106 const tracked_objects::Location& location,
107 const Closure& closure,
108 base::TimeDelta delta) OVERRIDE {
109 return mock_->PostNonNestableDelayedTask(location, closure, delta);
112 private:
113 MockTaskRunner* mock_;
114 virtual ~TaskRunnerProxy() {}
117 TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
118 MockTaskRunner mock_runner;
119 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
121 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
122 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
124 StartupTaskRunner runner(base::Bind(&Observer), proxy);
126 StartupTask task1 =
127 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
128 runner.AddTask(task1);
129 EXPECT_EQ(GetLastTask(), 0);
130 StartupTask task2 =
131 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
132 runner.AddTask(task2);
134 // Nothing should run until we tell them to.
135 EXPECT_EQ(GetLastTask(), 0);
136 runner.RunAllTasksNow();
138 // On an immediate StartupTaskRunner the tasks should now all have run.
139 EXPECT_EQ(GetLastTask(), 2);
141 EXPECT_EQ(task_count, 2);
142 EXPECT_EQ(observer_calls, 1);
143 EXPECT_EQ(observer_result, 0);
145 // Running the tasks asynchronously shouldn't do anything
146 // In particular Post... should not be called
147 runner.StartRunningTasksAsync();
149 // No more tasks should be run and the observer should not have been called
150 // again
151 EXPECT_EQ(task_count, 2);
152 EXPECT_EQ(observer_calls, 1);
155 TEST_F(StartupTaskRunnerTest, NullObserver) {
156 MockTaskRunner mock_runner;
157 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
159 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
160 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
162 StartupTaskRunner runner(base::Callback<void(int)>(), proxy);
164 StartupTask task1 =
165 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
166 runner.AddTask(task1);
167 EXPECT_EQ(GetLastTask(), 0);
168 StartupTask task2 =
169 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
170 runner.AddTask(task2);
172 // Nothing should run until we tell them to.
173 EXPECT_EQ(GetLastTask(), 0);
174 runner.RunAllTasksNow();
176 // On an immediate StartupTaskRunner the tasks should now all have run.
177 EXPECT_EQ(GetLastTask(), 2);
178 EXPECT_EQ(task_count, 2);
180 // Running the tasks asynchronously shouldn't do anything
181 // In particular Post... should not be called
182 runner.StartRunningTasksAsync();
184 // No more tasks should have been run
185 EXPECT_EQ(task_count, 2);
187 EXPECT_EQ(observer_calls, 0);
190 TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
191 MockTaskRunner mock_runner;
192 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
194 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
195 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
197 StartupTaskRunner runner(base::Bind(&Observer), proxy);
199 StartupTask task3 =
200 base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
201 runner.AddTask(task3);
202 EXPECT_EQ(GetLastTask(), 0);
203 StartupTask task2 =
204 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
205 runner.AddTask(task2);
207 // Nothing should run until we tell them to.
208 EXPECT_EQ(GetLastTask(), 0);
209 runner.RunAllTasksNow();
211 // Only the first task should have run, since it failed
212 EXPECT_EQ(GetLastTask(), 3);
213 EXPECT_EQ(task_count, 1);
214 EXPECT_EQ(observer_calls, 1);
215 EXPECT_EQ(observer_result, 1);
217 // After a failed task all remaining tasks should be cancelled
218 // In particular Post... should not be called by running asynchronously
219 runner.StartRunningTasksAsync();
221 // The observer should only be called the first time the queue completes and
222 // no more tasks should have run
223 EXPECT_EQ(observer_calls, 1);
224 EXPECT_EQ(task_count, 1);
227 TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
229 MockTaskRunner mock_runner;
230 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
232 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
233 EXPECT_CALL(
234 mock_runner,
235 PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
236 .Times(testing::Between(2, 3))
237 .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
239 StartupTaskRunner runner(base::Bind(&Observer), proxy);
241 StartupTask task1 =
242 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
243 runner.AddTask(task1);
244 StartupTask task2 =
245 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
246 runner.AddTask(task2);
248 // Nothing should run until we tell them to.
249 EXPECT_EQ(GetLastTask(), 0);
250 runner.StartRunningTasksAsync();
252 // No tasks should have run yet, since we the message loop hasn't run.
253 EXPECT_EQ(GetLastTask(), 0);
255 // Fake the actual message loop. Each time a task is run a new task should
256 // be added to the queue, hence updating "task". The loop should actually run
257 // at most 3 times (once for each task plus possibly once for the observer),
258 // the "4" is a backstop.
259 for (int i = 0; i < 4 && observer_calls == 0; i++) {
260 task.Run();
261 EXPECT_EQ(i + 1, GetLastTask());
263 EXPECT_EQ(task_count, 2);
264 EXPECT_EQ(observer_calls, 1);
265 EXPECT_EQ(observer_result, 0);
267 // Check that running synchronously now doesn't do anything
269 runner.RunAllTasksNow();
270 EXPECT_EQ(task_count, 2);
271 EXPECT_EQ(observer_calls, 1);
274 TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
276 MockTaskRunner mock_runner;
277 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
279 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
280 EXPECT_CALL(
281 mock_runner,
282 PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
283 .Times(testing::Between(1, 2))
284 .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
286 StartupTaskRunner runner(base::Bind(&Observer), proxy);
288 StartupTask task3 =
289 base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
290 runner.AddTask(task3);
291 StartupTask task2 =
292 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
293 runner.AddTask(task2);
295 // Nothing should run until we tell them to.
296 EXPECT_EQ(GetLastTask(), 0);
297 runner.StartRunningTasksAsync();
299 // No tasks should have run yet, since we the message loop hasn't run.
300 EXPECT_EQ(GetLastTask(), 0);
302 // Fake the actual message loop. Each time a task is run a new task should
303 // be added to the queue, hence updating "task". The loop should actually run
304 // at most twice (once for the failed task plus possibly once for the
305 // observer), the "4" is a backstop.
306 for (int i = 0; i < 4 && observer_calls == 0; i++) {
307 task.Run();
309 EXPECT_EQ(GetLastTask(), 3);
310 EXPECT_EQ(task_count, 1);
312 EXPECT_EQ(observer_calls, 1);
313 EXPECT_EQ(observer_result, 1);
315 // Check that running synchronously now doesn't do anything
316 runner.RunAllTasksNow();
317 EXPECT_EQ(observer_calls, 1);
318 EXPECT_EQ(task_count, 1);
320 } // namespace
321 } // namespace content