未验证 提交 dffe3fb2 编写于 作者: C Chinmay Garde 提交者: GitHub

Isolate and move common portable ELF loading from fixtures into //flutter/testing. (#16305)

Also update all known test harnesses to use this and fixes the broken shell_unittests harness.

Fixes https://github.com/flutter/flutter/issues/49853
上级 7c95cdad
......@@ -147,7 +147,6 @@ source_set("runtime_unittests_common") {
"$flutter_root/shell/common",
"$flutter_root/testing:dart",
"$flutter_root/third_party/tonic",
"//third_party/dart/runtime/bin:elf_loader",
"//third_party/skia",
]
}
......
......@@ -4,65 +4,18 @@
#include "flutter/runtime/runtime_test.h"
#include "flutter/fml/file.h"
#include "flutter/fml/native_library.h"
#include "flutter/fml/paths.h"
#include "flutter/runtime/dart_snapshot.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/testing/testing.h"
namespace flutter {
namespace testing {
static constexpr const char* kAOTAppELFFileName = "app_elf_snapshot.so";
static ELFAOTSymbols LoadELFIfNecessary() {
if (!DartVM::IsRunningPrecompiledCode()) {
return {};
}
const auto elf_path =
fml::paths::JoinPaths({GetFixturesPath(), kAOTAppELFFileName});
if (!fml::IsFile(elf_path)) {
FML_LOG(ERROR) << "App AOT file does not exist for this fixture. Attempts "
"to launch the Dart VM will fail.";
return {};
}
ELFAOTSymbols symbols;
// Must not be freed.
const char* error = nullptr;
auto loaded_elf =
Dart_LoadELF(elf_path.c_str(), // file path
0, // file offset
&error, // error (out)
&symbols.vm_snapshot_data, // vm snapshot data (out)
&symbols.vm_snapshot_instrs, // vm snapshot instrs (out)
&symbols.vm_isolate_data, // vm isolate data (out)
&symbols.vm_isolate_instrs // vm isolate instr (out)
);
if (loaded_elf == nullptr) {
FML_LOG(ERROR) << "Could not fetch AOT symbols from loaded ELF. Attempts "
"to launch the Dart VM will fail. Error: "
<< error;
return {};
}
symbols.loaded_elf.reset(loaded_elf);
return symbols;
}
RuntimeTest::RuntimeTest()
: native_resolver_(std::make_shared<TestDartNativeResolver>()),
assets_dir_(fml::OpenDirectory(GetFixturesPath(),
false,
fml::FilePermission::kRead)),
aot_symbols_(LoadELFIfNecessary()) {}
aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {}
void RuntimeTest::SetSnapshotsAndAssets(Settings& settings) {
if (!assets_dir_.is_valid()) {
......@@ -75,22 +28,7 @@ void RuntimeTest::SetSnapshotsAndAssets(Settings& settings) {
// don't need to be explicitly supplied by the embedder. In AOT, these
// snapshots will be present in the application AOT dylib.
if (DartVM::IsRunningPrecompiledCode()) {
settings.vm_snapshot_data = [&]() {
return std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_snapshot_data, 0u);
};
settings.isolate_snapshot_data = [&]() {
return std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_isolate_data, 0u);
};
settings.vm_snapshot_instr = [&]() {
return std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_snapshot_instrs, 0u);
};
settings.isolate_snapshot_instr = [&]() {
return std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_isolate_instrs, 0u);
};
PrepareSettingsForAOTWithSymbols(settings, aot_symbols_);
} else {
settings.application_kernels = [this]() {
std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
......
......@@ -9,27 +9,13 @@
#include "flutter/common/settings.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/elf_loader.h"
#include "flutter/testing/test_dart_native_resolver.h"
#include "flutter/testing/thread_test.h"
#include "third_party/dart/runtime/bin/elf_loader.h"
namespace flutter {
namespace testing {
struct LoadedELFDeleter {
void operator()(Dart_LoadedElf* elf) { Dart_UnloadELF(elf); }
};
using UniqueLoadedELF = std::unique_ptr<Dart_LoadedElf, LoadedELFDeleter>;
struct ELFAOTSymbols {
UniqueLoadedELF loaded_elf;
const uint8_t* vm_snapshot_data = nullptr;
const uint8_t* vm_snapshot_instrs = nullptr;
const uint8_t* vm_isolate_data = nullptr;
const uint8_t* vm_isolate_instrs = nullptr;
};
class RuntimeTest : public ThreadTest {
public:
RuntimeTest();
......
......@@ -25,7 +25,8 @@ ShellTest::ShellTest()
ThreadHost::Type::UI | ThreadHost::Type::GPU),
assets_dir_(fml::OpenDirectory(GetFixturesPath(),
false,
fml::FilePermission::kRead)) {}
fml::FilePermission::kRead)),
aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {}
void ShellTest::SendEnginePlatformMessage(
Shell* shell,
......@@ -52,26 +53,7 @@ void ShellTest::SetSnapshotsAndAssets(Settings& settings) {
// In JIT execution, all snapshots are present within the binary itself and
// don't need to be explicitly suppiled by the embedder.
if (DartVM::IsRunningPrecompiledCode()) {
settings.vm_snapshot_data = [this]() {
return fml::FileMapping::CreateReadOnly(assets_dir_, "vm_snapshot_data");
};
settings.isolate_snapshot_data = [this]() {
return fml::FileMapping::CreateReadOnly(assets_dir_,
"isolate_snapshot_data");
};
if (DartVM::IsRunningPrecompiledCode()) {
settings.vm_snapshot_instr = [this]() {
return fml::FileMapping::CreateReadExecute(assets_dir_,
"vm_snapshot_instr");
};
settings.isolate_snapshot_instr = [this]() {
return fml::FileMapping::CreateReadExecute(assets_dir_,
"isolate_snapshot_instr");
};
}
PrepareSettingsForAOTWithSymbols(settings, aot_symbols_);
} else {
settings.application_kernels = [this]() {
std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
......
......@@ -16,6 +16,7 @@
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/common/vsync_waiters_test.h"
#include "flutter/testing/elf_loader.h"
#include "flutter/testing/test_dart_native_resolver.h"
#include "flutter/testing/thread_test.h"
......@@ -84,6 +85,7 @@ class ShellTest : public ThreadTest {
std::shared_ptr<TestDartNativeResolver> native_resolver_;
ThreadHost thread_host_;
fml::UniqueFD assets_dir_;
ELFAOTSymbols aot_symbols_;
FML_DISALLOW_COPY_AND_ASSIGN(ShellTest);
};
......
......@@ -136,7 +136,6 @@ if (current_toolchain == host_toolchain) {
"$flutter_root/testing:opengl",
"$flutter_root/testing:skia",
"$flutter_root/third_party/tonic",
"//third_party/dart/runtime/bin:elf_loader",
"//third_party/skia",
]
}
......
......@@ -14,10 +14,9 @@
namespace flutter {
namespace testing {
static constexpr const char* kAppAOTELFFileName = "app_elf_snapshot.so";
EmbedderTestContext::EmbedderTestContext(std::string assets_path)
: assets_path_(std::move(assets_path)),
aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()),
native_resolver_(std::make_shared<TestDartNativeResolver>()) {
SetupAOTMappingsIfNecessary();
isolate_create_callbacks_.push_back(
......@@ -29,63 +28,20 @@ EmbedderTestContext::EmbedderTestContext(std::string assets_path)
});
}
EmbedderTestContext::~EmbedderTestContext() {
vm_snapshot_data_.reset();
vm_snapshot_instructions_.reset();
isolate_snapshot_data_.reset();
isolate_snapshot_instructions_.reset();
if (elf_library_handle_ != nullptr) {
Dart_UnloadELF(elf_library_handle_);
}
}
EmbedderTestContext::~EmbedderTestContext() = default;
void EmbedderTestContext::SetupAOTMappingsIfNecessary() {
if (!DartVM::IsRunningPrecompiledCode()) {
// Not in AOT mode. Nothing to do.
return;
}
auto elf_path = fml::paths::JoinPaths({assets_path_, kAppAOTELFFileName});
if (!fml::IsFile(elf_path.c_str())) {
FML_LOG(ERROR) << "Could not find the applications AOT ELF file in an "
"AOT environment. Engine launches attempted with this "
"context will fail. File not found: "
<< elf_path;
return;
}
const uint8_t* vm_snapshot_data = nullptr;
const uint8_t* vm_snapshot_instructions = nullptr;
const uint8_t* isolate_snapshot_data = nullptr;
const uint8_t* isolate_snapshot_instructions = nullptr;
const char* error = nullptr;
elf_library_handle_ =
Dart_LoadELF(elf_path.c_str(), // filename
0u, // file offset
&error, // error (must not be freed)
&vm_snapshot_data, // VM snapshot data
&vm_snapshot_instructions, // VM snapshot instructions
&isolate_snapshot_data, // VM isolate data
&isolate_snapshot_instructions // VM isolate instructions
);
if (elf_library_handle_ == nullptr) {
FML_LOG(ERROR) << "Could not load snapshot in an AOT environment. Engine "
"launches attempted with this context will fail. Error: "
<< error;
return;
}
vm_snapshot_data_.reset(new fml::NonOwnedMapping(vm_snapshot_data, 0));
vm_snapshot_instructions_.reset(
new fml::NonOwnedMapping(vm_snapshot_instructions, 0));
isolate_snapshot_data_.reset(
new fml::NonOwnedMapping(isolate_snapshot_data, 0));
isolate_snapshot_instructions_.reset(
new fml::NonOwnedMapping(isolate_snapshot_instructions, 0));
vm_snapshot_data_ =
std::make_unique<fml::NonOwnedMapping>(aot_symbols_.vm_snapshot_data, 0u);
vm_snapshot_instructions_ = std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_snapshot_instrs, 0u);
isolate_snapshot_data_ =
std::make_unique<fml::NonOwnedMapping>(aot_symbols_.vm_isolate_data, 0u);
isolate_snapshot_instructions_ = std::make_unique<fml::NonOwnedMapping>(
aot_symbols_.vm_isolate_instrs, 0u);
}
const std::string& EmbedderTestContext::GetAssetsPath() const {
......
......@@ -16,9 +16,9 @@
#include "flutter/fml/mapping.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/tests/embedder_test_compositor.h"
#include "flutter/testing/elf_loader.h"
#include "flutter/testing/test_dart_native_resolver.h"
#include "flutter/testing/test_gl_surface.h"
#include "third_party/dart/runtime/bin/elf_loader.h"
#include "third_party/skia/include/core/SkImage.h"
namespace flutter {
......@@ -74,9 +74,7 @@ class EmbedderTestContext {
using NextSceneCallback = std::function<void(sk_sp<SkImage> image)>;
std::string assets_path_;
// Pieces of the Dart snapshot in ELF form, loaded by Dart's ELF library.
Dart_LoadedElf* elf_library_handle_ = nullptr;
ELFAOTSymbols aot_symbols_;
std::unique_ptr<fml::Mapping> vm_snapshot_data_;
std::unique_ptr<fml::Mapping> vm_snapshot_instructions_;
std::unique_ptr<fml::Mapping> isolate_snapshot_data_;
......
......@@ -9,11 +9,11 @@ source_set("testing_lib") {
testonly = true
sources = [
"$flutter_root/testing/assertions.h",
"$flutter_root/testing/testing.cc",
"$flutter_root/testing/testing.h",
"$flutter_root/testing/thread_test.cc",
"$flutter_root/testing/thread_test.h",
"assertions.h",
"testing.cc",
"testing.h",
"thread_test.cc",
"thread_test.h",
]
public_deps = [
......@@ -27,7 +27,7 @@ source_set("testing") {
testonly = true
sources = [
"$flutter_root/testing/run_all_unittests.cc",
"run_all_unittests.cc",
]
public_deps = [
......@@ -39,14 +39,21 @@ source_set("dart") {
testonly = true
sources = [
"$flutter_root/testing/test_dart_native_resolver.cc",
"$flutter_root/testing/test_dart_native_resolver.h",
"elf_loader.cc",
"elf_loader.h",
"test_dart_native_resolver.cc",
"test_dart_native_resolver.h",
]
public_deps = [
":testing",
"$flutter_root/common",
"$flutter_root/fml",
"$flutter_root/runtime",
"$flutter_root/runtime:libdart",
"$flutter_root/third_party/tonic",
"//third_party/dart/runtime/bin:elf_loader",
"//third_party/skia",
]
}
......@@ -54,11 +61,11 @@ source_set("skia") {
testonly = true
sources = [
"$flutter_root/testing/assertions_skia.cc",
"$flutter_root/testing/assertions_skia.h",
"$flutter_root/testing/canvas_test.h",
"$flutter_root/testing/mock_canvas.cc",
"$flutter_root/testing/mock_canvas.h",
"assertions_skia.cc",
"assertions_skia.h",
"canvas_test.h",
"mock_canvas.cc",
"mock_canvas.h",
]
public_deps = [
......@@ -74,8 +81,8 @@ if (current_toolchain == host_toolchain) {
configs += [ "//third_party/swiftshader_flutter:swiftshader_config" ]
sources = [
"$flutter_root/testing/test_gl_surface.cc",
"$flutter_root/testing/test_gl_surface.h",
"test_gl_surface.cc",
"test_gl_surface.h",
]
deps = [
......@@ -95,14 +102,14 @@ if (current_toolchain == host_toolchain) {
testonly = true
sources = [
"$flutter_root/testing/test_metal_surface.cc",
"$flutter_root/testing/test_metal_surface.h",
"test_metal_surface.cc",
"test_metal_surface.h",
]
defines = []
if (shell_enable_metal) {
sources += [ "$flutter_root/testing/test_metal_surface_impl.mm" ]
sources += [ "test_metal_surface_impl.mm" ]
defines += [ "TESTING_ENABLE_METAL" ]
}
......
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/testing/elf_loader.h"
#include "flutter/fml/file.h"
#include "flutter/fml/paths.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/testing/testing.h"
namespace flutter {
namespace testing {
static constexpr const char* kAOTAppELFFileName = "app_elf_snapshot.so";
ELFAOTSymbols LoadELFSymbolFromFixturesIfNeccessary() {
if (!DartVM::IsRunningPrecompiledCode()) {
return {};
}
const auto elf_path =
fml::paths::JoinPaths({GetFixturesPath(), kAOTAppELFFileName});
if (!fml::IsFile(elf_path)) {
FML_LOG(ERROR) << "App AOT file does not exist for this fixture. Attempts "
"to launch the Dart VM with these AOT symbols will fail.";
return {};
}
ELFAOTSymbols symbols;
// Must not be freed.
const char* error = nullptr;
auto loaded_elf =
Dart_LoadELF(elf_path.c_str(), // file path
0, // file offset
&error, // error (out)
&symbols.vm_snapshot_data, // vm snapshot data (out)
&symbols.vm_snapshot_instrs, // vm snapshot instrs (out)
&symbols.vm_isolate_data, // vm isolate data (out)
&symbols.vm_isolate_instrs // vm isolate instr (out)
);
if (loaded_elf == nullptr) {
FML_LOG(ERROR)
<< "Could not fetch AOT symbols from loaded ELF. Attempts "
"to launch the Dart VM with these AOT symbols will fail. Error: "
<< error;
return {};
}
symbols.loaded_elf.reset(loaded_elf);
return symbols;
}
bool PrepareSettingsForAOTWithSymbols(Settings& settings,
const ELFAOTSymbols& symbols) {
if (!DartVM::IsRunningPrecompiledCode()) {
return false;
}
settings.vm_snapshot_data = [&]() {
return std::make_unique<fml::NonOwnedMapping>(symbols.vm_snapshot_data, 0u);
};
settings.isolate_snapshot_data = [&]() {
return std::make_unique<fml::NonOwnedMapping>(symbols.vm_isolate_data, 0u);
};
settings.vm_snapshot_instr = [&]() {
return std::make_unique<fml::NonOwnedMapping>(symbols.vm_snapshot_instrs,
0u);
};
settings.isolate_snapshot_instr = [&]() {
return std::make_unique<fml::NonOwnedMapping>(symbols.vm_isolate_instrs,
0u);
};
return true;
}
} // namespace testing
} // namespace flutter
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_TESTING_ELF_LOADER_H_
#define FLUTTER_TESTING_ELF_LOADER_H_
#include <memory>
#include "flutter/common/settings.h"
#include "flutter/fml/macros.h"
#include "third_party/dart/runtime/bin/elf_loader.h"
namespace flutter {
namespace testing {
struct LoadedELFDeleter {
void operator()(Dart_LoadedElf* elf) { ::Dart_UnloadELF(elf); }
};
using UniqueLoadedELF = std::unique_ptr<Dart_LoadedElf, LoadedELFDeleter>;
struct ELFAOTSymbols {
UniqueLoadedELF loaded_elf;
const uint8_t* vm_snapshot_data = nullptr;
const uint8_t* vm_snapshot_instrs = nullptr;
const uint8_t* vm_isolate_data = nullptr;
const uint8_t* vm_isolate_instrs = nullptr;
};
//------------------------------------------------------------------------------
/// @brief Attempts to resolve AOT symbols from the portable ELF loader.
/// This location is automatically resolved from the fixtures
/// generator. This only returns valid symbols when the VM is
/// configured for AOT.
///
/// @return The loaded ELF symbols.
///
ELFAOTSymbols LoadELFSymbolFromFixturesIfNeccessary();
//------------------------------------------------------------------------------
/// @brief Prepare the settings objects various AOT mappings resolvers with
/// the symbols already loaded. This method does nothing in non-AOT
/// runtime modes.
///
/// @warning The symbols must not be collected till all shell instantiations
/// made using the settings object are collected.
///
/// @param[in/out] settings The settings whose AOT resolvers to populate.
/// @param[in] symbols The symbols used to populate the settings object.
///
/// @return If the settings object was correctly updated.
///
bool PrepareSettingsForAOTWithSymbols(Settings& settings,
const ELFAOTSymbols& symbols);
} // namespace testing
} // namespace flutter
#endif // FLUTTER_TESTING_ELF_LOADER_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册