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.
5 #include "chrome/browser/after_startup_task_utils.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/run_loop.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/task/post_task.h"
16 #include "base/task/thread_pool.h"
17 #include "base/task_runner_util.h"
18 #include "content/public/browser/browser_task_traits.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/browser_task_environment.h"
21 #include "testing/gtest/include/gtest/gtest.h"
25 class WrappedTaskRunner : public base::SequencedTaskRunner {
27 explicit WrappedTaskRunner(scoped_refptr<SequencedTaskRunner> real_runner)
28 : real_task_runner_(std::move(real_runner)) {}
30 bool PostDelayedTask(const base::Location& from_here,
31 base::OnceClosure task,
32 base::TimeDelta delay) override {
34 return real_task_runner_->PostDelayedTask(
36 base::BindOnce(&WrappedTaskRunner::RunWrappedTask, this,
38 base::TimeDelta()); // Squash all delays so our tests complete asap.
41 bool PostNonNestableDelayedTask(const base::Location& from_here,
42 base::OnceClosure task,
43 base::TimeDelta delay) override {
49 bool RunsTasksInCurrentSequence() const override {
50 return real_task_runner_->RunsTasksInCurrentSequence();
53 base::SequencedTaskRunner* real_runner() const {
54 return real_task_runner_.get();
57 int total_task_count() const { return posted_task_count_ + ran_task_count_; }
58 int posted_task_count() const { return posted_task_count_; }
59 int ran_task_count() const { return ran_task_count_; }
61 void reset_task_counts() {
62 posted_task_count_ = 0;
67 ~WrappedTaskRunner() override {}
69 void RunWrappedTask(base::OnceClosure task) {
71 std::move(task).Run();
74 scoped_refptr<base::SequencedTaskRunner> real_task_runner_;
75 int posted_task_count_ = 0;
76 int ran_task_count_ = 0;
81 class AfterStartupTaskTest : public testing::Test {
83 AfterStartupTaskTest() {
84 ui_thread_ = base::MakeRefCounted<WrappedTaskRunner>(
85 content::GetUIThreadTaskRunner({}));
86 background_sequence_ = base::MakeRefCounted<WrappedTaskRunner>(
87 base::ThreadPool::CreateSequencedTaskRunner({}));
88 AfterStartupTaskUtils::UnsafeResetForTesting();
91 // Hop to the background sequence and call IsBrowserStartupComplete.
92 bool GetIsBrowserStartupCompleteFromBackgroundSequence() {
93 base::RunLoop run_loop;
95 base::PostTaskAndReplyWithResult(
96 background_sequence_->real_runner(), FROM_HERE,
97 base::BindOnce(&AfterStartupTaskUtils::IsBrowserStartupComplete),
98 base::BindOnce(&AfterStartupTaskTest::GotIsOnBrowserStartupComplete,
99 &run_loop, &is_complete));
104 // Hop to the background sequence and call PostAfterStartupTask.
105 void PostAfterStartupTaskFromBackgroundSequence(
106 const base::Location& from_here,
107 scoped_refptr<base::SequencedTaskRunner> task_runner,
108 base::OnceClosure task) {
109 base::RunLoop run_loop;
110 background_sequence_->real_runner()->PostTaskAndReply(
112 base::BindOnce(&AfterStartupTaskUtils::PostTask, from_here,
113 std::move(task_runner), std::move(task)),
114 base::BindOnce(&base::RunLoop::Quit, base::Unretained(&run_loop)));
118 // Make sure all tasks posted to the background sequence get run.
119 void FlushBackgroundSequence() {
120 base::RunLoop run_loop;
121 background_sequence_->real_runner()->PostTaskAndReply(
122 FROM_HERE, base::DoNothing(),
123 base::BindOnce(&base::RunLoop::Quit, base::Unretained(&run_loop)));
127 static void VerifyExpectedSequence(base::SequencedTaskRunner* task_runner) {
128 EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
132 scoped_refptr<WrappedTaskRunner> ui_thread_;
133 scoped_refptr<WrappedTaskRunner> background_sequence_;
136 static void GotIsOnBrowserStartupComplete(base::RunLoop* loop,
143 content::BrowserTaskEnvironment task_environment_;
146 TEST_F(AfterStartupTaskTest, IsStartupComplete) {
147 // Check IsBrowserStartupComplete on a background sequence first to
148 // verify that it does not allocate the underlying flag on that sequence.
149 // That allocation sequence correctness part of this test relies on
150 // the DCHECK in CancellationFlag::Set().
151 EXPECT_FALSE(GetIsBrowserStartupCompleteFromBackgroundSequence());
152 EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
153 AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting();
154 EXPECT_TRUE(AfterStartupTaskUtils::IsBrowserStartupComplete());
155 EXPECT_TRUE(GetIsBrowserStartupCompleteFromBackgroundSequence());
158 TEST_F(AfterStartupTaskTest, PostTask) {
159 // Nothing should be posted prior to startup completion.
160 EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
161 AfterStartupTaskUtils::PostTask(
162 FROM_HERE, ui_thread_,
163 base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
164 base::RetainedRef(ui_thread_)));
165 AfterStartupTaskUtils::PostTask(
166 FROM_HERE, background_sequence_,
167 base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
168 base::RetainedRef(background_sequence_)));
169 PostAfterStartupTaskFromBackgroundSequence(
170 FROM_HERE, ui_thread_,
171 base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
172 base::RetainedRef(ui_thread_)));
173 PostAfterStartupTaskFromBackgroundSequence(
174 FROM_HERE, background_sequence_,
175 base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
176 base::RetainedRef(background_sequence_)));
177 base::RunLoop().RunUntilIdle();
178 EXPECT_EQ(0, background_sequence_->total_task_count() +
179 ui_thread_->total_task_count());
181 // Queued tasks should be posted upon setting the flag.
182 AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting();
183 EXPECT_EQ(2, background_sequence_->posted_task_count());
184 EXPECT_EQ(2, ui_thread_->posted_task_count());
185 FlushBackgroundSequence();
186 base::RunLoop().RunUntilIdle();
187 EXPECT_EQ(2, background_sequence_->ran_task_count());
188 EXPECT_EQ(2, ui_thread_->ran_task_count());
190 background_sequence_->reset_task_counts();
191 ui_thread_->reset_task_counts();
192 EXPECT_EQ(0, background_sequence_->total_task_count() +
193 ui_thread_->total_task_count());
195 // Tasks posted after startup should get posted immediately.
196 AfterStartupTaskUtils::PostTask(FROM_HERE, ui_thread_, base::DoNothing());
197 AfterStartupTaskUtils::PostTask(FROM_HERE, background_sequence_,
199 EXPECT_EQ(1, background_sequence_->posted_task_count());
200 EXPECT_EQ(1, ui_thread_->posted_task_count());
201 PostAfterStartupTaskFromBackgroundSequence(FROM_HERE, ui_thread_,
203 PostAfterStartupTaskFromBackgroundSequence(FROM_HERE, background_sequence_,
205 EXPECT_EQ(2, background_sequence_->posted_task_count());
206 EXPECT_EQ(2, ui_thread_->posted_task_count());
207 FlushBackgroundSequence();
208 base::RunLoop().RunUntilIdle();
209 EXPECT_EQ(2, background_sequence_->ran_task_count());
210 EXPECT_EQ(2, ui_thread_->ran_task_count());