Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(485)

Side by Side Diff: content/browser/startup_task_runner_unittest.cc

Issue 19957002: Run the later parts of startup as UI thread tasks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Run the later parts of startup as UI thread tasks - fix component build Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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 bool observer_called = false;
27 int observer_result;
28
29
30 class StartupTaskRunnerTest : public testing::Test {
31 private:
32
33 int last_task_;
34
35 public:
36
37 virtual void SetUp() {
38 last_task_ = 0;
39 observer_called = false;
40 }
41
42 int Task1() {
43 last_task_ = 1;
44 return 0;
45 }
46
47 int Task2() {
48 last_task_ = 2;
49 return 0;
50 }
51
52 int Task3() {
53 // Task returning failure
54 last_task_ = 3;
55 return 1;
56 }
57
58 int GetLastTask() { return last_task_; }
59 };
60
61 void Observer(int result) {
62 observer_called = true;
63 observer_result = result;
64 }
65
66 // We can't use the real message loop, even if we want to, since doing so on
67 // Android requires a complex Java infrastructure. The test would have to built
68 // as a content_shell test; but content_shell startup invokes the class we are
69 // trying to test.
70 //
71 // The mocks are not directly in TaskRunnerProxy because reference counted
72 // objects seem to confuse the mocking framework
73
74 class MockTaskRunner {
75 public:
76 MOCK_METHOD3(
77 PostDelayedTask,
78 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
79 MOCK_METHOD3(
80 PostNonNestableDelayedTask,
81 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
82 };
83
84 class TaskRunnerProxy : public base::SingleThreadTaskRunner {
85 public:
86 TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
87 bool RunsTasksOnCurrentThread() const { return true; }
88 bool PostDelayedTask(const tracked_objects::Location& location,
89 const Closure& closure,
90 base::TimeDelta delta) {
91 return mock_->PostDelayedTask(location, closure, delta);
92 }
93 bool PostNonNestableDelayedTask(const tracked_objects::Location& location,
94 const Closure& closure,
95 base::TimeDelta delta) {
96 return mock_->PostNonNestableDelayedTask(location, closure, delta);
97 }
98
99 private:
100 MockTaskRunner* mock_;
101 };
102
103 TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
104 MockTaskRunner mock_runner;
105 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
106
107 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
108 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
109
110 scoped_refptr<StartupTaskRunner> runner =
111 new StartupTaskRunner(false, Observer, proxy);
112
113 StartupTask task1 =
114 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
115 runner->AddTask(task1);
116 EXPECT_EQ(GetLastTask(), 0);
117 StartupTask task2 =
118 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
119 runner->AddTask(task2);
120
121 // Nothing should run until we tell them to.
122 EXPECT_EQ(GetLastTask(), 0);
123 runner->StartRunningTasks();
124
125 // On an immediate StartupTaskRunner the tasks should now all have run.
126 EXPECT_EQ(GetLastTask(), 2);
127
128 EXPECT_TRUE(observer_called);
129 EXPECT_EQ(observer_result, 0);
130 }
131
132 TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
133 MockTaskRunner mock_runner;
134 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
135
136 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
137 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
138
139 scoped_refptr<StartupTaskRunner> runner =
140 new StartupTaskRunner(false, Observer, proxy);
141
142 StartupTask task3 =
143 base::Bind(&StartupTaskRunnerTest::Task3, base::Unretained(this));
144 runner->AddTask(task3);
145 EXPECT_EQ(GetLastTask(), 0);
146 StartupTask task2 =
147 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
148 runner->AddTask(task2);
149
150 // Nothing should run until we tell them to.
151 EXPECT_EQ(GetLastTask(), 0);
152 runner->StartRunningTasks();
153
154 // Only the first task should have run, since it failed
155 EXPECT_EQ(GetLastTask(), 3);
156
157 EXPECT_TRUE(observer_called);
158 EXPECT_EQ(observer_result, 1);
159 }
160 base::Closure task;
161
162 // I couldn't get gMock's SaveArg to compile, hence had to save the argument
163 // this way
164 bool SaveTaskArg(const Closure& arg) {
165 task = arg;
166 return true;
167 }
168
169 TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
170
171 MockTaskRunner mock_runner;
172 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
173
174 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
175 EXPECT_CALL(
176 mock_runner,
177 PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
178 .Times(testing::Between(2,3))
179 .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
180
181 scoped_refptr<StartupTaskRunner> runner =
182 new StartupTaskRunner(true, Observer, proxy);
183
184 StartupTask task1 =
185 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
186 runner->AddTask(task1);
187 StartupTask task2 =
188 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
189 runner->AddTask(task2);
190
191 // Nothing should run until we tell them to.
192 EXPECT_EQ(GetLastTask(), 0);
193 runner->StartRunningTasks();
194
195 // No tasks should have run yet, since we the message loop hasn't run.
196 EXPECT_EQ(GetLastTask(), 0);
197
198 // Fake the actual message loop. Each time a task is run a new task should
199 // be added to the queue, hence updating "task". The loop should actually run
200 // at most 3 times (once for each task plus possibly once for the observer),
201 // the "4" is a backstop.
202 for (int i = 0; i < 4 && !observer_called; i++) {
203 task.Run();
204 EXPECT_EQ(i + 1, GetLastTask());
205 }
206 EXPECT_TRUE(observer_called);
207 EXPECT_EQ(observer_result, 0);
208 }
209
210 TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
211
212 MockTaskRunner mock_runner;
213 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
214
215 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
216 EXPECT_CALL(
217 mock_runner,
218 PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
219 .Times(testing::Between(1,2))
220 .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
221
222 scoped_refptr<StartupTaskRunner> runner =
223 new StartupTaskRunner(true, Observer, proxy);
224
225 StartupTask task3 =
226 base::Bind(&StartupTaskRunnerTest::Task3, base::Unretained(this));
227 runner->AddTask(task3);
228 StartupTask task2 =
229 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
230 runner->AddTask(task2);
231
232 // Nothing should run until we tell them to.
233 EXPECT_EQ(GetLastTask(), 0);
234 runner->StartRunningTasks();
235
236 // No tasks should have run yet, since we the message loop hasn't run.
237 EXPECT_EQ(GetLastTask(), 0);
238
239 // Fake the actual message loop. Each time a task is run a new task should
240 // be added to the queue, hence updating "task". The loop should actually run
241 // at most twice (once for the failed task plus possibly once for the
242 // observer), the "4" is a backstop.
243 for (int i = 0; i < 4 && !observer_called; i++) {
244 task.Run();
245 }
246 EXPECT_EQ(GetLastTask(), 3);
247
248 EXPECT_TRUE(observer_called);
249 EXPECT_EQ(observer_result, 1);
250 }
251 } // namespace
252 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698