123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "chrome/browser/after_startup_task_utils.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/memory/ref_counted.h"
- #include "base/run_loop.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/task/task_runner_util.h"
- #include "base/task/thread_pool.h"
- #include "base/test/bind.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/test/browser_task_environment.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace {
- class WrappedTaskRunner : public base::SequencedTaskRunner {
- public:
- explicit WrappedTaskRunner(scoped_refptr<SequencedTaskRunner> real_runner)
- : real_task_runner_(std::move(real_runner)) {}
- bool PostDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- ++posted_task_count_;
- return real_task_runner_->PostDelayedTask(
- from_here,
- base::BindOnce(&WrappedTaskRunner::RunWrappedTask, this,
- std::move(task)),
- base::TimeDelta()); // Squash all delays so our tests complete asap.
- }
- bool PostNonNestableDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- // Not implemented.
- NOTREACHED();
- return false;
- }
- bool RunsTasksInCurrentSequence() const override {
- return real_task_runner_->RunsTasksInCurrentSequence();
- }
- base::SequencedTaskRunner* real_runner() const {
- return real_task_runner_.get();
- }
- int total_task_count() const { return posted_task_count_ + ran_task_count_; }
- int posted_task_count() const { return posted_task_count_; }
- int ran_task_count() const { return ran_task_count_; }
- void reset_task_counts() {
- posted_task_count_ = 0;
- ran_task_count_ = 0;
- }
- private:
- ~WrappedTaskRunner() override {}
- void RunWrappedTask(base::OnceClosure task) {
- ++ran_task_count_;
- std::move(task).Run();
- }
- scoped_refptr<base::SequencedTaskRunner> real_task_runner_;
- int posted_task_count_ = 0;
- int ran_task_count_ = 0;
- };
- } // namespace
- class AfterStartupTaskTest : public testing::Test {
- public:
- AfterStartupTaskTest() {
- ui_thread_ = base::MakeRefCounted<WrappedTaskRunner>(
- content::GetUIThreadTaskRunner({}));
- background_sequence_ = base::MakeRefCounted<WrappedTaskRunner>(
- base::ThreadPool::CreateSequencedTaskRunner({}));
- AfterStartupTaskUtils::UnsafeResetForTesting();
- }
- // Hop to the background sequence and call IsBrowserStartupComplete.
- bool GetIsBrowserStartupCompleteFromBackgroundSequence() {
- base::RunLoop run_loop;
- bool is_complete;
- base::PostTaskAndReplyWithResult(
- background_sequence_->real_runner(), FROM_HERE,
- base::BindOnce(&AfterStartupTaskUtils::IsBrowserStartupComplete),
- base::BindOnce(&AfterStartupTaskTest::GotIsOnBrowserStartupComplete,
- &run_loop, &is_complete));
- run_loop.Run();
- return is_complete;
- }
- // Hop to the background sequence and call PostAfterStartupTask.
- void PostAfterStartupTaskFromBackgroundSequence(
- const base::Location& from_here,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- base::OnceClosure task) {
- base::RunLoop run_loop;
- background_sequence_->real_runner()->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&AfterStartupTaskUtils::PostTask, from_here,
- std::move(task_runner), std::move(task)),
- base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
- run_loop.Run();
- }
- // Make sure all tasks posted to the background sequence get run.
- void FlushBackgroundSequence() {
- base::RunLoop run_loop;
- background_sequence_->real_runner()->PostTaskAndReply(
- FROM_HERE, base::DoNothing(),
- base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
- run_loop.Run();
- }
- static void VerifyExpectedSequence(base::SequencedTaskRunner* task_runner) {
- EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
- }
- protected:
- scoped_refptr<WrappedTaskRunner> ui_thread_;
- scoped_refptr<WrappedTaskRunner> background_sequence_;
- private:
- static void GotIsOnBrowserStartupComplete(base::RunLoop* loop,
- bool* out,
- bool is_complete) {
- *out = is_complete;
- loop->Quit();
- }
- content::BrowserTaskEnvironment task_environment_;
- };
- TEST_F(AfterStartupTaskTest, IsStartupComplete) {
- // Check IsBrowserStartupComplete on a background sequence first to
- // verify that it does not allocate the underlying flag on that sequence.
- // That allocation sequence correctness part of this test relies on
- // the DCHECK in CancellationFlag::Set().
- EXPECT_FALSE(GetIsBrowserStartupCompleteFromBackgroundSequence());
- EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
- AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting();
- EXPECT_TRUE(AfterStartupTaskUtils::IsBrowserStartupComplete());
- EXPECT_TRUE(GetIsBrowserStartupCompleteFromBackgroundSequence());
- }
- TEST_F(AfterStartupTaskTest, PostTask) {
- // Nothing should be posted prior to startup completion.
- EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
- AfterStartupTaskUtils::PostTask(
- FROM_HERE, ui_thread_,
- base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
- base::RetainedRef(ui_thread_)));
- AfterStartupTaskUtils::PostTask(
- FROM_HERE, background_sequence_,
- base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
- base::RetainedRef(background_sequence_)));
- PostAfterStartupTaskFromBackgroundSequence(
- FROM_HERE, ui_thread_,
- base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
- base::RetainedRef(ui_thread_)));
- PostAfterStartupTaskFromBackgroundSequence(
- FROM_HERE, background_sequence_,
- base::BindOnce(&AfterStartupTaskTest::VerifyExpectedSequence,
- base::RetainedRef(background_sequence_)));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, background_sequence_->total_task_count() +
- ui_thread_->total_task_count());
- // Queued tasks should be posted upon setting the flag.
- AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting();
- EXPECT_EQ(2, background_sequence_->posted_task_count());
- EXPECT_EQ(2, ui_thread_->posted_task_count());
- FlushBackgroundSequence();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, background_sequence_->ran_task_count());
- EXPECT_EQ(2, ui_thread_->ran_task_count());
- background_sequence_->reset_task_counts();
- ui_thread_->reset_task_counts();
- EXPECT_EQ(0, background_sequence_->total_task_count() +
- ui_thread_->total_task_count());
- // Tasks posted after startup should get posted immediately.
- AfterStartupTaskUtils::PostTask(FROM_HERE, ui_thread_, base::DoNothing());
- AfterStartupTaskUtils::PostTask(FROM_HERE, background_sequence_,
- base::DoNothing());
- EXPECT_EQ(1, background_sequence_->posted_task_count());
- EXPECT_EQ(1, ui_thread_->posted_task_count());
- PostAfterStartupTaskFromBackgroundSequence(FROM_HERE, ui_thread_,
- base::DoNothing());
- PostAfterStartupTaskFromBackgroundSequence(FROM_HERE, background_sequence_,
- base::DoNothing());
- EXPECT_EQ(2, background_sequence_->posted_task_count());
- EXPECT_EQ(2, ui_thread_->posted_task_count());
- FlushBackgroundSequence();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, background_sequence_->ran_task_count());
- EXPECT_EQ(2, ui_thread_->ran_task_count());
- }
|