Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b77f509

Browse files
authored
Refactor isolate test (#16933)
Make the test harness reusable for other tests that want to launch a Dart VM
1 parent 59b4d9b commit b77f509

File tree

3 files changed

+265
-203
lines changed

3 files changed

+265
-203
lines changed

runtime/dart_isolate_unittests.cc

Lines changed: 66 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#include "flutter/fml/make_copyable.h"
65
#include "flutter/fml/mapping.h"
7-
#include "flutter/fml/paths.h"
86
#include "flutter/fml/synchronization/count_down_latch.h"
97
#include "flutter/fml/synchronization/waitable_event.h"
108
#include "flutter/fml/thread.h"
119
#include "flutter/runtime/dart_isolate.h"
1210
#include "flutter/runtime/dart_vm.h"
1311
#include "flutter/runtime/dart_vm_lifecycle.h"
1412
#include "flutter/runtime/runtime_test.h"
13+
#include "flutter/testing/dart_isolate_runner.h"
1514
#include "flutter/testing/testing.h"
1615
#include "flutter/testing/thread_test.h"
1716
#include "third_party/tonic/converter/dart_converter.h"
@@ -96,199 +95,18 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
9695
ASSERT_EQ(destruction_callback_count, 1u);
9796
}
9897

99-
class AutoIsolateShutdown {
100-
public:
101-
AutoIsolateShutdown() = default;
102-
103-
AutoIsolateShutdown(std::shared_ptr<DartIsolate> isolate,
104-
fml::RefPtr<fml::TaskRunner> runner)
105-
: isolate_(std::move(isolate)), runner_(std::move(runner)) {}
106-
107-
~AutoIsolateShutdown() {
108-
if (!IsValid()) {
109-
return;
110-
}
111-
fml::AutoResetWaitableEvent latch;
112-
fml::TaskRunner::RunNowOrPostTask(
113-
runner_, [isolate = std::move(isolate_), &latch]() {
114-
if (!isolate->Shutdown()) {
115-
FML_LOG(ERROR) << "Could not shutdown isolate.";
116-
FML_CHECK(false);
117-
}
118-
latch.Signal();
119-
});
120-
latch.Wait();
121-
}
122-
123-
bool IsValid() const { return isolate_ != nullptr && runner_; }
124-
125-
FML_WARN_UNUSED_RESULT
126-
bool RunInIsolateScope(std::function<bool(void)> closure) {
127-
if (!IsValid()) {
128-
return false;
129-
}
130-
131-
bool result = false;
132-
fml::AutoResetWaitableEvent latch;
133-
fml::TaskRunner::RunNowOrPostTask(
134-
runner_, [this, &result, &latch, closure]() {
135-
tonic::DartIsolateScope scope(isolate_->isolate());
136-
tonic::DartApiScope api_scope;
137-
if (closure) {
138-
result = closure();
139-
}
140-
latch.Signal();
141-
});
142-
latch.Wait();
143-
return true;
144-
}
145-
146-
DartIsolate* get() {
147-
FML_CHECK(isolate_);
148-
return isolate_.get();
149-
}
150-
151-
private:
152-
std::shared_ptr<DartIsolate> isolate_;
153-
fml::RefPtr<fml::TaskRunner> runner_;
154-
155-
FML_DISALLOW_COPY_AND_ASSIGN(AutoIsolateShutdown);
156-
};
157-
158-
static void RunDartCodeInIsolate(DartVMRef& vm_ref,
159-
std::unique_ptr<AutoIsolateShutdown>& result,
160-
const Settings& settings,
161-
fml::RefPtr<fml::TaskRunner> task_runner,
162-
std::string entrypoint,
163-
const std::vector<std::string>& args) {
164-
FML_CHECK(task_runner->RunsTasksOnCurrentThread());
165-
166-
if (!vm_ref) {
167-
return;
168-
}
169-
170-
TaskRunners task_runners(GetCurrentTestName(), //
171-
task_runner, //
172-
task_runner, //
173-
task_runner, //
174-
task_runner //
175-
);
176-
177-
auto vm_data = vm_ref.GetVMData();
178-
179-
if (!vm_data) {
180-
return;
181-
}
182-
183-
auto weak_isolate = DartIsolate::CreateRootIsolate(
184-
vm_data->GetSettings(), // settings
185-
vm_data->GetIsolateSnapshot(), // isolate snapshot
186-
std::move(task_runners), // task runners
187-
nullptr, // window
188-
{}, // snapshot delegate
189-
{}, // io manager
190-
{}, // unref queue
191-
{}, // image decoder
192-
"main.dart", // advisory uri
193-
"main", // advisory entrypoint
194-
nullptr, // flags
195-
settings.isolate_create_callback, // isolate create callback
196-
settings.isolate_shutdown_callback // isolate shutdown callback
197-
);
198-
199-
auto root_isolate =
200-
std::make_unique<AutoIsolateShutdown>(weak_isolate.lock(), task_runner);
201-
202-
if (!root_isolate->IsValid()) {
203-
FML_LOG(ERROR) << "Could not create isolate.";
204-
return;
205-
}
206-
207-
if (root_isolate->get()->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
208-
FML_LOG(ERROR) << "Created isolate is in unexpected phase.";
209-
return;
210-
}
211-
212-
if (!DartVM::IsRunningPrecompiledCode()) {
213-
auto kernel_file_path =
214-
fml::paths::JoinPaths({GetFixturesPath(), "kernel_blob.bin"});
215-
216-
if (!fml::IsFile(kernel_file_path)) {
217-
FML_LOG(ERROR) << "Could not locate kernel file.";
218-
return;
219-
}
220-
221-
auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false,
222-
fml::FilePermission::kRead);
223-
224-
if (!kernel_file.is_valid()) {
225-
FML_LOG(ERROR) << "Kernel file descriptor was invalid.";
226-
return;
227-
}
228-
229-
auto kernel_mapping = std::make_unique<fml::FileMapping>(kernel_file);
230-
231-
if (kernel_mapping->GetMapping() == nullptr) {
232-
FML_LOG(ERROR) << "Could not setup kernel mapping.";
233-
return;
234-
}
235-
236-
if (!root_isolate->get()->PrepareForRunningFromKernel(
237-
std::move(kernel_mapping))) {
238-
FML_LOG(ERROR)
239-
<< "Could not prepare to run the isolate from the kernel file.";
240-
return;
241-
}
242-
} else {
243-
if (!root_isolate->get()->PrepareForRunningFromPrecompiledCode()) {
244-
FML_LOG(ERROR)
245-
<< "Could not prepare to run the isolate from precompiled code.";
246-
return;
247-
}
248-
}
249-
250-
if (root_isolate->get()->GetPhase() != DartIsolate::Phase::Ready) {
251-
FML_LOG(ERROR) << "Isolate is in unexpected phase.";
252-
return;
253-
}
254-
255-
if (!root_isolate->get()->Run(entrypoint, args,
256-
settings.root_isolate_create_callback)) {
257-
FML_LOG(ERROR) << "Could not run the method \"" << entrypoint
258-
<< "\" in the isolate.";
259-
return;
260-
}
261-
262-
root_isolate->get()->AddIsolateShutdownCallback(
263-
settings.root_isolate_shutdown_callback);
264-
265-
result = std::move(root_isolate);
266-
}
267-
268-
static std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
269-
DartVMRef& vm_ref,
270-
const Settings& settings,
271-
fml::RefPtr<fml::TaskRunner> task_runner,
272-
std::string entrypoint,
273-
const std::vector<std::string>& args) {
274-
std::unique_ptr<AutoIsolateShutdown> result;
275-
fml::AutoResetWaitableEvent latch;
276-
fml::TaskRunner::RunNowOrPostTask(
277-
task_runner, fml::MakeCopyable([&]() mutable {
278-
RunDartCodeInIsolate(vm_ref, result, settings, task_runner, entrypoint,
279-
args);
280-
latch.Signal();
281-
}));
282-
latch.Wait();
283-
return result;
284-
}
285-
28698
TEST_F(DartIsolateTest, IsolateCanLoadAndRunDartCode) {
28799
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
288100
const auto settings = CreateSettingsForFixture();
289101
auto vm_ref = DartVMRef::Create(settings);
290-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
291-
"main", {});
102+
TaskRunners task_runners(GetCurrentTestName(), //
103+
GetCurrentTaskRunner(), //
104+
GetCurrentTaskRunner(), //
105+
GetCurrentTaskRunner(), //
106+
GetCurrentTaskRunner() //
107+
);
108+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
109+
{}, GetFixturesPath());
292110
ASSERT_TRUE(isolate);
293111
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
294112
}
@@ -297,17 +115,30 @@ TEST_F(DartIsolateTest, IsolateCannotLoadAndRunUnknownDartEntrypoint) {
297115
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
298116
const auto settings = CreateSettingsForFixture();
299117
auto vm_ref = DartVMRef::Create(settings);
300-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
301-
"thisShouldNotExist", {});
118+
TaskRunners task_runners(GetCurrentTestName(), //
119+
GetCurrentTaskRunner(), //
120+
GetCurrentTaskRunner(), //
121+
GetCurrentTaskRunner(), //
122+
GetCurrentTaskRunner() //
123+
);
124+
auto isolate =
125+
RunDartCodeInIsolate(vm_ref, settings, task_runners, "thisShouldNotExist",
126+
{}, GetFixturesPath());
302127
ASSERT_FALSE(isolate);
303128
}
304129

305130
TEST_F(DartIsolateTest, CanRunDartCodeCodeSynchronously) {
306131
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
307132
const auto settings = CreateSettingsForFixture();
308133
auto vm_ref = DartVMRef::Create(settings);
309-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
310-
"main", {});
134+
TaskRunners task_runners(GetCurrentTestName(), //
135+
GetCurrentTaskRunner(), //
136+
GetCurrentTaskRunner(), //
137+
GetCurrentTaskRunner(), //
138+
GetCurrentTaskRunner() //
139+
);
140+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
141+
{}, GetFixturesPath());
311142

312143
ASSERT_TRUE(isolate);
313144
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
@@ -330,8 +161,16 @@ TEST_F(DartIsolateTest, CanRegisterNativeCallback) {
330161
})));
331162
const auto settings = CreateSettingsForFixture();
332163
auto vm_ref = DartVMRef::Create(settings);
333-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, CreateNewThread(),
334-
"canRegisterNativeCallback", {});
164+
auto thread = CreateNewThread();
165+
TaskRunners task_runners(GetCurrentTestName(), //
166+
thread, //
167+
thread, //
168+
thread, //
169+
thread //
170+
);
171+
auto isolate =
172+
RunDartCodeInIsolate(vm_ref, settings, task_runners,
173+
"canRegisterNativeCallback", {}, GetFixturesPath());
335174
ASSERT_TRUE(isolate);
336175
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
337176
latch.Wait();
@@ -353,8 +192,16 @@ TEST_F(DartIsolateTest, CanSaveCompilationTrace) {
353192

354193
const auto settings = CreateSettingsForFixture();
355194
auto vm_ref = DartVMRef::Create(settings);
356-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, CreateNewThread(),
357-
"testCanSaveCompilationTrace", {});
195+
auto thread = CreateNewThread();
196+
TaskRunners task_runners(GetCurrentTestName(), //
197+
thread, //
198+
thread, //
199+
thread, //
200+
thread //
201+
);
202+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
203+
"testCanSaveCompilationTrace", {},
204+
GetFixturesPath());
358205
ASSERT_TRUE(isolate);
359206
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
360207

@@ -384,8 +231,16 @@ TEST_F(DartIsolateTest, CanLaunchSecondaryIsolates) {
384231
child_shutdown_latch.Signal();
385232
};
386233
auto vm_ref = DartVMRef::Create(settings);
387-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, CreateNewThread(),
388-
"testCanLaunchSecondaryIsolate", {});
234+
auto thread = CreateNewThread();
235+
TaskRunners task_runners(GetCurrentTestName(), //
236+
thread, //
237+
thread, //
238+
thread, //
239+
thread //
240+
);
241+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
242+
"testCanLaunchSecondaryIsolate", {},
243+
GetFixturesPath());
389244
ASSERT_TRUE(isolate);
390245
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
391246
child_shutdown_latch.Wait(); // wait for child isolate to shutdown first
@@ -405,8 +260,16 @@ TEST_F(DartIsolateTest, CanRecieveArguments) {
405260

406261
const auto settings = CreateSettingsForFixture();
407262
auto vm_ref = DartVMRef::Create(settings);
408-
auto isolate = RunDartCodeInIsolate(vm_ref, settings, CreateNewThread(),
409-
"testCanRecieveArguments", {"arg1"});
263+
auto thread = CreateNewThread();
264+
TaskRunners task_runners(GetCurrentTestName(), //
265+
thread, //
266+
thread, //
267+
thread, //
268+
thread //
269+
);
270+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
271+
"testCanRecieveArguments", {"arg1"},
272+
GetFixturesPath());
410273
ASSERT_TRUE(isolate);
411274
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
412275

testing/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ source_set("dart") {
4343
testonly = true
4444

4545
sources = [
46+
"dart_isolate_runner.h",
4647
"elf_loader.cc",
4748
"elf_loader.h",
4849
"test_dart_native_resolver.cc",

0 commit comments

Comments
 (0)