OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/startup_task_runner.h" | 5 #include "content/browser/startup_task_runner.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
12 #include "base/task_runner.h" | 12 #include "base/task_runner.h" |
13 | 13 |
14 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
16 | 16 |
17 namespace content { | 17 namespace content { |
18 namespace { | 18 namespace { |
19 | 19 |
20 using base::Closure; | 20 using base::Closure; |
21 using testing::_; | 21 using testing::_; |
22 using testing::Assign; | 22 using testing::Assign; |
23 using testing::Invoke; | 23 using testing::Invoke; |
24 using testing::WithArg; | 24 using testing::WithArg; |
25 | 25 |
26 bool observer_called = false; | 26 int observer_calls = 0; |
| 27 int task_count = 0; |
27 int observer_result; | 28 int observer_result; |
28 base::Closure task; | 29 base::Closure task; |
29 | 30 |
30 // I couldn't get gMock's SaveArg to compile, hence had to save the argument | 31 // I couldn't get gMock's SaveArg to compile, hence had to save the argument |
31 // this way | 32 // this way |
32 bool SaveTaskArg(const Closure& arg) { | 33 bool SaveTaskArg(const Closure& arg) { |
33 task = arg; | 34 task = arg; |
34 return true; | 35 return true; |
35 } | 36 } |
36 | 37 |
37 void Observer(int result) { | 38 void Observer(int result) { |
38 observer_called = true; | 39 observer_calls++; |
39 observer_result = result; | 40 observer_result = result; |
40 } | 41 } |
41 | 42 |
42 class StartupTaskRunnerTest : public testing::Test { | 43 class StartupTaskRunnerTest : public testing::Test { |
43 public: | 44 public: |
44 | 45 |
45 virtual void SetUp() { | 46 virtual void SetUp() { |
46 last_task_ = 0; | 47 last_task_ = 0; |
47 observer_called = false; | 48 observer_calls = 0; |
| 49 task_count = 0; |
48 } | 50 } |
49 | 51 |
50 int Task1() { | 52 int Task1() { |
51 last_task_ = 1; | 53 last_task_ = 1; |
| 54 task_count++; |
52 return 0; | 55 return 0; |
53 } | 56 } |
54 | 57 |
55 int Task2() { | 58 int Task2() { |
56 last_task_ = 2; | 59 last_task_ = 2; |
| 60 task_count++; |
57 return 0; | 61 return 0; |
58 } | 62 } |
59 | 63 |
60 int FailingTask() { | 64 int FailingTask() { |
61 // Task returning failure | 65 // Task returning failure |
62 last_task_ = 3; | 66 last_task_ = 3; |
| 67 task_count++; |
63 return 1; | 68 return 1; |
64 } | 69 } |
65 | 70 |
66 int GetLastTask() { return last_task_; } | 71 int GetLastTask() { return last_task_; } |
67 | 72 |
68 private: | 73 private: |
69 | 74 |
70 int last_task_; | 75 int last_task_; |
71 }; | 76 }; |
72 | 77 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); | 131 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); |
127 runner.AddTask(task2); | 132 runner.AddTask(task2); |
128 | 133 |
129 // Nothing should run until we tell them to. | 134 // Nothing should run until we tell them to. |
130 EXPECT_EQ(GetLastTask(), 0); | 135 EXPECT_EQ(GetLastTask(), 0); |
131 runner.RunAllTasksNow(); | 136 runner.RunAllTasksNow(); |
132 | 137 |
133 // On an immediate StartupTaskRunner the tasks should now all have run. | 138 // On an immediate StartupTaskRunner the tasks should now all have run. |
134 EXPECT_EQ(GetLastTask(), 2); | 139 EXPECT_EQ(GetLastTask(), 2); |
135 | 140 |
136 EXPECT_TRUE(observer_called); | 141 EXPECT_EQ(task_count, 2); |
| 142 EXPECT_EQ(observer_calls, 1); |
137 EXPECT_EQ(observer_result, 0); | 143 EXPECT_EQ(observer_result, 0); |
| 144 |
| 145 // Running the tasks asynchronously shouldn't do anything |
| 146 // In particular Post... should not be called |
| 147 runner.StartRunningTasksAsync(); |
| 148 |
| 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); |
138 } | 153 } |
139 | 154 |
140 TEST_F(StartupTaskRunnerTest, NullObserver) { | 155 TEST_F(StartupTaskRunnerTest, NullObserver) { |
141 MockTaskRunner mock_runner; | 156 MockTaskRunner mock_runner; |
142 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); | 157 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); |
143 | 158 |
144 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); | 159 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); |
145 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0); | 160 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0); |
146 | 161 |
147 StartupTaskRunner runner(base::Callback<void(int)>(), proxy); | 162 StartupTaskRunner runner(base::Callback<void(int)>(), proxy); |
148 | 163 |
149 StartupTask task1 = | 164 StartupTask task1 = |
150 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this)); | 165 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this)); |
151 runner.AddTask(task1); | 166 runner.AddTask(task1); |
152 EXPECT_EQ(GetLastTask(), 0); | 167 EXPECT_EQ(GetLastTask(), 0); |
153 StartupTask task2 = | 168 StartupTask task2 = |
154 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); | 169 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); |
155 runner.AddTask(task2); | 170 runner.AddTask(task2); |
156 | 171 |
157 // Nothing should run until we tell them to. | 172 // Nothing should run until we tell them to. |
158 EXPECT_EQ(GetLastTask(), 0); | 173 EXPECT_EQ(GetLastTask(), 0); |
159 runner.RunAllTasksNow(); | 174 runner.RunAllTasksNow(); |
160 | 175 |
161 // On an immediate StartupTaskRunner the tasks should now all have run. | 176 // On an immediate StartupTaskRunner the tasks should now all have run. |
162 EXPECT_EQ(GetLastTask(), 2); | 177 EXPECT_EQ(GetLastTask(), 2); |
| 178 EXPECT_EQ(task_count, 2); |
163 | 179 |
164 EXPECT_FALSE(observer_called); | 180 // Running the tasks asynchronously shouldn't do anything |
| 181 // In particular Post... should not be called |
| 182 runner.StartRunningTasksAsync(); |
| 183 |
| 184 // No more tasks should have been run |
| 185 EXPECT_EQ(task_count, 2); |
| 186 |
| 187 EXPECT_EQ(observer_calls, 0); |
165 } | 188 } |
166 | 189 |
167 TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) { | 190 TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) { |
168 MockTaskRunner mock_runner; | 191 MockTaskRunner mock_runner; |
169 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); | 192 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); |
170 | 193 |
171 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); | 194 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); |
172 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0); | 195 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0); |
173 | 196 |
174 StartupTaskRunner runner(base::Bind(&Observer), proxy); | 197 StartupTaskRunner runner(base::Bind(&Observer), proxy); |
175 | 198 |
176 StartupTask task3 = | 199 StartupTask task3 = |
177 base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this)); | 200 base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this)); |
178 runner.AddTask(task3); | 201 runner.AddTask(task3); |
179 EXPECT_EQ(GetLastTask(), 0); | 202 EXPECT_EQ(GetLastTask(), 0); |
180 StartupTask task2 = | 203 StartupTask task2 = |
181 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); | 204 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this)); |
182 runner.AddTask(task2); | 205 runner.AddTask(task2); |
183 | 206 |
184 // Nothing should run until we tell them to. | 207 // Nothing should run until we tell them to. |
185 EXPECT_EQ(GetLastTask(), 0); | 208 EXPECT_EQ(GetLastTask(), 0); |
186 runner.RunAllTasksNow(); | 209 runner.RunAllTasksNow(); |
187 | 210 |
188 // Only the first task should have run, since it failed | 211 // Only the first task should have run, since it failed |
189 EXPECT_EQ(GetLastTask(), 3); | 212 EXPECT_EQ(GetLastTask(), 3); |
| 213 EXPECT_EQ(task_count, 1); |
| 214 EXPECT_EQ(observer_calls, 1); |
| 215 EXPECT_EQ(observer_result, 1); |
190 | 216 |
191 EXPECT_TRUE(observer_called); | 217 // After a failed task all remaining tasks should be cancelled |
192 EXPECT_EQ(observer_result, 1); | 218 // In particular Post... should not be called by running asynchronously |
| 219 runner.StartRunningTasksAsync(); |
| 220 |
| 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); |
193 } | 225 } |
194 | 226 |
195 TEST_F(StartupTaskRunnerTest, AsynchronousExecution) { | 227 TEST_F(StartupTaskRunnerTest, AsynchronousExecution) { |
196 | 228 |
197 MockTaskRunner mock_runner; | 229 MockTaskRunner mock_runner; |
198 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); | 230 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); |
199 | 231 |
200 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); | 232 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); |
201 EXPECT_CALL( | 233 EXPECT_CALL( |
202 mock_runner, | 234 mock_runner, |
(...skipping 14 matching lines...) Expand all Loading... |
217 EXPECT_EQ(GetLastTask(), 0); | 249 EXPECT_EQ(GetLastTask(), 0); |
218 runner.StartRunningTasksAsync(); | 250 runner.StartRunningTasksAsync(); |
219 | 251 |
220 // No tasks should have run yet, since we the message loop hasn't run. | 252 // No tasks should have run yet, since we the message loop hasn't run. |
221 EXPECT_EQ(GetLastTask(), 0); | 253 EXPECT_EQ(GetLastTask(), 0); |
222 | 254 |
223 // Fake the actual message loop. Each time a task is run a new task should | 255 // Fake the actual message loop. Each time a task is run a new task should |
224 // be added to the queue, hence updating "task". The loop should actually run | 256 // be added to the queue, hence updating "task". The loop should actually run |
225 // at most 3 times (once for each task plus possibly once for the observer), | 257 // at most 3 times (once for each task plus possibly once for the observer), |
226 // the "4" is a backstop. | 258 // the "4" is a backstop. |
227 for (int i = 0; i < 4 && !observer_called; i++) { | 259 for (int i = 0; i < 4 && observer_calls == 0; i++) { |
228 task.Run(); | 260 task.Run(); |
229 EXPECT_EQ(i + 1, GetLastTask()); | 261 EXPECT_EQ(i + 1, GetLastTask()); |
230 } | 262 } |
231 EXPECT_TRUE(observer_called); | 263 EXPECT_EQ(task_count, 2); |
| 264 EXPECT_EQ(observer_calls, 1); |
232 EXPECT_EQ(observer_result, 0); | 265 EXPECT_EQ(observer_result, 0); |
| 266 |
| 267 // Check that running synchronously now doesn't do anything |
| 268 |
| 269 runner.RunAllTasksNow(); |
| 270 EXPECT_EQ(task_count, 2); |
| 271 EXPECT_EQ(observer_calls, 1); |
233 } | 272 } |
234 | 273 |
235 TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) { | 274 TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) { |
236 | 275 |
237 MockTaskRunner mock_runner; | 276 MockTaskRunner mock_runner; |
238 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); | 277 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner); |
239 | 278 |
240 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); | 279 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0); |
241 EXPECT_CALL( | 280 EXPECT_CALL( |
242 mock_runner, | 281 mock_runner, |
(...skipping 14 matching lines...) Expand all Loading... |
257 EXPECT_EQ(GetLastTask(), 0); | 296 EXPECT_EQ(GetLastTask(), 0); |
258 runner.StartRunningTasksAsync(); | 297 runner.StartRunningTasksAsync(); |
259 | 298 |
260 // No tasks should have run yet, since we the message loop hasn't run. | 299 // No tasks should have run yet, since we the message loop hasn't run. |
261 EXPECT_EQ(GetLastTask(), 0); | 300 EXPECT_EQ(GetLastTask(), 0); |
262 | 301 |
263 // Fake the actual message loop. Each time a task is run a new task should | 302 // Fake the actual message loop. Each time a task is run a new task should |
264 // be added to the queue, hence updating "task". The loop should actually run | 303 // be added to the queue, hence updating "task". The loop should actually run |
265 // at most twice (once for the failed task plus possibly once for the | 304 // at most twice (once for the failed task plus possibly once for the |
266 // observer), the "4" is a backstop. | 305 // observer), the "4" is a backstop. |
267 for (int i = 0; i < 4 && !observer_called; i++) { | 306 for (int i = 0; i < 4 && observer_calls == 0; i++) { |
268 task.Run(); | 307 task.Run(); |
269 } | 308 } |
270 EXPECT_EQ(GetLastTask(), 3); | 309 EXPECT_EQ(GetLastTask(), 3); |
| 310 EXPECT_EQ(task_count, 1); |
271 | 311 |
272 EXPECT_TRUE(observer_called); | 312 EXPECT_EQ(observer_calls, 1); |
273 EXPECT_EQ(observer_result, 1); | 313 EXPECT_EQ(observer_result, 1); |
| 314 |
| 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); |
274 } | 319 } |
275 } // namespace | 320 } // namespace |
276 } // namespace content | 321 } // namespace content |
OLD | NEW |