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

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

Powered by Google App Engine
This is Rietveld 408576698