OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "chrome/browser/after_startup_task_utils.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "base/message_loop/message_loop_proxy.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/task_runner_util.h" | |
15 #include "base/threading/thread.h" | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "content/public/test/test_browser_thread_bundle.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 using base::RunLoop; | |
21 using content::BrowserThread; | |
22 using content::TestBrowserThreadBundle; | |
23 | |
24 namespace { | |
25 | |
26 class WrappedTaskRunner : public base::TaskRunner { | |
27 public: | |
28 explicit WrappedTaskRunner(const scoped_refptr<TaskRunner>& real_runner) | |
29 : real_task_runner_(real_runner), | |
30 posted_task_count_(0), | |
cmumford
2015/04/06 23:18:03
Nit: Use Non-Static Class Member Initializers
michaeln
2015/04/06 23:45:59
Done
| |
31 ran_task_count_(0) {} | |
32 | |
33 bool PostDelayedTask(const tracked_objects::Location& from_here, | |
34 const base::Closure& task, | |
35 base::TimeDelta delay) override { | |
36 ++posted_task_count_; | |
37 return real_task_runner_->PostDelayedTask( | |
38 from_here, base::Bind(&WrappedTaskRunner::RunWrappedTask, this, task), | |
39 base::TimeDelta()); // Squash all delays so our tests complete asap. | |
40 } | |
41 | |
42 bool RunsTasksOnCurrentThread() const override { | |
43 return real_task_runner_->RunsTasksOnCurrentThread(); | |
44 } | |
45 | |
46 base::TaskRunner* real_runner() const { return real_task_runner_.get(); } | |
47 | |
48 int total_task_count() const { return posted_task_count_ + ran_task_count_; } | |
49 int posted_task_count() const { return posted_task_count_; } | |
50 int ran_task_count() const { return ran_task_count_; } | |
51 | |
52 void reset_task_counts() { | |
53 posted_task_count_ = 0; | |
54 ran_task_count_ = 0; | |
55 } | |
56 | |
57 private: | |
58 void RunWrappedTask(const base::Closure& task) { | |
59 ++ran_task_count_; | |
60 task.Run(); | |
61 } | |
62 | |
63 scoped_refptr<TaskRunner> real_task_runner_; | |
64 int posted_task_count_; | |
65 int ran_task_count_; | |
66 }; | |
67 | |
68 } // namespace | |
69 | |
70 class AfterStartupTaskTest : public testing::Test { | |
71 public: | |
72 AfterStartupTaskTest() | |
73 : browser_thread_bundle_(TestBrowserThreadBundle::REAL_DB_THREAD) { | |
74 ui_thread_ = new WrappedTaskRunner( | |
75 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)); | |
76 | |
77 db_thread_ = new WrappedTaskRunner( | |
78 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)); | |
79 AfterStartupTaskUtils::UnsafeReset(); | |
80 } | |
81 | |
82 // Hop to the db thread and call IsBrowserStartupComplete. | |
83 bool GetIsBrowserStartupCompleteFromDBThread() { | |
84 RunLoop run_loop; | |
85 bool is_complete; | |
86 base::PostTaskAndReplyWithResult( | |
87 db_thread_->real_runner(), FROM_HERE, | |
88 base::Bind(&AfterStartupTaskUtils::IsBrowserStartupComplete), | |
89 base::Bind(&AfterStartupTaskTest::GotIsOnBrowserStartupComplete, | |
90 &run_loop, &is_complete)); | |
91 run_loop.Run(); | |
92 return is_complete; | |
93 } | |
94 | |
95 // Hop to the db thread and call PostAfterStartupTask. | |
96 void PostAfterStartupTaskFromDBThread( | |
97 const tracked_objects::Location& from_here, | |
98 const scoped_refptr<base::TaskRunner>& task_runner, | |
99 const base::Closure& task) { | |
100 RunLoop run_loop; | |
101 db_thread_->real_runner()->PostTaskAndReply( | |
102 FROM_HERE, base::Bind(&AfterStartupTaskUtils::PostTask, from_here, | |
103 task_runner, task), | |
104 base::Bind(&RunLoop::Quit, base::Unretained(&run_loop))); | |
105 run_loop.Run(); | |
106 } | |
107 | |
108 // Make sure all tasks posted to the DB thread get run. | |
109 void FlushDBThread() { | |
110 RunLoop run_loop; | |
111 db_thread_->real_runner()->PostTaskAndReply( | |
112 FROM_HERE, base::Bind(&base::DoNothing), | |
113 base::Bind(&RunLoop::Quit, base::Unretained(&run_loop))); | |
114 run_loop.Run(); | |
115 } | |
116 | |
117 protected: | |
118 scoped_refptr<WrappedTaskRunner> ui_thread_; | |
119 scoped_refptr<WrappedTaskRunner> db_thread_; | |
120 | |
121 private: | |
122 static void GotIsOnBrowserStartupComplete(RunLoop* loop, | |
123 bool* out, | |
124 bool is_complete) { | |
125 *out = is_complete; | |
126 loop->Quit(); | |
127 } | |
128 | |
129 TestBrowserThreadBundle browser_thread_bundle_; | |
130 }; | |
131 | |
132 TEST_F(AfterStartupTaskTest, IsStartupComplete) { | |
133 // Check IsBrowserStartupComplete on a background thread first to | |
134 // verify that it does not allocate the underlying flag on that thread. | |
135 EXPECT_FALSE(GetIsBrowserStartupCompleteFromDBThread()); | |
136 EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete()); | |
137 AfterStartupTaskUtils::SetBrowserStartupIsComplete(); | |
cmumford
2015/04/06 23:18:03
Can you add a comment explaining this test relies
michaeln
2015/04/06 23:45:59
Done.
| |
138 EXPECT_TRUE(AfterStartupTaskUtils::IsBrowserStartupComplete()); | |
139 EXPECT_TRUE(GetIsBrowserStartupCompleteFromDBThread()); | |
140 } | |
141 | |
142 TEST_F(AfterStartupTaskTest, PostTask) { | |
143 // Nothing should be posted prior to startup completion. | |
144 EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete()); | |
145 AfterStartupTaskUtils::PostTask(FROM_HERE, ui_thread_, | |
146 base::Bind(&base::DoNothing)); | |
147 AfterStartupTaskUtils::PostTask(FROM_HERE, db_thread_, | |
148 base::Bind(&base::DoNothing)); | |
149 PostAfterStartupTaskFromDBThread(FROM_HERE, ui_thread_, | |
150 base::Bind(&base::DoNothing)); | |
151 PostAfterStartupTaskFromDBThread(FROM_HERE, db_thread_, | |
152 base::Bind(&base::DoNothing)); | |
153 FlushDBThread(); | |
154 RunLoop().RunUntilIdle(); | |
155 EXPECT_EQ(0, db_thread_->total_task_count()); | |
156 EXPECT_EQ(0, ui_thread_->total_task_count()); | |
157 | |
158 // Queued tasks should be posted upon setting the flag. | |
159 AfterStartupTaskUtils::SetBrowserStartupIsComplete(); | |
160 EXPECT_EQ(2, db_thread_->posted_task_count()); | |
161 EXPECT_EQ(2, ui_thread_->posted_task_count()); | |
162 FlushDBThread(); | |
163 RunLoop().RunUntilIdle(); | |
164 EXPECT_EQ(2, db_thread_->ran_task_count()); | |
165 EXPECT_EQ(2, ui_thread_->ran_task_count()); | |
166 | |
167 db_thread_->reset_task_counts(); | |
168 ui_thread_->reset_task_counts(); | |
cmumford
2015/04/06 23:18:03
What do you think about maybe resetting only one o
michaeln
2015/04/06 23:45:58
Instead, I made some of the tasks verify they're r
| |
169 | |
170 // Tasks posted after startup should get posted immediately. | |
cmumford
2015/04/06 23:18:03
Do you want to add EXPECT_EQ(0, db_thread_->total_
michaeln
2015/04/06 23:45:58
Done.
| |
171 AfterStartupTaskUtils::PostTask(FROM_HERE, ui_thread_, | |
172 base::Bind(&base::DoNothing)); | |
173 AfterStartupTaskUtils::PostTask(FROM_HERE, db_thread_, | |
174 base::Bind(&base::DoNothing)); | |
175 EXPECT_EQ(1, db_thread_->posted_task_count()); | |
176 EXPECT_EQ(1, ui_thread_->posted_task_count()); | |
177 PostAfterStartupTaskFromDBThread(FROM_HERE, ui_thread_, | |
178 base::Bind(&base::DoNothing)); | |
179 PostAfterStartupTaskFromDBThread(FROM_HERE, db_thread_, | |
180 base::Bind(&base::DoNothing)); | |
181 FlushDBThread(); | |
182 EXPECT_EQ(2, db_thread_->posted_task_count()); | |
183 EXPECT_EQ(2, ui_thread_->posted_task_count()); | |
184 FlushDBThread(); | |
185 RunLoop().RunUntilIdle(); | |
186 EXPECT_EQ(2, db_thread_->ran_task_count()); | |
187 EXPECT_EQ(2, ui_thread_->ran_task_count()); | |
188 } | |
OLD | NEW |