1 // Copyright 2017 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/browser_main_loop.h"
6
7 #include "base/command_line.h"
8 #include "base/system/sys_info.h"
9 #include "base/task/thread_pool/thread_pool_instance.h"
10 #include "base/test/mock_callback.h"
11 #include "base/test/scoped_command_line.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/scheduler/browser_task_executor.h"
14 #include "content/browser/startup_data_impl.h"
15 #include "content/browser/startup_helper.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/common/content_switches.h"
18 #include "content/public/common/main_function_params.h"
19 #include "content/public/test/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace content {
23
24 using StrickMockTask =
25 testing::StrictMock<base::MockCallback<base::RepeatingCallback<void()>>>;
26
27 class BrowserMainLoopTest : public testing::Test {
28 protected:
BrowserMainLoopTest()29 BrowserMainLoopTest() {
30 base::test::ScopedCommandLine scoped_command_line;
31 scoped_command_line.GetProcessCommandLine()->AppendSwitch(
32 switches::kSingleProcess);
33 base::ThreadPoolInstance::Create("Browser");
34 StartBrowserThreadPool();
35 BrowserTaskExecutor::Create();
36 }
37
~BrowserMainLoopTest()38 ~BrowserMainLoopTest() override {
39 BrowserTaskExecutor::ResetForTesting();
40 for (int id = BrowserThread::UI; id < BrowserThread::ID_COUNT; ++id) {
41 BrowserThreadImpl::ResetGlobalsForTesting(
42 static_cast<BrowserThread::ID>(id));
43 }
44 base::ThreadPoolInstance::Get()->JoinForTesting();
45 base::ThreadPoolInstance::Set(nullptr);
46 }
47
GetProcessCommandLine()48 const base::CommandLine& GetProcessCommandLine() {
49 return *scoped_command_line_.GetProcessCommandLine();
50 }
51
52 private:
53 base::test::ScopedCommandLine scoped_command_line_;
54 }; // namespace content
55
56 // Verify that a single-process browser process has at least as many threads as
57 // the number of cores in its foreground pool.
TEST_F(BrowserMainLoopTest,CreateThreadsInSingleProcess)58 TEST_F(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
59 MainFunctionParams main_function_params(GetProcessCommandLine());
60
61 StartupDataImpl startup_data;
62 startup_data.io_thread = BrowserTaskExecutor::CreateIOThread();
63 main_function_params.startup_data = &startup_data;
64
65 BrowserMainLoop browser_main_loop(
66 main_function_params,
67 std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>());
68 browser_main_loop.MainMessageLoopStart();
69 browser_main_loop.Init();
70 browser_main_loop.CreateThreads();
71 EXPECT_GE(base::ThreadPoolInstance::Get()
72 ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
73 {base::TaskPriority::USER_VISIBLE}),
74 base::SysInfo::NumberOfProcessors() - 1);
75 browser_main_loop.ShutdownThreadsAndCleanUp();
76 BrowserTaskExecutor::ResetForTesting();
77 }
78
TEST_F(BrowserMainLoopTest,PostTaskToIOThreadBeforeThreadCreationDoesNotRunTask)79 TEST_F(BrowserMainLoopTest,
80 PostTaskToIOThreadBeforeThreadCreationDoesNotRunTask) {
81 MainFunctionParams main_function_params(GetProcessCommandLine());
82
83 StartupDataImpl startup_data;
84 startup_data.io_thread = BrowserTaskExecutor::CreateIOThread();
85 main_function_params.startup_data = &startup_data;
86
87 BrowserMainLoop browser_main_loop(
88 main_function_params,
89 std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>());
90 browser_main_loop.MainMessageLoopStart();
91 browser_main_loop.Init();
92
93 StrickMockTask task;
94
95 // No task should run because IO thread has not been initialized yet.
96 GetIOThreadTaskRunner({})->PostTask(FROM_HERE, task.Get());
97 GetIOThreadTaskRunner({})->PostTask(FROM_HERE, task.Get());
98
99 content::RunAllPendingInMessageLoop(BrowserThread::IO);
100
101 EXPECT_CALL(task, Run).Times(2);
102 browser_main_loop.CreateThreads();
103 content::RunAllPendingInMessageLoop(BrowserThread::IO);
104
105 browser_main_loop.ShutdownThreadsAndCleanUp();
106 BrowserTaskExecutor::ResetForTesting();
107 }
108
109 } // namespace content
110