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

Side by Side Diff: content/common/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 - patch for Yaron's comments Created 7 years, 5 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/public/common/startup_task_runner.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "base/run_loop.h"
11 #include "base/task_runner.h"
12
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace content {
17 namespace {
18
19 using base::Closure;
20 using testing::_;
21 using testing::Assign;
22 using testing::Invoke;
23 using testing::WithArg;
24
25 class StartupTaskRunnerTest : public testing::Test {
26 private:
27
28 int last_task_;
29
30 public:
31
32 virtual void SetUp() { last_task_ = 0; }
33
34 void Task1() { last_task_ = 1; }
35
36 void Task2() { last_task_ = 2; }
37
38 int GetLastTask() { return last_task_; }
39 };
40
41 class MockObserver : public StartupTaskRunner::Observer {
42 public:
43 MOCK_METHOD0(AllStartupTasksRan, void());
44 };
45
46 // We can't use the real message loop, even if we want to, since doing so on
47 // Android requires a complex Java infrastructure. The test would have to built
48 // as a content_shell test; but content_shell startup invokes the class we are
49 // trying to test.
50 //
51 // The mocks are not directly in TaskRunnerProxy because reference counted
52 // objects seem to confuse the mocking framework
53
54 class MockTaskRunner {
55 public:
56 MOCK_METHOD3(
57 PostDelayedTask,
58 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
59 MOCK_METHOD3(
60 PostNonNestableDelayedTask,
61 bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
62 };
63
64 class TaskRunnerProxy : public base::SingleThreadTaskRunner {
65 public:
66 TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
67 bool RunsTasksOnCurrentThread() const { return true; }
68 bool PostDelayedTask(const tracked_objects::Location& location,
69 const Closure& closure,
70 base::TimeDelta delta) {
71 return mock_->PostDelayedTask(location, closure, delta);
72 }
73 bool PostNonNestableDelayedTask(const tracked_objects::Location& location,
74 const Closure& closure,
75 base::TimeDelta delta) {
76 return mock_->PostNonNestableDelayedTask(location, closure, delta);
77 }
78
79 private:
80 MockTaskRunner* mock_;
81 };
82
83 TEST_F(StartupTaskRunnerTest, ImmediateExecution) {
84
85 MockTaskRunner mock_runner;
86 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
87
88 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
89 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
90
91 scoped_refptr<StartupTaskRunner> runner =
92 new StartupTaskRunner(StartupTaskRunner::IMMEDIATE, NULL);
93
94 runner->SetProxy(proxy);
95
96 base::Closure task1 =
97 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
98 runner->AddTask(task1);
99 EXPECT_EQ(GetLastTask(), 0);
100 base::Closure task2 =
101 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
102 runner->AddTask(task2);
103
104 // Nothing should run until we tell them to.
105 EXPECT_EQ(GetLastTask(), 0);
106 runner->StartRunningTasks();
107
108 // On an immediate StartupTaskRunner the tasks should now all have run.
109 EXPECT_EQ(GetLastTask(), 2);
110 }
111
112 TEST_F(StartupTaskRunnerTest, ImmediateExecutionObserved) {
113 MockTaskRunner mock_runner;
114 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
115
116 MockObserver observer;
117 EXPECT_CALL(observer, AllStartupTasksRan()).Times(1);
118
119 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
120 EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
121
122 scoped_refptr<StartupTaskRunner> runner =
123 new StartupTaskRunner(StartupTaskRunner::IMMEDIATE, &observer);
124
125 runner->SetProxy(proxy);
126
127 base::Closure task1 =
128 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
129 runner->AddTask(task1);
130 EXPECT_EQ(GetLastTask(), 0);
131 base::Closure task2 =
132 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
133 runner->AddTask(task2);
134
135 // Nothing should run until we tell them to.
136 EXPECT_EQ(GetLastTask(), 0);
137 runner->StartRunningTasks();
138
139 // On an immediate StartupTaskRunner the tasks should now all have run.
140 EXPECT_EQ(GetLastTask(), 2);
141 }
142
143 base::Closure task;
144
145 // I couldn't get gMock's SaveArg to compile, hence had to save the argument
146 // this way
147 bool SaveTaskArg(const Closure& arg) {
148 task = arg;
149 return true;
150 }
151
152 TEST_F(StartupTaskRunnerTest, IncrementalExecution) {
153
154 MockTaskRunner mock_runner;
155 scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
156
157 bool done = false;
158 ;
159
160 MockObserver observer;
161
162 EXPECT_CALL(observer, AllStartupTasksRan()).WillOnce(Assign(&done, true));
163 EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
164 EXPECT_CALL(
165 mock_runner,
166 PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
167 .Times(3).WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
168
169 scoped_refptr<StartupTaskRunner> runner =
170 new StartupTaskRunner(StartupTaskRunner::INCREMENTAL, &observer);
171
172 runner->SetProxy(proxy);
173
174 base::Closure task1 =
175 base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
176 runner->AddTask(task1);
177 base::Closure task2 =
178 base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
179 runner->AddTask(task2);
180
181 // Nothing should run until we tell them to.
182 EXPECT_EQ(GetLastTask(), 0);
183 runner->StartRunningTasks();
184
185 // No tasks should have run yet, since we the message loop hasn't run.
186 EXPECT_EQ(GetLastTask(), 0);
187
188 // Fake the actual message loop. Each time a task is run a new task should
189 // be added to the queue, hence updating "task". The loop should actually run
190 // three times, the "4" is a backstop.
191 for (int i = 0; i < 4 && !done; i++) {
192 task.Run();
193 if (!done) {
194 EXPECT_EQ(i + 1, GetLastTask());
195 }
196 }
197 }
198
199 } // namespace
200 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698