| 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 |