1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
content / public / test / unittest_test_suite.cc [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/unittest_test_suite.h"
#include <memory>
#include "base/base_switches.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/rand_util.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/null_task_runner.h"
#include "base/test/test_suite.h"
#include "build/build_config.h"
#include "components/breadcrumbs/core/breadcrumb_manager.h"
#include "components/breadcrumbs/core/crash_reporter_breadcrumb_observer.h"
#include "content/app/mojo/mojo_init.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/network_service_instance_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_client.h"
#include "content/public/test/content_test_suite_base.h"
#include "content/public/test/scoped_web_ui_controller_factory_registration.h"
#include "content/public/test/test_host_resolver.h"
#include "content/public/utility/content_utility_client.h"
#include "content/test/test_blink_web_unit_test_support.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
#include "mojo/core/embedder/embedder.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/blink.h"
#include "ui/base/resource/resource_bundle.h"
#if defined(USE_AURA)
#include "ui/aura/env.h"
#endif
namespace content {
class UnitTestTestSuite::UnitTestEventListener
: public testing::EmptyTestEventListener {
public:
UnitTestEventListener(
base::RepeatingCallback<
std::unique_ptr<UnitTestTestSuite::ContentClients>()> create_clients,
base::OnceClosure first_test_start_callback)
: create_clients_(create_clients),
first_test_start_callback_(std::move(first_test_start_callback)) {}
UnitTestEventListener(const UnitTestEventListener&) = delete;
UnitTestEventListener& operator=(const UnitTestEventListener&) = delete;
void InitializeObjects() {
test_network_connection_tracker_ =
network::TestNetworkConnectionTracker::CreateInstance();
SetNetworkConnectionTrackerForTesting(
network::TestNetworkConnectionTracker::GetInstance());
content_clients_ = create_clients_.Run();
CHECK(content_clients_->content_client.get());
SetContentClient(content_clients_->content_client.get());
SetBrowserClientForTesting(content_clients_->content_browser_client.get());
SetUtilityClientForTesting(content_clients_->content_utility_client.get());
browser_accessibility_state_ = BrowserAccessibilityStateImpl::Create();
if (first_test_start_callback_)
std::move(first_test_start_callback_).Run();
}
void OnTestStart(const testing::TestInfo& test_info) override {
InitializeObjects();
}
void OnTestEnd(const testing::TestInfo& test_info) override {
browser_accessibility_state_.reset();
// Don't call SetUtilityClientForTesting or SetBrowserClientForTesting since
// if a test overrode ContentClient it might already be deleted and setting
// these pointers on it would result in a UAF.
SetContentClient(nullptr);
content_clients_.reset();
SetNetworkConnectionTrackerForTesting(nullptr);
test_network_connection_tracker_.reset();
// If the network::NetworkService object was instantiated during a unit test
// it will be deleted because network_service_instance.cc has it in a
// SequenceLocalStorageSlot. However we want to synchronously destruct the
// InterfacePtr pointing to it to avoid it getting the connection error
// later and have other tests use the InterfacePtr that is invalid.
ResetNetworkServiceForTesting();
breadcrumbs::BreadcrumbManager::GetInstance().ResetForTesting();
}
private:
base::RepeatingCallback<std::unique_ptr<UnitTestTestSuite::ContentClients>()>
create_clients_;
base::OnceClosure first_test_start_callback_;
std::unique_ptr<network::TestNetworkConnectionTracker>
test_network_connection_tracker_;
std::unique_ptr<UnitTestTestSuite::ContentClients> content_clients_;
std::unique_ptr<BrowserAccessibilityStateImpl> browser_accessibility_state_;
};
UnitTestTestSuite::ContentClients::ContentClients() = default;
UnitTestTestSuite::ContentClients::~ContentClients() = default;
std::unique_ptr<UnitTestTestSuite::ContentClients>
UnitTestTestSuite::CreateTestContentClients() {
auto clients = std::make_unique<UnitTestTestSuite::ContentClients>();
clients->content_client = std::make_unique<TestContentClient>();
clients->content_browser_client =
std::make_unique<TestContentBrowserClient>();
return clients;
}
static UnitTestTestSuite* g_test_suite = nullptr;
UnitTestTestSuite::UnitTestTestSuite(
base::TestSuite* test_suite,
base::RepeatingCallback<std::unique_ptr<ContentClients>()> create_clients,
std::optional<mojo::core::Configuration> child_mojo_config)
: test_suite_(test_suite), create_clients_(create_clients) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
std::string enabled =
command_line->GetSwitchValueASCII(switches::kEnableFeatures);
std::string disabled =
command_line->GetSwitchValueASCII(switches::kDisableFeatures);
ForceCreateNetworkServiceDirectlyForTesting();
StoragePartitionImpl::ForceInProcessStorageServiceForTesting();
testing::TestEventListeners& listeners =
testing::UnitTest::GetInstance()->listeners();
listeners.Append(CreateTestEventListener());
listeners.Append(new CheckForLeakedWebUIRegistrations);
scoped_feature_list_.InitFromCommandLine(enabled, disabled);
mojo::core::InitFeatures();
if (command_line->HasSwitch(switches::kTestChildProcess)) {
// Note that in the main test process, TestBlinkWebUnitTestSupport
// initializes Mojo; so we only do this in child processes.
mojo::core::Init(child_mojo_config.value_or(mojo::core::Configuration{}));
} else {
mojo::core::Init(mojo::core::Configuration{.is_broker_process = true});
}
DCHECK(test_suite);
test_host_resolver_ = std::make_unique<TestHostResolver>();
g_test_suite = this;
}
UnitTestTestSuite::~UnitTestTestSuite() {
CHECK(g_test_suite == this);
g_test_suite = nullptr;
}
int UnitTestTestSuite::Run() {
#if defined(USE_AURA)
std::unique_ptr<aura::Env> aura_env = aura::Env::CreateInstance();
#endif
std::unique_ptr<url::ScopedSchemeRegistryForTests> scheme_registry;
// TestEventListeners repeater event propagation is disabled in death test
// child process so create and set the clients here for it.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
"gtest_internal_run_death_test")) {
// TestSuite::Initialize hasn't run yet, which is what initializes the
// ResourceBundle. This will be needed by Blink initialization to load
// resources, so do it temporarily here.
ContentTestSuiteBase::InitializeResourceBundle();
CreateTestEventListener()->InitializeObjects();
// Since Blink initialization ended up using the SchemeRegistry, reset
// that it was accessed before testSuite::Initialize registers its schemes.
scheme_registry = std::make_unique<url::ScopedSchemeRegistryForTests>();
ui::ResourceBundle::CleanupSharedInstance();
}
return test_suite_->Run();
}
UnitTestTestSuite::UnitTestEventListener*
UnitTestTestSuite::CreateTestEventListener() {
return new UnitTestEventListener(
create_clients_,
base::BindOnce(&UnitTestTestSuite::OnFirstTestStartComplete,
base::Unretained(this)));
}
void UnitTestTestSuite::OnFirstTestStartComplete() {
// At this point ContentClient and ResourceBundle will be initialized, which
// this needs.
blink_test_support_ = std::make_unique<TestBlinkWebUnitTestSupport>(
TestBlinkWebUnitTestSupport::SchedulerType::kMockScheduler,
" --single-threaded");
// Dummy task runner is initialized because blink::CreateMainThreadIsolate
// needs the current task runner handle and TestBlinkWebUnitTestSupport
// initialized with kMockScheduler doesn't provide one. There should be no
// task posted to this task runner. The message loop is not created before
// this initialization because some tests need specific kinds of message
// loops, and their types are not known upfront. Some tests also create their
// own thread bundles or message loops, and doing the same in
// TestBlinkWebUnitTestSupport would introduce a conflict.
auto dummy_task_runner = base::MakeRefCounted<base::NullTaskRunner>();
auto dummy_task_runner_handle =
std::make_unique<base::SingleThreadTaskRunner::CurrentDefaultHandle>(
dummy_task_runner);
isolate_ = blink::CreateMainThreadIsolate();
}
v8::Isolate* UnitTestTestSuite::MainThreadIsolateForUnitTestSuite() {
CHECK(g_test_suite);
CHECK(g_test_suite->blink_test_support_);
return g_test_suite->isolate_.get();
}
} // namespace content