Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions runtime/dart_isolate_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/mapping.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/thread.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_vm.h"
Expand Down Expand Up @@ -81,4 +83,131 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
ASSERT_EQ(destruction_callback_count, 1u);
}

class AutoIsolateShutdown {
public:
AutoIsolateShutdown(std::shared_ptr<blink::DartIsolate> isolate)
: isolate_(std::move(isolate)) {}

~AutoIsolateShutdown() {
if (isolate_) {
FML_LOG(INFO) << "Shutting down isolate.";
if (!isolate_->Shutdown()) {
FML_LOG(ERROR) << "Could not shutdown isolate.";
}
}
}

bool IsValid() const { return isolate_ != nullptr; }

blink::DartIsolate* get() {
FML_CHECK(isolate_);
return isolate_.get();
}

private:
std::shared_ptr<blink::DartIsolate> isolate_;

FML_DISALLOW_COPY_AND_ASSIGN(AutoIsolateShutdown);
};

std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
fml::RefPtr<fml::TaskRunner> task_runner,
std::string entrypoint) {
Settings settings = {};
settings.task_observer_add = [](intptr_t, fml::closure) {};
settings.task_observer_remove = [](intptr_t) {};

auto vm = DartVM::ForProcess(settings);

if (!vm) {
return {};
}
TaskRunners task_runners(CURRENT_TEST_NAME, //
task_runner, //
task_runner, //
task_runner, //
task_runner //
);

auto weak_isolate = DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
vm->GetSharedSnapshot(), // shared snapshot
std::move(task_runners), // task runners
nullptr, // window
{}, // snapshot delegate
{}, // io manager
"main.dart", // advisory uri
"main" // advisory entrypoint
);

auto root_isolate =
std::make_unique<AutoIsolateShutdown>(weak_isolate.lock());

if (!root_isolate->IsValid()) {
FML_LOG(ERROR) << "Could not create isolate.";
return {};
}

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
FML_LOG(ERROR) << "Created isolate is in unexpected phase.";
return {};
}

auto kernel_file_path =
fml::paths::JoinPaths({testing::GetFixturesPath(), "kernel_blob.bin"});

if (!fml::IsFile(kernel_file_path)) {
FML_LOG(ERROR) << "Could not locate kernel file.";
return {};
}

auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false,
fml::FilePermission::kRead);

if (!kernel_file.is_valid()) {
FML_LOG(ERROR) << "Kernel file descriptor was invalid.";
return {};
}

auto kernel_mapping = std::make_unique<fml::FileMapping>(kernel_file);

if (kernel_mapping->GetMapping() == nullptr) {
FML_LOG(ERROR) << "Could not setup kernel mapping.";
return {};
}

if (!root_isolate->get()->PrepareForRunningFromKernel(
std::move(kernel_mapping))) {
FML_LOG(ERROR)
<< "Could not prepare to run the isolate from the kernel file.";
return {};
}

if (root_isolate->get()->GetPhase() != DartIsolate::Phase::Ready) {
FML_LOG(ERROR) << "Isolate is in unexpected phase.";
return {};
}

if (!root_isolate->get()->Run(entrypoint)) {
FML_LOG(ERROR) << "Could not run the method \"" << entrypoint
<< "\" in the isolate.";
return {};
}

return root_isolate;
}

TEST_F(DartIsolateTest, IsolateCanLoadAndRunDartCode) {
auto isolate = RunDartCodeInIsolate(GetCurrentTaskRunner(), "main");
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
}

TEST_F(DartIsolateTest, IsolateCannotLoadAndRunUnknownDartEntrypoint) {
auto isolate =
RunDartCodeInIsolate(GetCurrentTaskRunner(), "thisShouldNotExist");
ASSERT_FALSE(isolate);
}

} // namespace blink