Flutter Engine
 
Loading...
Searching...
No Matches
platform_isolate_manager_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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
11
12namespace flutter {
13namespace testing {
14
17 Dart_Isolate isolate = nullptr;
18 bool is_shutdown = false;
19 bool was_registered = false;
20 explicit IsolateData(PlatformIsolateManager* _mgr) : mgr(_mgr) {}
21};
22
23// The IsolateDataMap is a map from Dart_Isolate to a *vector* of IsolateData,
24// because Dart_Isolates are frequently reused after shutdown, and we want the
25// IsolateData objects to live as long as the map itself. The last element of
26// the vector is always the currently active IsolateData, and the other elements
27// refer to isolates that have been shutdown.
29 std::unordered_map<Dart_Isolate, std::vector<std::unique_ptr<IsolateData>>>;
30
31// Using a thread local isolate data map so that MultithreadedCreation test
32// can avoid using locks while creating isolates on multiple threads. A lock
33// would sync up the threads, so would defeat the purpose of the test.
34static thread_local std::unique_ptr<IsolateDataMap> isolate_data_map_;
35
37 public:
39
40 void TestWithRootIsolate(const std::function<void()>& test) {
41 ASSERT_FALSE(DartVMRef::IsInstanceRunning());
42 auto settings = CreateSettingsForFixture();
43 auto vm_ref = DartVMRef::Create(settings);
44 ASSERT_TRUE(vm_ref);
45 auto vm_data = vm_ref.GetVMData();
46 ASSERT_TRUE(vm_data);
47
48 TaskRunners task_runners(GetCurrentTestName(), //
53 );
54
55 auto isolate_configuration =
57
58 UIDartState::Context context(task_runners);
59 context.advisory_script_uri = "main.dart";
60 context.advisory_script_entrypoint = "main";
61 auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
62 vm_data->GetSettings(), // settings
63 vm_data->GetIsolateSnapshot(), // isolate snapshot
64 nullptr, // platform configuration
65 DartIsolate::Flags{}, // flags
66 nullptr, // root_isolate_create_callback
67 settings.isolate_create_callback, // isolate create callback
68 settings.isolate_shutdown_callback, // isolate shutdown callback
69 "main", // dart entrypoint
70 std::nullopt, // dart entrypoint library
71 {}, // dart entrypoint arguments
72 std::move(isolate_configuration), // isolate configuration
73 context // engine context
74 );
75 root_isolate_ = weak_isolate.lock()->isolate();
76 ASSERT_TRUE(root_isolate_);
77
78 test();
79
80 Dart_EnterIsolate(root_isolate_);
81 Dart_ShutdownIsolate();
82 }
83
85 if (isolate_data_map_.get() == nullptr) {
87 }
88
89 IsolateData* isolate_data = new IsolateData(mgr);
90 char* error = nullptr;
91 Dart_Isolate isolate =
92 Dart_CreateIsolateInGroup(root_isolate_, "TestIsolate", OnShutdown,
93 nullptr, isolate_data, &error);
94 isolate_data->isolate = isolate;
95 EXPECT_TRUE(isolate);
96 Dart_ExitIsolate();
97
98 (*isolate_data_map_.get())[isolate].push_back(
99 std::unique_ptr<IsolateData>(isolate_data));
100 isolate_data->was_registered = mgr->RegisterPlatformIsolate(isolate);
101
102 return isolate;
103 }
104
105 bool IsolateIsShutdown(Dart_Isolate isolate) {
106 EXPECT_EQ(1u, isolate_data_map_.get()->count(isolate));
107 EXPECT_LT(0u, (*isolate_data_map_.get())[isolate].size());
108 return (*isolate_data_map_.get())[isolate].back()->is_shutdown;
109 }
110
111 bool IsolateWasRegistered(Dart_Isolate isolate) {
112 EXPECT_EQ(1u, isolate_data_map_.get()->count(isolate));
113 EXPECT_LT(0u, (*isolate_data_map_.get())[isolate].size());
114 return (*isolate_data_map_.get())[isolate].back()->was_registered;
115 }
116
117 private:
118 Dart_Isolate root_isolate_ = nullptr;
119
120 static void OnShutdown(void*, void* raw_isolate_data) {
121 IsolateData* isolate_data =
122 reinterpret_cast<IsolateData*>(raw_isolate_data);
123 EXPECT_TRUE(isolate_data->isolate);
124 EXPECT_FALSE(isolate_data->is_shutdown);
125 isolate_data->is_shutdown = true;
126 if (isolate_data->was_registered) {
127 isolate_data->mgr->RemovePlatformIsolate(isolate_data->isolate);
128 }
129 }
130
132};
133
135 TestWithRootIsolate([this]() {
137 EXPECT_FALSE(mgr.HasShutdown());
138 EXPECT_FALSE(mgr.HasShutdownMaybeFalseNegative());
139
140 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
141 ASSERT_TRUE(isolateA);
142 EXPECT_FALSE(IsolateIsShutdown(isolateA));
143 EXPECT_TRUE(IsolateWasRegistered(isolateA));
144 EXPECT_TRUE(mgr.IsRegisteredForTestingOnly(isolateA));
145
146 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
147 ASSERT_TRUE(isolateB);
148 EXPECT_FALSE(IsolateIsShutdown(isolateB));
149 EXPECT_TRUE(IsolateWasRegistered(isolateB));
150 EXPECT_TRUE(mgr.IsRegisteredForTestingOnly(isolateB));
151
153 EXPECT_TRUE(mgr.HasShutdown());
154 EXPECT_TRUE(mgr.HasShutdownMaybeFalseNegative());
155
156 EXPECT_TRUE(IsolateIsShutdown(isolateA));
157 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
158 EXPECT_TRUE(IsolateIsShutdown(isolateB));
159 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
160 });
161}
162
164 TestWithRootIsolate([this]() {
166 EXPECT_FALSE(mgr.HasShutdown());
167
168 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
169 ASSERT_TRUE(isolateA);
170 EXPECT_FALSE(IsolateIsShutdown(isolateA));
171 EXPECT_TRUE(IsolateWasRegistered(isolateA));
172 EXPECT_TRUE(mgr.IsRegisteredForTestingOnly(isolateA));
173
174 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
175 ASSERT_TRUE(isolateB);
176 EXPECT_FALSE(IsolateIsShutdown(isolateB));
177 EXPECT_TRUE(IsolateWasRegistered(isolateB));
178 EXPECT_TRUE(mgr.IsRegisteredForTestingOnly(isolateB));
179
180 Dart_EnterIsolate(isolateA);
181 Dart_ShutdownIsolate();
182 EXPECT_TRUE(IsolateIsShutdown(isolateA));
183 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
184
185 Dart_EnterIsolate(isolateB);
186 Dart_ShutdownIsolate();
187 EXPECT_TRUE(IsolateIsShutdown(isolateB));
188 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
189
191 EXPECT_TRUE(mgr.HasShutdown());
192
193 EXPECT_TRUE(IsolateIsShutdown(isolateA));
194 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
195 EXPECT_TRUE(IsolateIsShutdown(isolateB));
196 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
197 });
198}
199
200TEST_F(PlatformIsolateManagerTest, RegistrationAfterShutdown) {
201 TestWithRootIsolate([this]() {
203 EXPECT_FALSE(mgr.HasShutdown());
204
205 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
206 ASSERT_TRUE(isolateA);
207 EXPECT_FALSE(IsolateIsShutdown(isolateA));
208 EXPECT_TRUE(IsolateWasRegistered(isolateA));
209 EXPECT_TRUE(mgr.IsRegisteredForTestingOnly(isolateA));
210
212 EXPECT_TRUE(mgr.HasShutdown());
213
214 EXPECT_TRUE(IsolateIsShutdown(isolateA));
215 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
216
217 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
218 ASSERT_TRUE(isolateB);
219 EXPECT_FALSE(IsolateIsShutdown(isolateB));
220 EXPECT_FALSE(IsolateWasRegistered(isolateB));
221 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
222
223 Dart_EnterIsolate(isolateB);
224 Dart_ShutdownIsolate();
225 EXPECT_TRUE(IsolateIsShutdown(isolateB));
226 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
227 });
228}
229
230TEST_F(PlatformIsolateManagerTest, MultithreadedCreation) {
231 // Try to generate race conditions by creating Isolates on multiple threads,
232 // while shutting down the manager.
233 TestWithRootIsolate([this]() {
235 EXPECT_FALSE(mgr.HasShutdown());
236
237 std::atomic<bool> test_finished = false;
238 std::vector<std::thread> threads;
239 threads.reserve(10);
240 for (int i = 0; i < 10; ++i) {
241 threads.push_back(std::thread([this, &mgr, &test_finished]() {
242 for (int j = 0; j < 100; ++j) {
243 Dart_Isolate isolate = CreateAndRegisterIsolate(&mgr);
244 ASSERT_TRUE(isolate);
245
246 if (!IsolateWasRegistered(isolate)) {
247 Dart_EnterIsolate(isolate);
248 Dart_ShutdownIsolate();
249 }
250 }
251 while (!test_finished.load()) {
252 // Wait for the test to finish, to avoid prematurely destroying thread
253 // local isolate_data_map_.
254 }
255 }));
256 }
257
259 EXPECT_TRUE(mgr.HasShutdown());
260
261 test_finished = true;
262 for (auto& thread : threads) {
263 thread.join();
264 }
265 });
266}
267
268} // namespace testing
269} // namespace flutter
static std::weak_ptr< DartIsolate > CreateRunningRootIsolate(const Settings &settings, const fml::RefPtr< const DartSnapshot > &isolate_snapshot, std::unique_ptr< PlatformConfiguration > platform_configuration, Flags flags, const fml::closure &root_isolate_create_callback, const fml::closure &isolate_create_callback, const fml::closure &isolate_shutdown_callback, std::optional< std::string > dart_entrypoint, std::optional< std::string > dart_entrypoint_library, const std::vector< std::string > &dart_entrypoint_args, std::unique_ptr< IsolateConfiguration > isolate_configuration, const UIDartState::Context &context, const DartIsolate *spawning_isolate=nullptr, std::shared_ptr< NativeAssetsManager > native_assets_manager=nullptr)
Creates an instance of a root isolate and returns a weak pointer to the same. The isolate instance ma...
static DartVMRef Create(const Settings &settings, fml::RefPtr< const DartSnapshot > vm_snapshot=nullptr, fml::RefPtr< const DartSnapshot > isolate_snapshot=nullptr)
static bool IsInstanceRunning()
static std::unique_ptr< IsolateConfiguration > InferFromSettings(const Settings &settings, const std::shared_ptr< AssetManager > &asset_manager=nullptr, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer the isolate configuration from the Settings object. If the VM is configured for AOT...
void RemovePlatformIsolate(Dart_Isolate isolate)
bool IsRegisteredForTestingOnly(Dart_Isolate isolate)
bool RegisterPlatformIsolate(Dart_Isolate isolate)
virtual Settings CreateSettingsForFixture()
Dart_Isolate CreateAndRegisterIsolate(PlatformIsolateManager *mgr)
void TestWithRootIsolate(const std::function< void()> &test)
fml::RefPtr< fml::TaskRunner > GetCurrentTaskRunner()
Get the task runner for the thread that the current unit-test is running on. This creates a message l...
const uint8_t uint32_t uint32_t GError ** error
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
std::string GetCurrentTestName()
Gets the name of the currently running test. This is useful in generating logs or assets based on tes...
Definition testing.cc:14
TEST_F(DisplayListTest, Defaults)
std::unordered_map< Dart_Isolate, std::vector< std::unique_ptr< IsolateData > > > IsolateDataMap
static thread_local std::unique_ptr< IsolateDataMap > isolate_data_map_
The subset of state which is owned by the shell or engine and passed through the RuntimeController in...