Flutter Engine
The Flutter Engine
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
5#include "flutter/runtime/dart_vm.h"
6#include "flutter/runtime/dart_vm_lifecycle.h"
7#include "flutter/runtime/platform_isolate_manager.h"
8#include "flutter/testing/fixture_test.h"
9#include "flutter/testing/testing.h"
10
11namespace flutter {
12namespace testing {
13
17 bool is_shutdown = false;
18 bool was_registered = false;
19 explicit IsolateData(PlatformIsolateManager* _mgr) : mgr(_mgr) {}
20};
21
22// The IsolateDataMap is a map from Dart_Isolate to a *vector* of IsolateData,
23// because Dart_Isolates are frequently reused after shutdown, and we want the
24// IsolateData objects to live as long as the map itself. The last element of
25// the vector is always the currently active IsolateData, and the other elements
26// refer to isolates that have been shutdown.
28 std::unordered_map<Dart_Isolate, std::vector<std::unique_ptr<IsolateData>>>;
29
30// Using a thread local isolate data map so that MultithreadedCreation test
31// can avoid using locks while creating isolates on multiple threads. A lock
32// would sync up the threads, so would defeat the purpose of the test.
33static thread_local std::unique_ptr<IsolateDataMap> isolate_data_map_;
34
36 public:
38
39 void TestWithRootIsolate(const std::function<void()>& test) {
40 ASSERT_FALSE(DartVMRef::IsInstanceRunning());
42 auto vm_ref = DartVMRef::Create(settings);
43 ASSERT_TRUE(vm_ref);
44 auto vm_data = vm_ref.GetVMData();
45 ASSERT_TRUE(vm_data);
46
47 TaskRunners task_runners(GetCurrentTestName(), //
52 );
53
54 auto isolate_configuration =
56
57 UIDartState::Context context(task_runners);
58 context.advisory_script_uri = "main.dart";
59 context.advisory_script_entrypoint = "main";
60 auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
61 vm_data->GetSettings(), // settings
62 vm_data->GetIsolateSnapshot(), // isolate snapshot
63 nullptr, // platform configuration
64 DartIsolate::Flags{}, // flags
65 nullptr, // root_isolate_create_callback
66 settings.isolate_create_callback, // isolate create callback
67 settings.isolate_shutdown_callback, // isolate shutdown callback
68 "main", // dart entrypoint
69 std::nullopt, // dart entrypoint library
70 {}, // dart entrypoint arguments
71 std::move(isolate_configuration), // isolate configuration
72 context // engine context
73 );
74 root_isolate_ = weak_isolate.lock()->isolate();
75 ASSERT_TRUE(root_isolate_);
76
77 test();
78
79 Dart_EnterIsolate(root_isolate_);
81 }
82
84 if (isolate_data_map_.get() == nullptr) {
86 }
87
88 IsolateData* isolate_data = new IsolateData(mgr);
89 char* error = nullptr;
90 Dart_Isolate isolate =
91 Dart_CreateIsolateInGroup(root_isolate_, "TestIsolate", OnShutdown,
92 nullptr, isolate_data, &error);
93 isolate_data->isolate = isolate;
94 EXPECT_TRUE(isolate);
96
97 (*isolate_data_map_.get())[isolate].push_back(
98 std::unique_ptr<IsolateData>(isolate_data));
99 isolate_data->was_registered = mgr->RegisterPlatformIsolate(isolate);
100
101 return isolate;
102 }
103
105 EXPECT_EQ(1u, isolate_data_map_.get()->count(isolate));
106 EXPECT_LT(0u, (*isolate_data_map_.get())[isolate].size());
107 return (*isolate_data_map_.get())[isolate].back()->is_shutdown;
108 }
109
111 EXPECT_EQ(1u, isolate_data_map_.get()->count(isolate));
112 EXPECT_LT(0u, (*isolate_data_map_.get())[isolate].size());
113 return (*isolate_data_map_.get())[isolate].back()->was_registered;
114 }
115
116 private:
117 Dart_Isolate root_isolate_ = nullptr;
118
119 static void OnShutdown(void*, void* raw_isolate_data) {
120 IsolateData* isolate_data =
121 reinterpret_cast<IsolateData*>(raw_isolate_data);
122 EXPECT_TRUE(isolate_data->isolate);
123 EXPECT_FALSE(isolate_data->is_shutdown);
124 isolate_data->is_shutdown = true;
125 if (isolate_data->was_registered) {
126 isolate_data->mgr->RemovePlatformIsolate(isolate_data->isolate);
127 }
128 }
129
130 FML_DISALLOW_COPY_AND_ASSIGN(PlatformIsolateManagerTest);
131};
132
134 TestWithRootIsolate([this]() {
136 EXPECT_FALSE(mgr.HasShutdown());
137 EXPECT_FALSE(mgr.HasShutdownMaybeFalseNegative());
138
139 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
140 ASSERT_TRUE(isolateA);
141 EXPECT_FALSE(IsolateIsShutdown(isolateA));
142 EXPECT_TRUE(IsolateWasRegistered(isolateA));
144
145 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
146 ASSERT_TRUE(isolateB);
147 EXPECT_FALSE(IsolateIsShutdown(isolateB));
148 EXPECT_TRUE(IsolateWasRegistered(isolateB));
150
154
155 EXPECT_TRUE(IsolateIsShutdown(isolateA));
156 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
157 EXPECT_TRUE(IsolateIsShutdown(isolateB));
158 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
159 });
160}
161
163 TestWithRootIsolate([this]() {
165 EXPECT_FALSE(mgr.HasShutdown());
166
167 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
168 ASSERT_TRUE(isolateA);
169 EXPECT_FALSE(IsolateIsShutdown(isolateA));
170 EXPECT_TRUE(IsolateWasRegistered(isolateA));
172
173 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
174 ASSERT_TRUE(isolateB);
175 EXPECT_FALSE(IsolateIsShutdown(isolateB));
176 EXPECT_TRUE(IsolateWasRegistered(isolateB));
178
179 Dart_EnterIsolate(isolateA);
181 EXPECT_TRUE(IsolateIsShutdown(isolateA));
182 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
183
184 Dart_EnterIsolate(isolateB);
186 EXPECT_TRUE(IsolateIsShutdown(isolateB));
187 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
188
191
192 EXPECT_TRUE(IsolateIsShutdown(isolateA));
193 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
194 EXPECT_TRUE(IsolateIsShutdown(isolateB));
195 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
196 });
197}
198
199TEST_F(PlatformIsolateManagerTest, RegistrationAfterShutdown) {
200 TestWithRootIsolate([this]() {
202 EXPECT_FALSE(mgr.HasShutdown());
203
204 Dart_Isolate isolateA = CreateAndRegisterIsolate(&mgr);
205 ASSERT_TRUE(isolateA);
206 EXPECT_FALSE(IsolateIsShutdown(isolateA));
207 EXPECT_TRUE(IsolateWasRegistered(isolateA));
209
212
213 EXPECT_TRUE(IsolateIsShutdown(isolateA));
214 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateA));
215
216 Dart_Isolate isolateB = CreateAndRegisterIsolate(&mgr);
217 ASSERT_TRUE(isolateB);
218 EXPECT_FALSE(IsolateIsShutdown(isolateB));
219 EXPECT_FALSE(IsolateWasRegistered(isolateB));
220 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
221
222 Dart_EnterIsolate(isolateB);
224 EXPECT_TRUE(IsolateIsShutdown(isolateB));
225 EXPECT_FALSE(mgr.IsRegisteredForTestingOnly(isolateB));
226 });
227}
228
229TEST_F(PlatformIsolateManagerTest, MultithreadedCreation) {
230 // Try to generate race conditions by creating Isolates on multiple threads,
231 // while shutting down the manager.
232 TestWithRootIsolate([this]() {
234 EXPECT_FALSE(mgr.HasShutdown());
235
236 std::atomic<bool> test_finished = false;
237 std::vector<std::thread> threads;
238 threads.reserve(10);
239 for (int i = 0; i < 10; ++i) {
240 threads.push_back(std::thread([this, &mgr, &test_finished]() {
241 for (int j = 0; j < 100; ++j) {
242 Dart_Isolate isolate = CreateAndRegisterIsolate(&mgr);
243 ASSERT_TRUE(isolate);
244
245 if (!IsolateWasRegistered(isolate)) {
246 Dart_EnterIsolate(isolate);
248 }
249 }
250 while (!test_finished.load()) {
251 // Wait for the test to finish, to avoid prematurely destroying thread
252 // local isolate_data_map_.
253 }
254 }));
255 }
256
259
260 test_finished = true;
261 for (auto& thread : threads) {
262 thread.join();
263 }
264 });
265}
266
267} // namespace testing
268} // namespace flutter
#define test(name)
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)
Creates an instance of a root isolate and returns a weak pointer to the same. The isolate instance ma...
Definition: dart_isolate.cc:90
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()
Definition: dart_fixture.cc:30
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...
Definition: thread_test.cc:22
DART_EXPORT void Dart_ShutdownIsolate(void)
DART_EXPORT Dart_Isolate Dart_CreateIsolateInGroup(Dart_Isolate group_member, const char *name, Dart_IsolateShutdownCallback shutdown_callback, Dart_IsolateCleanupCallback cleanup_callback, void *child_isolate_data, char **error)
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT void Dart_ExitIsolate(void)
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
Definition: fuchsia.cc:51
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:15
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...
Definition: ui_dart_state.h:45
std::string advisory_script_entrypoint
Definition: ui_dart_state.h:93
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678