Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / startup_task_runner_unittest.cc
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.
4
5 #include "content/browser/startup_task_runner.h"
6
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"
13
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace content {
18 namespace {
19
20 using base::Closure;
21 using testing::_;
22 using testing::Assign;
23 using testing::Invoke;
24 using testing::WithArg;
25
26 int observer_calls = 0;
27 int task_count = 0;
28 int observer_result;
29 base::Closure task;
30
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;
36 }
37
38 void Observer(int result) {
39   observer_calls++;
40   observer_result = result;
41 }
42
43 class StartupTaskRunnerTest : public testing::Test {
44  public:
45   void SetUp() override {
46     last_task_ = 0;
47     observer_calls = 0;
48     task_count = 0;
49   }
50
51   int Task1() {
52     last_task_ = 1;
53     task_count++;
54     return 0;
55   }
56
57   int Task2() {
58     last_task_ = 2;
59     task_count++;
60     return 0;
61   }
62
63   int FailingTask() {
64     // Task returning failure
65     last_task_ = 3;
66     task_count++;
67     return 1;
68   }
69
70   int GetLastTask() { return last_task_; }
71
72  private:
73
74   int last_task_;
75 };
76
77 // We can't use the real message loop, even if we want to, since doing so on
78 // Android requires a complex Java infrastructure. The test would have to built
79 // as a content_shell test; but content_shell startup invokes the class we are
80 // trying to test.
81 //
82 // The mocks are not directly in TaskRunnerProxy because reference counted
83 // objects seem to confuse the mocking framework
84
85 class MockTaskRunner {
86  public:
87   MOCK_METHOD3(
88       PostDelayedTask,
89       bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
90   MOCK_METHOD3(
91       PostNonNestableDelayedTask,
92       bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
93 };
94
95 class TaskRunnerProxy : public base::SingleThreadTaskRunner {
96  public:
97   TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
98   bool RunsTasksOnCurrentThread() const override { return true; }
99   bool PostDelayedTask(const tracked_objects::Location& location,
100                        const Closure& closure,
101                        base::TimeDelta delta) override {
102     return mock_->PostDelayedTask(location, closure, delta);
103   }
104   bool PostNonNestableDelayedTask(const tracked_objects::Location& location,
105                                   const Closure& closure,
106                                   base::TimeDelta delta) override {
107     return mock_->PostNonNestableDelayedTask(location, closure, delta);
108   }
109
110  private:
111   MockTaskRunner* mock_;
112   ~TaskRunnerProxy() override {}
113 };
114
115 TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
116   MockTaskRunner mock_runner;
117   scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
118
119   EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
120   EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
121
122   StartupTaskRunner runner(base::Bind(&Observer), proxy);
123
124   StartupTask task1 =
125       base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
126   runner.AddTask(task1);
127   EXPECT_EQ(GetLastTask(), 0);
128   StartupTask task2 =
129       base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
130   runner.AddTask(task2);
131
132   // Nothing should run until we tell them to.
133   EXPECT_EQ(GetLastTask(), 0);
134   runner.RunAllTasksNow();
135
136   // On an immediate StartupTaskRunner the tasks should now all have run.
137   EXPECT_EQ(GetLastTask(), 2);
138
139   EXPECT_EQ(task_count, 2);
140   EXPECT_EQ(observer_calls, 1);
141   EXPECT_EQ(observer_result, 0);
142
143   // Running the tasks asynchronously shouldn't do anything
144   // In particular Post... should not be called
145   runner.StartRunningTasksAsync();
146
147   // No more tasks should be run and the observer should not have been called
148   // again
149   EXPECT_EQ(task_count, 2);
150   EXPECT_EQ(observer_calls, 1);
151 }
152
153 TEST_F(StartupTaskRunnerTest, NullObserver) {
154   MockTaskRunner mock_runner;
155   scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
156
157   EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
158   EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
159
160   StartupTaskRunner runner(base::Callback<void(int)>(), proxy);
161
162   StartupTask task1 =
163       base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
164   runner.AddTask(task1);
165   EXPECT_EQ(GetLastTask(), 0);
166   StartupTask task2 =
167       base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
168   runner.AddTask(task2);
169
170   // Nothing should run until we tell them to.
171   EXPECT_EQ(GetLastTask(), 0);
172   runner.RunAllTasksNow();
173
174   // On an immediate StartupTaskRunner the tasks should now all have run.
175   EXPECT_EQ(GetLastTask(), 2);
176   EXPECT_EQ(task_count, 2);
177
178   // Running the tasks asynchronously shouldn't do anything
179   // In particular Post... should not be called
180   runner.StartRunningTasksAsync();
181
182   // No more tasks should have been run
183   EXPECT_EQ(task_count, 2);
184
185   EXPECT_EQ(observer_calls, 0);
186 }
187
188 TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
189   MockTaskRunner mock_runner;
190   scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
191
192   EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
193   EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
194
195   StartupTaskRunner runner(base::Bind(&Observer), proxy);
196
197   StartupTask task3 =
198       base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
199   runner.AddTask(task3);
200   EXPECT_EQ(GetLastTask(), 0);
201   StartupTask task2 =
202       base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
203   runner.AddTask(task2);
204
205   // Nothing should run until we tell them to.
206   EXPECT_EQ(GetLastTask(), 0);
207   runner.RunAllTasksNow();
208
209   // Only the first task should have run, since it failed
210   EXPECT_EQ(GetLastTask(), 3);
211   EXPECT_EQ(task_count, 1);
212   EXPECT_EQ(observer_calls, 1);
213   EXPECT_EQ(observer_result, 1);
214
215   // After a failed task all remaining tasks should be cancelled
216   // In particular Post... should not be called by running asynchronously
217   runner.StartRunningTasksAsync();
218
219   // The observer should only be called the first time the queue completes and
220   // no more tasks should have run
221   EXPECT_EQ(observer_calls, 1);
222   EXPECT_EQ(task_count, 1);
223 }
224
225 TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
226
227   MockTaskRunner mock_runner;
228   scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
229
230   EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
231   EXPECT_CALL(
232       mock_runner,
233       PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
234       .Times(testing::Between(2, 3))
235       .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
236
237   StartupTaskRunner runner(base::Bind(&Observer), proxy);
238
239   StartupTask task1 =
240       base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
241   runner.AddTask(task1);
242   StartupTask task2 =
243       base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
244   runner.AddTask(task2);
245
246   // Nothing should run until we tell them to.
247   EXPECT_EQ(GetLastTask(), 0);
248   runner.StartRunningTasksAsync();
249
250   // No tasks should have run yet, since we the message loop hasn't run.
251   EXPECT_EQ(GetLastTask(), 0);
252
253   // Fake the actual message loop. Each time a task is run a new task should
254   // be added to the queue, hence updating "task". The loop should actually run
255   // at most 3 times (once for each task plus possibly once for the observer),
256   // the "4" is a backstop.
257   for (int i = 0; i < 4 && observer_calls == 0; i++) {
258     task.Run();
259     EXPECT_EQ(i + 1, GetLastTask());
260   }
261   EXPECT_EQ(task_count, 2);
262   EXPECT_EQ(observer_calls, 1);
263   EXPECT_EQ(observer_result, 0);
264
265   // Check that running synchronously now doesn't do anything
266
267   runner.RunAllTasksNow();
268   EXPECT_EQ(task_count, 2);
269   EXPECT_EQ(observer_calls, 1);
270 }
271
272 TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
273
274   MockTaskRunner mock_runner;
275   scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
276
277   EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
278   EXPECT_CALL(
279       mock_runner,
280       PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
281       .Times(testing::Between(1, 2))
282       .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
283
284   StartupTaskRunner runner(base::Bind(&Observer), proxy);
285
286   StartupTask task3 =
287       base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
288   runner.AddTask(task3);
289   StartupTask task2 =
290       base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
291   runner.AddTask(task2);
292
293   // Nothing should run until we tell them to.
294   EXPECT_EQ(GetLastTask(), 0);
295   runner.StartRunningTasksAsync();
296
297   // No tasks should have run yet, since we the message loop hasn't run.
298   EXPECT_EQ(GetLastTask(), 0);
299
300   // Fake the actual message loop. Each time a task is run a new task should
301   // be added to the queue, hence updating "task". The loop should actually run
302   // at most twice (once for the failed task plus possibly once for the
303   // observer), the "4" is a backstop.
304   for (int i = 0; i < 4 && observer_calls == 0; i++) {
305     task.Run();
306   }
307   EXPECT_EQ(GetLastTask(), 3);
308   EXPECT_EQ(task_count, 1);
309
310   EXPECT_EQ(observer_calls, 1);
311   EXPECT_EQ(observer_result, 1);
312
313   // Check that running synchronously now doesn't do anything
314   runner.RunAllTasksNow();
315   EXPECT_EQ(observer_calls, 1);
316   EXPECT_EQ(task_count, 1);
317 }
318 }  // namespace
319 }  // namespace content